SSP_LPC18xx.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034
  1. /* --------------------------------------------------------------------------
  2. * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * $Date: 13. March 2016
  19. * $Revision: V2.8
  20. *
  21. * Driver: Driver_SPI0, Driver_SPI1
  22. * Configured: via RTE_Device.h configuration file
  23. * Project: SPI (SSP used for SPI) Driver for NXP LPC18xx
  24. * --------------------------------------------------------------------------
  25. * Use the following configuration settings in the middleware component
  26. * to connect to this driver.
  27. *
  28. * Configuration Setting Value SPI Interface
  29. * --------------------- ----- -------------
  30. * Connect to hardware via Driver_SPI# = 0 use SPI0 (SSP0)
  31. * Connect to hardware via Driver_SPI# = 1 use SPI1 (SSP1)
  32. * -------------------------------------------------------------------------- */
  33. /* History:
  34. * Version 2.8
  35. * - Corrected Pin Configuration and Unconfiguration
  36. * Version 2.7
  37. * - Driver update to work with GPDMA_LPC18xx ver.: 1.3
  38. * Version 2.6
  39. * - Corrected Bus Speed configuration
  40. * - Corrected PowerControl function for conditional Power full (driver must be initialized)
  41. * Version 2.5
  42. * - PowerControl for Power OFF and Uninitialize functions made unconditional.
  43. * - Corrected status bit-field handling, to prevent race conditions.
  44. * - Corrected ARM_SPI_EVENT_DATA_LOST event handling in slave mode
  45. * Version 2.4
  46. * - Corrected ssp->info->mode and pin handling
  47. * Version 2.3
  48. * - Updated Control functions
  49. * - GPDMA initialization and uninitialization
  50. * Version 2.2
  51. * - Updated Send and Receive functions to avoid stack corruption
  52. * Version 2.1
  53. * - Added DMA support
  54. * Version 2.0
  55. * - Initial CMSIS Driver API V2.00 release
  56. */
  57. #include <string.h>
  58. #include "SCU_LPC18xx.h"
  59. #include "GPIO_LPC18xx.h"
  60. #include "GPDMA_LPC18xx.h"
  61. #include "SSP_LPC18xx.h"
  62. #include "Driver_SPI.h"
  63. #include "RTE_Device.h"
  64. #include "RTE_Components.h"
  65. extern uint32_t GetClockFreq (uint32_t clk_src);
  66. void SSP0_GPDMA_Tx_SignalEvent (uint32_t event);
  67. void SSP0_GPDMA_Rx_SignalEvent (uint32_t event);
  68. void SSP1_GPDMA_Tx_SignalEvent (uint32_t event);
  69. void SSP1_GPDMA_Rx_SignalEvent (uint32_t event);
  70. #define ARM_SPI_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2,8) // driver version
  71. #if ((defined(RTE_Drivers_SPI0) || defined(RTE_Drivers_SPI1)) && (!RTE_SSP0) && (!RTE_SSP1))
  72. #error "SSP not configured in RTE_Device.h!"
  73. #endif
  74. #if ((RTE_SSP0) && \
  75. ((RTE_SSP0_DMA_TX_EN && !RTE_SSP0_DMA_RX_EN) || \
  76. (RTE_SSP0_DMA_RX_EN && !RTE_SSP0_DMA_TX_EN)))
  77. #error "Both Tx and Rx DMA for SSP0 have to be enabled or disabled in RTE_Device.h!"
  78. #endif
  79. #if ((RTE_SSP1) && \
  80. ((RTE_SSP1_DMA_TX_EN && !RTE_SSP1_DMA_RX_EN) || \
  81. (RTE_SSP1_DMA_RX_EN && !RTE_SSP1_DMA_TX_EN)))
  82. #error "Both Tx and Rx DMA for SSP1 have to be enabled or disabled in RTE_Device.h!"
  83. #endif
  84. // Driver Version
  85. static const ARM_DRIVER_VERSION DriverVersion = {
  86. ARM_SPI_API_VERSION,
  87. ARM_SPI_DRV_VERSION
  88. };
  89. // Driver Capabilities
  90. static const ARM_SPI_CAPABILITIES DriverCapabilities = {
  91. 0, // Simplex Mode (Master and Slave)
  92. 1, // TI Synchronous Serial Interface
  93. 1, // Microwire Interface
  94. 0 // Signal Mode Fault event: \ref ARM_SPI_EVENT_MODE_FAULT
  95. };
  96. #if (RTE_SSP0)
  97. static SSP_INFO SSP0_Info = { 0 };
  98. static SSP_TRANSFER_INFO SSP0_Xfer;
  99. static PIN_ID SSP0_pin_sck = { RTE_SSP0_SCK_PORT, RTE_SSP0_SCK_BIT, RTE_SSP0_SCK_FUNC };
  100. static PIN_ID SSP0_pin_miso = { RTE_SSP0_MISO_PORT, RTE_SSP0_MISO_BIT, RTE_SSP0_MISO_FUNC};
  101. static PIN_ID SSP0_pin_mosi = { RTE_SSP0_MOSI_PORT, RTE_SSP0_MOSI_BIT, RTE_SSP0_MOSI_FUNC};
  102. #if (RTE_SSP0_SSEL_PIN_EN == 1U)
  103. static PIN_ID SSP0_pin_ssel = { RTE_SSP0_SSEL_PORT, RTE_SSP0_SSEL_BIT, RTE_SSP0_SSEL_FUNC };
  104. static GPIO_ID SSP0_gpio_ssel = { RTE_SSP0_SSEL_GPIO_PORT, RTE_SSP0_SSEL_GPIO_BIT};
  105. #endif
  106. static SSP_RESOURCES SSP0_Resources = {
  107. LPC_SSP0,
  108. { &SSP0_pin_sck,
  109. &SSP0_pin_miso,
  110. &SSP0_pin_mosi,
  111. #if (RTE_SSP0_SSEL_PIN_EN == 1U)
  112. &SSP0_pin_ssel,
  113. &SSP0_gpio_ssel,
  114. RTE_SSP0_SSEL_GPIO_FUNC,
  115. #else
  116. NULL,
  117. NULL,
  118. 0,
  119. #endif
  120. },
  121. { CGU_BASE_SSPx_CLK_AUTOBLOCK | ((CLK_SRC_PLL1 << 24) & CGU_BASE_SSPx_CLK_CLK_SEL),
  122. &(LPC_CGU->BASE_SSP0_CLK),
  123. CCU1_CLK_M3_SSPx_CFG_AUTO | CCU1_CLK_M3_SSPx_CFG_RUN,
  124. &(LPC_CCU1->CLK_M3_SSP0_CFG),
  125. CCU1_CLK_M3_SSPx_STAT_RUN,
  126. &(LPC_CCU1->CLK_M3_SSP0_STAT) },
  127. { RGU_RESET_CTRL1_SSP0_RST,
  128. &(LPC_RGU->RESET_CTRL1),
  129. RGU_RESET_ACTIVE_STATUS1_SSP0_RST,
  130. &(LPC_RGU->RESET_ACTIVE_STATUS1) },
  131. { RTE_SSP0_DMA_TX_EN,
  132. RTE_SSP0_DMA_TX_CH,
  133. RTE_SSP0_DMA_TX_PERI,
  134. RTE_SSP0_DMA_TX_PERI_SEL,
  135. SSP0_GPDMA_Tx_SignalEvent,
  136. RTE_SSP0_DMA_RX_EN,
  137. RTE_SSP0_DMA_RX_CH,
  138. RTE_SSP0_DMA_RX_PERI,
  139. RTE_SSP0_DMA_RX_PERI_SEL,
  140. SSP0_GPDMA_Rx_SignalEvent },
  141. SSP0_IRQn,
  142. &SSP0_Info,
  143. &SSP0_Xfer
  144. };
  145. #endif
  146. #if (RTE_SSP1)
  147. static SSP_INFO SSP1_Info = { 0 };
  148. static SSP_TRANSFER_INFO SSP1_Xfer;
  149. static PIN_ID SSP1_pin_sck = { RTE_SSP1_SCK_PORT, RTE_SSP1_SCK_BIT, RTE_SSP1_SCK_FUNC };
  150. static PIN_ID SSP1_pin_miso = { RTE_SSP1_MISO_PORT, RTE_SSP1_MISO_BIT, RTE_SSP1_MISO_FUNC};
  151. static PIN_ID SSP1_pin_mosi = { RTE_SSP1_MOSI_PORT, RTE_SSP1_MOSI_BIT, RTE_SSP1_MOSI_FUNC};
  152. #if (RTE_SSP1_SSEL_PIN_EN == 1U)
  153. static PIN_ID SSP1_pin_ssel = { RTE_SSP1_SSEL_PORT, RTE_SSP1_SSEL_BIT, RTE_SSP1_SSEL_FUNC };
  154. static GPIO_ID SSP1_gpio_ssel = { RTE_SSP1_SSEL_GPIO_PORT, RTE_SSP1_SSEL_GPIO_BIT};
  155. #endif
  156. static SSP_RESOURCES SSP1_Resources = {
  157. LPC_SSP1,
  158. { &SSP1_pin_sck,
  159. &SSP1_pin_miso,
  160. &SSP1_pin_mosi,
  161. #if (RTE_SSP1_SSEL_PIN_EN == 1U)
  162. &SSP1_pin_ssel,
  163. &SSP1_gpio_ssel,
  164. RTE_SSP1_SSEL_GPIO_FUNC,
  165. #else
  166. NULL,
  167. NULL,
  168. 0,
  169. #endif
  170. },
  171. { CGU_BASE_SSPx_CLK_AUTOBLOCK | ((CLK_SRC_PLL1 << 24) & CGU_BASE_SSPx_CLK_CLK_SEL),
  172. &(LPC_CGU->BASE_SSP1_CLK),
  173. CCU1_CLK_M3_SSPx_CFG_AUTO | CCU1_CLK_M3_SSPx_CFG_RUN,
  174. &(LPC_CCU1->CLK_M3_SSP1_CFG),
  175. CCU1_CLK_M3_SSPx_STAT_RUN,
  176. &(LPC_CCU1->CLK_M3_SSP1_STAT) },
  177. { RGU_RESET_CTRL1_SSP1_RST,
  178. &(LPC_RGU->RESET_CTRL1),
  179. RGU_RESET_ACTIVE_STATUS1_SSP1_RST,
  180. &(LPC_RGU->RESET_ACTIVE_STATUS1) },
  181. { RTE_SSP1_DMA_TX_EN,
  182. RTE_SSP1_DMA_TX_CH,
  183. RTE_SSP1_DMA_TX_PERI,
  184. RTE_SSP1_DMA_TX_PERI_SEL,
  185. SSP1_GPDMA_Tx_SignalEvent,
  186. RTE_SSP1_DMA_RX_EN,
  187. RTE_SSP1_DMA_RX_CH,
  188. RTE_SSP1_DMA_RX_PERI,
  189. RTE_SSP1_DMA_RX_PERI_SEL,
  190. SSP1_GPDMA_Rx_SignalEvent },
  191. SSP1_IRQn,
  192. &SSP1_Info,
  193. &SSP1_Xfer
  194. };
  195. #endif
  196. /**
  197. \fn ARM_DRIVER_VERSION SSP_GetVersion (void)
  198. \brief Get SSP driver version.
  199. \return \ref ARM_DRV_VERSION
  200. */
  201. static ARM_DRIVER_VERSION SSP_GetVersion (void) {
  202. return DriverVersion;
  203. }
  204. /**
  205. \fn ARM_SPI_CAPABILITIES SSP_GetCapabilities (void)
  206. \brief Get driver capabilities.
  207. \return \ref ARM_SPI_CAPABILITIES
  208. */
  209. static ARM_SPI_CAPABILITIES SSP_GetCapabilities (void) {
  210. return DriverCapabilities;
  211. }
  212. /**
  213. \fn int32_t SSPx_Initialize (ARM_SPI_SignalEvent_t cb_event, SSP_RESOURCES *ssp)
  214. \brief Initialize SSP Interface.
  215. \param[in] cb_event Pointer to \ref ARM_SPI_SignalEvent
  216. \param[in] ssp Pointer to SSP resources
  217. \return \ref execution_status
  218. */
  219. static int32_t SSPx_Initialize (ARM_SPI_SignalEvent_t cb_event, SSP_RESOURCES *ssp) {
  220. uint32_t val;
  221. if (ssp->info->state & SSP_INITIALIZED) { return ARM_DRIVER_OK; }
  222. // Initialize SSP Run-Time Resources
  223. ssp->info->cb_event = cb_event;
  224. ssp->info->status.busy = 0U;
  225. ssp->info->status.data_lost = 0U;
  226. ssp->info->status.mode_fault = 0U;
  227. // Clear transfer information
  228. memset(ssp->xfer, 0, sizeof(SSP_TRANSFER_INFO));
  229. // Configure pins
  230. val = SCU_PIN_CFG_PULLUP_DIS | SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN | SCU_PIN_CFG_INPUT_BUFFER_EN | SCU_PIN_CFG_INPUT_FILTER_DIS;
  231. SCU_PinConfigure (ssp->pin.sck->port, ssp->pin.sck->num, ssp->pin.sck->config_val | val);
  232. if (ssp->pin.sck->port == 16U) { SCU_CLK_PinConfigure (ssp->pin.sck->num, ssp->pin.sck->config_val | val); }
  233. else { SCU_PinConfigure (ssp->pin.sck->port, ssp->pin.sck->num, ssp->pin.sck->config_val | val); }
  234. SCU_PinConfigure (ssp->pin.miso->port, ssp->pin.miso->num, ssp->pin.miso->config_val | val);
  235. SCU_PinConfigure (ssp->pin.mosi->port, ssp->pin.mosi->num, ssp->pin.mosi->config_val | val);
  236. // Configure DMA if it will be used
  237. if (ssp->dma.tx_en || ssp->dma.rx_en) { GPDMA_Initialize (); }
  238. if (ssp->dma.tx_en) { GPDMA_PeripheralSelect (ssp->dma.tx_peri, ssp->dma.tx_peri_sel); }
  239. if (ssp->dma.rx_en) { GPDMA_PeripheralSelect (ssp->dma.rx_peri, ssp->dma.rx_peri_sel); }
  240. ssp->info->state = SSP_INITIALIZED; // SSP is initialized
  241. return ARM_DRIVER_OK;
  242. }
  243. /**
  244. \fn int32_t SSPx_Uninitialize (SSP_RESOURCES *ssp)
  245. \brief De-initialize SSP Interface.
  246. \param[in] ssp Pointer to SSP resources
  247. \return \ref execution_status
  248. */
  249. static int32_t SSPx_Uninitialize (SSP_RESOURCES *ssp) {
  250. // Unconfigure pins
  251. if (ssp->pin.ssel != NULL) { SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, 0U); }
  252. if (ssp->pin.sck->port == 16U) { SCU_CLK_PinConfigure (ssp->pin.sck->num, 0U); }
  253. else { SCU_PinConfigure (ssp->pin.sck->port, ssp->pin.sck->num, 0U); }
  254. SCU_PinConfigure (ssp->pin.miso->port, ssp->pin.miso->num, 0U);
  255. SCU_PinConfigure (ssp->pin.mosi->port, ssp->pin.mosi->num, 0U);
  256. // Uninitialize DMA
  257. if (ssp->dma.tx_en || ssp->dma.rx_en) { GPDMA_Uninitialize (); }
  258. ssp->info->state = 0U; // SSP is uninitialized
  259. return ARM_DRIVER_OK;
  260. }
  261. /**
  262. \fn int32_t SSPx_PowerControl (ARM_POWER_STATE state, SSP_RESOURCES *ssp)
  263. \brief Control SSP Interface Power.
  264. \param[in] state Power state
  265. \param[in] ssp Pointer to SSP resources
  266. \return \ref execution_status
  267. */
  268. static int32_t SSPx_PowerControl (ARM_POWER_STATE state, SSP_RESOURCES *ssp) {
  269. switch (state) {
  270. case ARM_POWER_OFF:
  271. NVIC_DisableIRQ (ssp->irq_num); // Disable SSP IRQ in NVIC
  272. if (ssp->info->status.busy) {
  273. // If DMA mode - disable DMA channel
  274. if (ssp->dma.tx_en) { GPDMA_ChannelDisable (ssp->dma.tx_ch); }
  275. // If DMA mode - disable DMA channel
  276. if (ssp->dma.rx_en) { GPDMA_ChannelDisable (ssp->dma.rx_ch); }
  277. }
  278. // Reset SSP peripheral
  279. *(ssp->rst.reg_cfg) = ssp->rst.reg_cfg_val;
  280. while (!(*(ssp->rst.reg_stat) & ssp->rst.reg_stat_val));
  281. if (*(ssp->clk.reg_cfg) == 0U) {
  282. *(ssp->clk.peri_cfg) = ~1U;
  283. while ( *(ssp->clk.peri_cfg) & 1U);
  284. // Power down, clock source set to IRC
  285. *(ssp->clk.reg_cfg) = 1U | (1U << 24) | (1U << 11);
  286. }
  287. // Reset SSP Run-Time Resources
  288. ssp->info->status.busy = 0U;
  289. ssp->info->status.data_lost = 0U;
  290. ssp->info->status.mode_fault = 0U;
  291. // Clear transfer information
  292. memset(ssp->xfer, 0, sizeof(SSP_TRANSFER_INFO));
  293. ssp->info->state &= ~SSP_POWERED; // SSP is not powered
  294. break;
  295. case ARM_POWER_FULL:
  296. if ((ssp->info->state & SSP_INITIALIZED) == 0U) { return ARM_DRIVER_ERROR; }
  297. if ((ssp->info->state & SSP_POWERED) != 0U) { return ARM_DRIVER_OK; }
  298. // Initialize SSP register clock
  299. *(ssp->clk.reg_cfg) = ssp->clk.reg_cfg_val;
  300. // Activate SSP peripheral clock
  301. *(ssp->clk.peri_cfg) = ssp->clk.peri_cfg_val;
  302. while (!(*(ssp->clk.peri_stat) & ssp->clk.peri_stat_val));
  303. // Reset SSP peripheral
  304. *(ssp->rst.reg_cfg) = ssp->rst.reg_cfg_val;
  305. while (!(*(ssp->rst.reg_stat) & ssp->rst.reg_stat_val));
  306. ssp->reg->IMSC = 0U; // Disable SSP interrupts
  307. ssp->reg->ICR = 3U; // Clear SSP interrupts
  308. // Reset SSP Run-Time Resources
  309. ssp->info->status.busy = 0U;
  310. ssp->info->status.data_lost = 0U;
  311. ssp->info->status.mode_fault = 0U;
  312. ssp->info->state |= SSP_POWERED; // SSP is powered
  313. // Enable DMA
  314. if (ssp->dma.tx_en) { ssp->reg->DMACR |= SSPx_DMACR_TXDMAE; }
  315. if (ssp->dma.rx_en) { ssp->reg->DMACR |= SSPx_DMACR_RXDMAE; }
  316. NVIC_ClearPendingIRQ (ssp->irq_num);
  317. NVIC_EnableIRQ (ssp->irq_num); // Enable SSP IRQ in NVIC
  318. break;
  319. default:
  320. return ARM_DRIVER_ERROR_UNSUPPORTED;
  321. }
  322. return ARM_DRIVER_OK;
  323. }
  324. /**
  325. \fn int32_t SSPx_Send (const void *data, uint32_t num, SSP_RESOURCES *ssp)
  326. \brief Start sending data to SSP transmitter.
  327. \param[in] data Pointer to buffer with data to send to SSP transmitter
  328. \param[in] num Number of data items to send
  329. \param[in] ssp Pointer to SSP resources
  330. \return \ref execution_status
  331. */
  332. static int32_t SSPx_Send (const void *data, uint32_t num, SSP_RESOURCES *ssp) {
  333. static uint32_t dummy_data;
  334. if ((data == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
  335. if (!(ssp->info->state & SSP_CONFIGURED)) { return ARM_DRIVER_ERROR; }
  336. if ( ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
  337. ssp->info->status.busy = 1U;
  338. ssp->info->status.data_lost = 0U;
  339. ssp->info->status.mode_fault = 0U;
  340. ssp->xfer->rx_buf = NULL;
  341. ssp->xfer->tx_buf = (uint8_t *)data;
  342. ssp->xfer->num = num;
  343. ssp->xfer->rx_cnt = 0U;
  344. ssp->xfer->tx_cnt = 0U;
  345. if (ssp->dma.tx_en && ssp->dma.rx_en) {
  346. if (GPDMA_ChannelConfigure (ssp->dma.rx_ch,
  347. (uint32_t)&ssp->reg->DR,
  348. (uint32_t)&dummy_data,
  349. num,
  350. GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
  351. GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
  352. GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  353. GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  354. GPDMA_CH_CONTROL_S |
  355. GPDMA_CH_CONTROL_D |
  356. GPDMA_CH_CONTROL_I,
  357. GPDMA_CH_CONFIG_SRC_PERI(ssp->dma.rx_peri) |
  358. GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_P2M_CTRL_DMA) |
  359. GPDMA_CH_CONFIG_IE |
  360. GPDMA_CH_CONFIG_ITC |
  361. GPDMA_CH_CONFIG_E,
  362. ssp->dma.rx_callback) == -1) {
  363. return ARM_DRIVER_ERROR;
  364. }
  365. if (GPDMA_ChannelConfigure (ssp->dma.tx_ch,
  366. (uint32_t)data,
  367. (uint32_t)&ssp->reg->DR,
  368. num,
  369. GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
  370. GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
  371. GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  372. GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  373. GPDMA_CH_CONTROL_S |
  374. GPDMA_CH_CONTROL_D |
  375. GPDMA_CH_CONTROL_SI |
  376. GPDMA_CH_CONTROL_I,
  377. GPDMA_CH_CONFIG_DEST_PERI(ssp->dma.tx_peri) |
  378. GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_M2P_CTRL_DMA) |
  379. GPDMA_CH_CONFIG_IE |
  380. GPDMA_CH_CONFIG_ITC |
  381. GPDMA_CH_CONFIG_E,
  382. ssp->dma.tx_callback) == -1) {
  383. return ARM_DRIVER_ERROR;
  384. }
  385. } else {
  386. ssp->reg->IMSC = SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM;
  387. }
  388. return ARM_DRIVER_OK;
  389. }
  390. /**
  391. \fn int32_t SSPx_Receive (void *data, uint32_t num, SSP_RESOURCES *ssp)
  392. \brief Start receiving data from SSP receiver.
  393. \param[out] data Pointer to buffer for data to receive from SSP receiver
  394. \param[in] num Number of data items to receive
  395. \param[in] ssp Pointer to SSP resources
  396. \return \ref execution_status
  397. */
  398. static int32_t SSPx_Receive (void *data, uint32_t num, SSP_RESOURCES *ssp) {
  399. static uint32_t dummy_data;
  400. if ((data == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
  401. if (!(ssp->info->state & SSP_CONFIGURED)) { return ARM_DRIVER_ERROR; }
  402. if ( ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
  403. ssp->info->status.busy = 1U;
  404. ssp->info->status.data_lost = 0U;
  405. ssp->info->status.mode_fault = 0U;
  406. dummy_data = ssp->xfer->def_val;
  407. ssp->xfer->rx_buf = (uint8_t *)data;
  408. ssp->xfer->tx_buf = NULL;
  409. ssp->xfer->num = num;
  410. ssp->xfer->rx_cnt = 0U;
  411. ssp->xfer->tx_cnt = 0U;
  412. if (ssp->dma.tx_en && ssp->dma.rx_en) {
  413. if (GPDMA_ChannelConfigure (ssp->dma.rx_ch,
  414. (uint32_t)&ssp->reg->DR,
  415. (uint32_t)data,
  416. num,
  417. GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
  418. GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
  419. GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  420. GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  421. GPDMA_CH_CONTROL_S |
  422. GPDMA_CH_CONTROL_D |
  423. GPDMA_CH_CONTROL_DI |
  424. GPDMA_CH_CONTROL_I,
  425. GPDMA_CH_CONFIG_SRC_PERI(ssp->dma.rx_peri) |
  426. GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_P2M_CTRL_DMA) |
  427. GPDMA_CH_CONFIG_IE |
  428. GPDMA_CH_CONFIG_ITC |
  429. GPDMA_CH_CONFIG_E,
  430. ssp->dma.rx_callback) == -1) {
  431. return ARM_DRIVER_ERROR;
  432. }
  433. if (GPDMA_ChannelConfigure (ssp->dma.tx_ch,
  434. (uint32_t)&dummy_data,
  435. (uint32_t)&ssp->reg->DR,
  436. num,
  437. GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
  438. GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
  439. GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  440. GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  441. GPDMA_CH_CONTROL_S |
  442. GPDMA_CH_CONTROL_D |
  443. GPDMA_CH_CONTROL_I,
  444. GPDMA_CH_CONFIG_DEST_PERI(ssp->dma.tx_peri) |
  445. GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_M2P_CTRL_DMA) |
  446. GPDMA_CH_CONFIG_IE |
  447. GPDMA_CH_CONFIG_ITC |
  448. GPDMA_CH_CONFIG_E,
  449. ssp->dma.tx_callback) == -1) {
  450. return ARM_DRIVER_ERROR;
  451. }
  452. } else {
  453. ssp->reg->IMSC = SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM;
  454. }
  455. return ARM_DRIVER_OK;
  456. }
  457. /**
  458. \fn int32_t SSPx_Transfer (const void *data_out,
  459. void *data_in,
  460. uint32_t num,
  461. SSP_RESOURCES *ssp)
  462. \brief Start sending/receiving data to/from SSP transmitter/receiver.
  463. \param[in] data_out Pointer to buffer with data to send to SSP transmitter
  464. \param[out] data_in Pointer to buffer for data to receive from SSP receiver
  465. \param[in] num Number of data items to transfer
  466. \param[in] ssp Pointer to SSP resources
  467. \return \ref execution_status
  468. */
  469. static int32_t SSPx_Transfer (const void *data_out, void *data_in, uint32_t num, SSP_RESOURCES *ssp) {
  470. if ((data_out == NULL) || (data_in == NULL) || (num == 0U)) { return ARM_DRIVER_ERROR_PARAMETER; }
  471. if (!(ssp->info->state & SSP_CONFIGURED)) { return ARM_DRIVER_ERROR; }
  472. if ( ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
  473. ssp->info->status.busy = 1U;
  474. ssp->info->status.data_lost = 0U;
  475. ssp->info->status.mode_fault = 0U;
  476. ssp->xfer->rx_buf = (uint8_t *)data_in;
  477. ssp->xfer->tx_buf = (uint8_t *)data_out;
  478. ssp->xfer->num = num;
  479. ssp->xfer->rx_cnt = 0U;
  480. ssp->xfer->tx_cnt = 0U;
  481. if (ssp->dma.tx_en && ssp->dma.rx_en) {
  482. if (GPDMA_ChannelConfigure (ssp->dma.rx_ch,
  483. (uint32_t)&ssp->reg->DR,
  484. (uint32_t)data_in,
  485. num,
  486. GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
  487. GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
  488. GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  489. GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  490. GPDMA_CH_CONTROL_S |
  491. GPDMA_CH_CONTROL_D |
  492. GPDMA_CH_CONTROL_DI |
  493. GPDMA_CH_CONTROL_I,
  494. GPDMA_CH_CONFIG_SRC_PERI(ssp->dma.rx_peri) |
  495. GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_P2M_CTRL_DMA) |
  496. GPDMA_CH_CONFIG_IE |
  497. GPDMA_CH_CONFIG_ITC |
  498. GPDMA_CH_CONFIG_E,
  499. ssp->dma.rx_callback) == -1) {
  500. return ARM_DRIVER_ERROR;
  501. }
  502. if (GPDMA_ChannelConfigure (ssp->dma.tx_ch,
  503. (uint32_t)data_out,
  504. (uint32_t)&ssp->reg->DR,
  505. num,
  506. GPDMA_CH_CONTROL_SBSIZE(GPDMA_BSIZE_1) |
  507. GPDMA_CH_CONTROL_DBSIZE(GPDMA_BSIZE_1) |
  508. GPDMA_CH_CONTROL_SWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  509. GPDMA_CH_CONTROL_DWIDTH((ssp->reg->CR0 & SSPx_CR0_DSS) > 7) |
  510. GPDMA_CH_CONTROL_S |
  511. GPDMA_CH_CONTROL_D |
  512. GPDMA_CH_CONTROL_SI |
  513. GPDMA_CH_CONTROL_I,
  514. GPDMA_CH_CONFIG_DEST_PERI(ssp->dma.tx_peri) |
  515. GPDMA_CH_CONFIG_FLOWCNTRL(GPDMA_TRANSFER_M2P_CTRL_DMA) |
  516. GPDMA_CH_CONFIG_IE |
  517. GPDMA_CH_CONFIG_ITC |
  518. GPDMA_CH_CONFIG_E,
  519. ssp->dma.tx_callback) == -1) {
  520. return ARM_DRIVER_ERROR;
  521. }
  522. } else {
  523. ssp->reg->IMSC = SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM;
  524. }
  525. return ARM_DRIVER_OK;
  526. }
  527. /**
  528. \fn uint32_t SSPx_GetDataCount (SSP_RESOURCES *ssp)
  529. \brief Get transferred data count.
  530. \param[in] ssp Pointer to SSP resources
  531. \return number of data items transferred
  532. */
  533. static uint32_t SSPx_GetDataCount (SSP_RESOURCES *ssp) {
  534. uint32_t cnt;
  535. if (!(ssp->info->state & SSP_CONFIGURED)) { return 0U; }
  536. if (ssp->dma.rx_en) {
  537. cnt = GPDMA_ChannelGetCount (ssp->dma.rx_ch);
  538. } else {
  539. cnt = ssp->xfer->rx_cnt;
  540. }
  541. return cnt;
  542. }
  543. /**
  544. \fn int32_t SSPx_Control (uint32_t control, uint32_t arg, SSP_RESOURCES *ssp)
  545. \brief Control SSP Interface.
  546. \param[in] control Operation
  547. \param[in] arg Argument of operation (optional)
  548. \param[in] ssp Pointer to SSP resources
  549. \return common \ref execution_status and driver specific \ref spi_execution_status
  550. */
  551. static int32_t SSPx_Control (uint32_t control, uint32_t arg, SSP_RESOURCES *ssp) {
  552. uint32_t cpsr, scr, bps = 0U, clk, data_bits;
  553. uint32_t best_cpsr = 2U, best_scr = 0U, best_bps = 0U;
  554. if (!(ssp->info->state & SSP_POWERED)) { return ARM_DRIVER_ERROR; }
  555. if ((control & ARM_SPI_CONTROL_Msk) == ARM_SPI_ABORT_TRANSFER) {
  556. ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
  557. ssp->reg->IMSC = 0U; // Disable interrupts
  558. if (ssp->info->status.busy) {
  559. // If DMA mode - disable DMA channel
  560. if (ssp->dma.tx_en) { GPDMA_ChannelDisable (ssp->dma.tx_ch); }
  561. // If DMA mode - disable DMA channel
  562. if (ssp->dma.rx_en) { GPDMA_ChannelDisable (ssp->dma.rx_ch); }
  563. }
  564. memset(ssp->xfer, 0, sizeof(SSP_TRANSFER_INFO));
  565. ssp->info->status.busy = 0U;
  566. ssp->reg->CR1 |= SSPx_CR1_SSE; // Enable SSP
  567. return ARM_DRIVER_OK;
  568. }
  569. if (ssp->info->status.busy) { return ARM_DRIVER_ERROR_BUSY; }
  570. switch (control & ARM_SPI_CONTROL_Msk) {
  571. default:
  572. return ARM_DRIVER_ERROR_UNSUPPORTED;
  573. case ARM_SPI_MODE_INACTIVE: // SPI Inactive
  574. ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
  575. ssp->reg->IMSC = 0U; // Disable interrupts
  576. ssp->info->mode &= ~ARM_SPI_CONTROL_Msk;
  577. ssp->info->mode |= ARM_SPI_MODE_INACTIVE;
  578. ssp->info->state &= ~SSP_CONFIGURED;
  579. return ARM_DRIVER_OK;
  580. case ARM_SPI_MODE_MASTER: // SPI Master (Output on MOSI, Input on MISO); arg = Bus Speed in bps
  581. ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
  582. ssp->reg->IMSC = 0U; // Disable interrupts
  583. ssp->reg->CR1 &= ~SSPx_CR1_MS; // Set master mode
  584. ssp->info->mode &= ~ARM_SPI_CONTROL_Msk;
  585. ssp->info->mode |= ARM_SPI_MODE_MASTER;
  586. ssp->info->state |= SSP_CONFIGURED;
  587. ssp->reg->CR1 |= SSPx_CR1_SSE; // Enable SSP
  588. goto set_speed;
  589. case ARM_SPI_MODE_SLAVE: // SPI Slave (Output on MISO, Input on MOSI)
  590. ssp->reg->CR1 &= ~SSPx_CR1_SSE; // Disable SSP
  591. ssp->reg->CR1 |= SSPx_CR1_MS; // Set slave mode
  592. ssp->reg->IMSC = SSPx_IMSC_RORIM; // Enable receive overrun interrupt
  593. ssp->info->mode &= ~ARM_SPI_CONTROL_Msk;
  594. ssp->info->mode |= ARM_SPI_MODE_SLAVE;
  595. ssp->info->state |= SSP_CONFIGURED;
  596. ssp->reg->CR1 |= SSPx_CR1_SSE; // Enable SSP
  597. break;
  598. case ARM_SPI_MODE_MASTER_SIMPLEX: // SPI Master (Output/Input on MOSI); arg = Bus Speed in bps
  599. case ARM_SPI_MODE_SLAVE_SIMPLEX: // SPI Slave (Output/Input on MISO)
  600. return ARM_SPI_ERROR_MODE;
  601. case ARM_SPI_SET_BUS_SPEED: // Set Bus Speed in bps; arg = value
  602. set_speed:
  603. if (arg == 0U) {
  604. return ARM_DRIVER_ERROR;
  605. }
  606. clk = GetClockFreq(CLK_SRC_PLL1) << 4;
  607. arg = (arg << 4);
  608. for (cpsr = 2U; cpsr < 255U; cpsr+= 2U) {// Loop through clock prescaler
  609. for (scr = 0U; scr < 256U; scr++) { // Loop through bit prescaler
  610. bps = clk / (cpsr * (scr + 1U));
  611. if (arg == bps) {
  612. best_bps = bps;
  613. best_cpsr = cpsr;
  614. best_scr = scr;
  615. goto found_best;
  616. } else {
  617. if (arg > bps) {
  618. if ((arg - best_bps) > (arg - bps)) {
  619. best_bps = bps;
  620. best_cpsr = cpsr;
  621. best_scr = scr;
  622. }
  623. }
  624. }
  625. }
  626. }
  627. if (best_bps == 0U) {
  628. return ARM_DRIVER_ERROR;
  629. }
  630. found_best:
  631. ssp->reg->CPSR = best_cpsr & SSPx_CPSR_CPSDVSR;
  632. ssp->reg->CR0 &= ~SSPx_CR0_SCR;
  633. ssp->reg->CR0 |= ((best_scr << 8) & SSPx_CR0_SCR);
  634. if ((control & ARM_SPI_CONTROL_Msk) == ARM_SPI_SET_BUS_SPEED) {
  635. return ARM_DRIVER_OK;
  636. }
  637. break;
  638. case ARM_SPI_GET_BUS_SPEED: // Get Bus Speed in bps
  639. return (GetClockFreq(CLK_SRC_PLL1) / ((ssp->reg->CPSR & SSPx_CPSR_CPSDVSR) * (((ssp->reg->CR0 & SSPx_CR0_SCR) >> 8) + 1U)));
  640. case ARM_SPI_SET_DEFAULT_TX_VALUE: // Set default Transmit value; arg = value
  641. ssp->xfer->def_val = (uint16_t)(arg & 0xFFFF);
  642. return ARM_DRIVER_OK;
  643. case ARM_SPI_CONTROL_SS: // Control Slave Select; arg = 0:inactive, 1:active
  644. if (((ssp->info->mode & ARM_SPI_CONTROL_Msk) != ARM_SPI_MODE_MASTER) ||
  645. ((ssp->info->mode & ARM_SPI_SS_MASTER_MODE_Msk) != ARM_SPI_SS_MASTER_SW)) {
  646. return ARM_DRIVER_ERROR;
  647. }
  648. if (ssp->pin.ssel == NULL) {
  649. return ARM_DRIVER_ERROR;
  650. }
  651. if (arg == ARM_SPI_SS_INACTIVE) {
  652. GPIO_PinWrite (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, 1U);
  653. } else {
  654. GPIO_PinWrite (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, 0U);
  655. }
  656. return ARM_DRIVER_OK;
  657. }
  658. if ((ssp->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_MASTER) {
  659. switch (control & ARM_SPI_SS_MASTER_MODE_Msk) {
  660. case ARM_SPI_SS_MASTER_UNUSED: // SPI Slave Select when Master: Not used (default)
  661. if (ssp->pin.ssel != NULL) { SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, 0U); }
  662. ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
  663. ssp->info->mode |= ARM_SPI_SS_MASTER_UNUSED;
  664. break;
  665. case ARM_SPI_SS_MASTER_HW_INPUT: // SPI Slave Select when Master: Hardware monitored Input
  666. ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
  667. return ARM_SPI_ERROR_SS_MODE;
  668. case ARM_SPI_SS_MASTER_SW: // SPI Slave Select when Master: Software controlled
  669. ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
  670. if (ssp->pin.ssel != NULL) {
  671. SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, ssp->pin.gpio_ssel_af |
  672. SCU_PIN_CFG_PULLUP_DIS |
  673. SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN );
  674. GPIO_SetDir (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, GPIO_DIR_OUTPUT);
  675. GPIO_PinWrite (ssp->pin.gpio_ssel->port, ssp->pin.gpio_ssel->num, 1);
  676. ssp->info->mode |= ARM_SPI_SS_MASTER_SW;
  677. } else {
  678. return ARM_SPI_ERROR_SS_MODE;
  679. }
  680. break;
  681. case ARM_SPI_SS_MASTER_HW_OUTPUT: // SPI Slave Select when Master: Hardware controlled Output
  682. ssp->info->mode &= ~ARM_SPI_SS_MASTER_MODE_Msk;
  683. if (ssp->pin.ssel != NULL) {
  684. SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, ssp->pin.ssel->config_val |
  685. SCU_PIN_CFG_PULLUP_DIS |
  686. SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN );
  687. ssp->info->mode |= ARM_SPI_SS_MASTER_HW_OUTPUT;
  688. } else {
  689. return ARM_SPI_ERROR_SS_MODE;
  690. }
  691. default:
  692. break;
  693. }
  694. }
  695. if ((ssp->info->mode & ARM_SPI_CONTROL_Msk) == ARM_SPI_MODE_SLAVE) {
  696. switch (control & ARM_SPI_SS_SLAVE_MODE_Msk) {
  697. case ARM_SPI_SS_SLAVE_HW: // SPI Slave Select when Slave: Hardware monitored (default)
  698. ssp->info->mode &= ~ARM_SPI_SS_SLAVE_MODE_Msk;
  699. if (ssp->pin.ssel != NULL) {
  700. SCU_PinConfigure (ssp->pin.ssel->port, ssp->pin.ssel->num, ssp->pin.ssel->config_val |
  701. SCU_PIN_CFG_PULLUP_DIS |
  702. SCU_PIN_CFG_HIGH_SPEED_SLEW_RATE_EN |
  703. SCU_PIN_CFG_INPUT_BUFFER_EN |
  704. SCU_PIN_CFG_INPUT_FILTER_DIS );
  705. ssp->info->mode |= ARM_SPI_SS_SLAVE_HW;
  706. } else {
  707. return ARM_SPI_ERROR_SS_MODE;
  708. }
  709. break;
  710. case ARM_SPI_SS_SLAVE_SW: // SPI Slave Select when Slave: Software controlled
  711. ssp->info->mode &= ~ARM_SPI_SS_SLAVE_MODE_Msk;
  712. return ARM_SPI_ERROR_SS_MODE;
  713. default: return ARM_SPI_ERROR_SS_MODE;
  714. }
  715. }
  716. // Configure Frame Format
  717. switch (control & ARM_SPI_FRAME_FORMAT_Msk) {
  718. case ARM_SPI_CPOL0_CPHA0:
  719. ssp->reg->CR0 &= ~SSPx_CR0_FRF;
  720. ssp->reg->CR0 &= ~(SSPx_CR0_CPOL | SSPx_CR0_CPHA);
  721. break;
  722. case ARM_SPI_CPOL0_CPHA1:
  723. ssp->reg->CR0 &= ~SSPx_CR0_FRF;
  724. ssp->reg->CR0 &= ~SSPx_CR0_CPOL;
  725. ssp->reg->CR0 |= SSPx_CR0_CPHA;
  726. break;
  727. case ARM_SPI_CPOL1_CPHA0:
  728. ssp->reg->CR0 &= ~SSPx_CR0_FRF;
  729. ssp->reg->CR0 |= SSPx_CR0_CPOL;
  730. ssp->reg->CR0 &= ~SSPx_CR0_CPHA;
  731. break;
  732. case ARM_SPI_CPOL1_CPHA1:
  733. ssp->reg->CR0 &= ~SSPx_CR0_FRF;
  734. ssp->reg->CR0 |= (SSPx_CR0_CPOL | SSPx_CR0_CPHA);
  735. break;
  736. case ARM_SPI_TI_SSI:
  737. ssp->reg->CR0 = (ssp->reg->CR0 & (~SSPx_CR0_FRF)) | (1U << 4);
  738. break;
  739. case ARM_SPI_MICROWIRE:
  740. ssp->reg->CR0 = (ssp->reg->CR0 & (~SSPx_CR0_FRF)) | (2U << 4);
  741. break;
  742. default:
  743. return ARM_SPI_ERROR_FRAME_FORMAT;
  744. }
  745. // Configure Number of Data Bits
  746. data_bits = ((control & ARM_SPI_DATA_BITS_Msk) >> ARM_SPI_DATA_BITS_Pos);
  747. if ((data_bits >= 4U) && (data_bits <= 16U)) {
  748. ssp->reg->CR0 = (ssp->reg->CR0 & (~SSPx_CR0_DSS)) | ((data_bits - 1U) << 0);
  749. } else {
  750. return ARM_SPI_ERROR_DATA_BITS;
  751. }
  752. // Configure Bit Order
  753. if ((control & ARM_SPI_BIT_ORDER_Msk) == ARM_SPI_LSB_MSB) {
  754. return ARM_SPI_ERROR_BIT_ORDER;
  755. }
  756. return ARM_DRIVER_OK;
  757. }
  758. /**
  759. \fn ARM_SPI_STATUS SSPx_GetStatus (SSP_RESOURCES *ssp)
  760. \brief Get SSP status.
  761. \param[in] ssp Pointer to SSP resources
  762. \return SPI status \ref ARM_SPI_STATUS
  763. */
  764. static ARM_SPI_STATUS SSPx_GetStatus (SSP_RESOURCES *ssp) {
  765. ARM_SPI_STATUS status;
  766. status.busy = ssp->info->status.busy;
  767. status.data_lost = ssp->info->status.data_lost;
  768. status.mode_fault = ssp->info->status.mode_fault;
  769. return (status);
  770. }
  771. /**
  772. \fn void SSPx_GPDMA_Tx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp)
  773. \brief SSP GPDMA Tx Event handler.
  774. \param[in] event GPDMA Tx Event
  775. \param[in] ssp Pointer to SSP resources
  776. */
  777. void SSPx_GPDMA_Tx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp) {
  778. switch (event) {
  779. case GPDMA_EVENT_TERMINAL_COUNT_REQUEST:
  780. ssp->xfer->tx_cnt = ssp->xfer->num;
  781. break;
  782. case GPDMA_EVENT_ERROR:
  783. default:
  784. break;
  785. }
  786. }
  787. /**
  788. \fn void SSPx_GPDMA_Rx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp)
  789. \brief SSP GPDMA Rx Event handler.
  790. \param[in] event GPDMA Rx Event
  791. \param[in] ssp Pointer to SSP resources
  792. */
  793. void SSPx_GPDMA_Rx_SignalEvent (uint32_t event, SSP_RESOURCES *ssp) {
  794. switch (event) {
  795. case GPDMA_EVENT_TERMINAL_COUNT_REQUEST:
  796. ssp->xfer->rx_cnt = ssp->xfer->num;
  797. ssp->info->status.busy = 0U;
  798. if (ssp->info->cb_event) {
  799. ssp->info->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE);
  800. }
  801. break;
  802. case GPDMA_EVENT_ERROR:
  803. default:
  804. break;
  805. }
  806. }
  807. /**
  808. \fn void SSPx_IRQHandler (SSP_RESOURCES *ssp)
  809. \brief SSP Interrupt handler.
  810. \param[in] ssp Pointer to SSP resources
  811. */
  812. static void SSPx_IRQHandler (SSP_RESOURCES *ssp) {
  813. uint16_t data;
  814. uint32_t mis;
  815. mis = ssp->reg->MIS;
  816. ssp->reg->ICR = mis & 3U;
  817. // Handle transfer
  818. if ((ssp->reg->SR & SSPx_SR_TNF) && (ssp->xfer->num > ssp->xfer->tx_cnt)) {
  819. if (ssp->xfer->tx_buf) { // If data available
  820. data = *(ssp->xfer->tx_buf++);
  821. if ((ssp->reg->CR0 & SSPx_CR0_DSS) > 7U) { // If 9..16-bit data frame format
  822. data |= *(ssp->xfer->tx_buf++) << 8;
  823. }
  824. } else { // If default data send
  825. data = ssp->xfer->def_val;
  826. }
  827. ssp->reg->DR = data; // Activate send
  828. ssp->xfer->tx_cnt++;
  829. }
  830. if (ssp->reg->SR & SSPx_SR_RNE) {
  831. data = ssp->reg->DR; // Read data
  832. if (ssp->xfer->num > ssp->xfer->rx_cnt) {
  833. if (ssp->xfer->rx_buf) {
  834. *(ssp->xfer->rx_buf++) = (uint8_t)data; // Put data into buffer
  835. if ((ssp->reg->CR0 & SSPx_CR0_DSS) > 7U) { // If 9..16-bit data frame format
  836. *(ssp->xfer->rx_buf++) = (uint8_t)(data >> 8);
  837. }
  838. }
  839. ssp->xfer->rx_cnt++;
  840. if (ssp->xfer->rx_cnt == ssp->xfer->num) { // If all data received
  841. ssp->reg->IMSC &= ~(SSPx_IMSC_TXIM | SSPx_IMSC_RXIM | SSPx_IMSC_RTIM | SSPx_IMSC_RORIM);
  842. ssp->info->status.busy = 0U;
  843. if (ssp->info->cb_event) { ssp->info->cb_event(ARM_SPI_EVENT_TRANSFER_COMPLETE); }
  844. }
  845. }
  846. }
  847. if (mis & SSPx_MIS_RORMIS) { // Handle errors
  848. // Overrun flag is set
  849. ssp->info->status.data_lost = 1U;
  850. if (ssp->info->cb_event) { ssp->info->cb_event(ARM_SPI_EVENT_DATA_LOST); }
  851. }
  852. }
  853. #if (RTE_SSP0)
  854. static int32_t SSP0_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SSPx_Initialize (pSignalEvent, &SSP0_Resources); }
  855. static int32_t SSP0_Uninitialize (void) { return SSPx_Uninitialize (&SSP0_Resources); }
  856. static int32_t SSP0_PowerControl (ARM_POWER_STATE state) { return SSPx_PowerControl (state, &SSP0_Resources); }
  857. static int32_t SSP0_Send (const void *data, uint32_t num) { return SSPx_Send (data, num, &SSP0_Resources); }
  858. static int32_t SSP0_Receive (void *data, uint32_t num) { return SSPx_Receive (data, num, &SSP0_Resources); }
  859. static int32_t SSP0_Transfer (const void *data_out, void *data_in, uint32_t num) { return SSPx_Transfer (data_out, data_in, num, &SSP0_Resources); }
  860. static uint32_t SSP0_GetDataCount (void) { return SSPx_GetDataCount (&SSP0_Resources); }
  861. static int32_t SSP0_Control (uint32_t control, uint32_t arg) { return SSPx_Control (control, arg, &SSP0_Resources); }
  862. static ARM_SPI_STATUS SSP0_GetStatus (void) { return SSPx_GetStatus (&SSP0_Resources); }
  863. void SSP0_GPDMA_Tx_SignalEvent(uint32_t event) { SSPx_GPDMA_Tx_SignalEvent(event, &SSP0_Resources); }
  864. void SSP0_GPDMA_Rx_SignalEvent(uint32_t event) { SSPx_GPDMA_Rx_SignalEvent(event, &SSP0_Resources); }
  865. void SSP0_IRQHandler (void) { SSPx_IRQHandler (&SSP0_Resources); }
  866. // SPI0 Driver Control Block
  867. ARM_DRIVER_SPI Driver_SPI0 = {
  868. SSP_GetVersion,
  869. SSP_GetCapabilities,
  870. SSP0_Initialize,
  871. SSP0_Uninitialize,
  872. SSP0_PowerControl,
  873. SSP0_Send,
  874. SSP0_Receive,
  875. SSP0_Transfer,
  876. SSP0_GetDataCount,
  877. SSP0_Control,
  878. SSP0_GetStatus
  879. };
  880. #endif
  881. #if (RTE_SSP1)
  882. static int32_t SSP1_Initialize (ARM_SPI_SignalEvent_t pSignalEvent) { return SSPx_Initialize (pSignalEvent, &SSP1_Resources); }
  883. static int32_t SSP1_Uninitialize (void) { return SSPx_Uninitialize (&SSP1_Resources); }
  884. static int32_t SSP1_PowerControl (ARM_POWER_STATE state) { return SSPx_PowerControl (state, &SSP1_Resources); }
  885. static int32_t SSP1_Send (const void *data, uint32_t num) { return SSPx_Send (data, num, &SSP1_Resources); }
  886. static int32_t SSP1_Receive (void *data, uint32_t num) { return SSPx_Receive (data, num, &SSP1_Resources); }
  887. static int32_t SSP1_Transfer (const void *data_out, void *data_in, uint32_t num) { return SSPx_Transfer (data_out, data_in, num, &SSP1_Resources); }
  888. static uint32_t SSP1_GetDataCount (void) { return SSPx_GetDataCount (&SSP1_Resources); }
  889. static int32_t SSP1_Control (uint32_t control, uint32_t arg) { return SSPx_Control (control, arg, &SSP1_Resources); }
  890. static ARM_SPI_STATUS SSP1_GetStatus (void) { return SSPx_GetStatus (&SSP1_Resources); }
  891. void SSP1_GPDMA_Tx_SignalEvent(uint32_t event) { SSPx_GPDMA_Tx_SignalEvent(event, &SSP1_Resources); }
  892. void SSP1_GPDMA_Rx_SignalEvent(uint32_t event) { SSPx_GPDMA_Rx_SignalEvent(event, &SSP1_Resources); }
  893. void SSP1_IRQHandler (void) { SSPx_IRQHandler (&SSP1_Resources); }
  894. // SPI1 Driver Control Block
  895. ARM_DRIVER_SPI Driver_SPI1 = {
  896. SSP_GetVersion,
  897. SSP_GetCapabilities,
  898. SSP1_Initialize,
  899. SSP1_Uninitialize,
  900. SSP1_PowerControl,
  901. SSP1_Send,
  902. SSP1_Receive,
  903. SSP1_Transfer,
  904. SSP1_GetDataCount,
  905. SSP1_Control,
  906. SSP1_GetStatus
  907. };
  908. #endif