fsl_dspi_edma.c 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_dspi_edma.h"
  35. /***********************************************************************************************************************
  36. * Definitons
  37. ***********************************************************************************************************************/
  38. /*!
  39. * @brief Structure definition for dspi_master_edma_private_handle_t. The structure is private.
  40. */
  41. typedef struct _dspi_master_edma_private_handle
  42. {
  43. SPI_Type *base; /*!< DSPI peripheral base address. */
  44. dspi_master_edma_handle_t *handle; /*!< dspi_master_edma_handle_t handle */
  45. } dspi_master_edma_private_handle_t;
  46. /*!
  47. * @brief Structure definition for dspi_slave_edma_private_handle_t. The structure is private.
  48. */
  49. typedef struct _dspi_slave_edma_private_handle
  50. {
  51. SPI_Type *base; /*!< DSPI peripheral base address. */
  52. dspi_slave_edma_handle_t *handle; /*!< dspi_master_edma_handle_t handle */
  53. } dspi_slave_edma_private_handle_t;
  54. /***********************************************************************************************************************
  55. * Prototypes
  56. ***********************************************************************************************************************/
  57. /*!
  58. * @brief EDMA_DspiMasterCallback after the DSPI master transfer completed by using EDMA.
  59. * This is not a public API.
  60. */
  61. static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle,
  62. void *g_dspiEdmaPrivateHandle,
  63. bool transferDone,
  64. uint32_t tcds);
  65. /*!
  66. * @brief EDMA_DspiSlaveCallback after the DSPI slave transfer completed by using EDMA.
  67. * This is not a public API.
  68. */
  69. static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle,
  70. void *g_dspiEdmaPrivateHandle,
  71. bool transferDone,
  72. uint32_t tcds);
  73. /*!
  74. * @brief Get instance number for DSPI module.
  75. *
  76. * This is not a public API and it's extern from fsl_dspi.c.
  77. *
  78. * @param base DSPI peripheral base address
  79. */
  80. extern uint32_t DSPI_GetInstance(SPI_Type *base);
  81. /***********************************************************************************************************************
  82. * Variables
  83. ***********************************************************************************************************************/
  84. /*! @brief Pointers to dspi edma handles for each instance. */
  85. static dspi_master_edma_private_handle_t s_dspiMasterEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT];
  86. static dspi_slave_edma_private_handle_t s_dspiSlaveEdmaPrivateHandle[FSL_FEATURE_SOC_DSPI_COUNT];
  87. /*! @brief Global variable for dummy data value setting. */
  88. extern volatile uint8_t s_dummyData[];
  89. /***********************************************************************************************************************
  90. * Code
  91. ***********************************************************************************************************************/
  92. void DSPI_MasterTransferCreateHandleEDMA(SPI_Type *base,
  93. dspi_master_edma_handle_t *handle,
  94. dspi_master_edma_transfer_callback_t callback,
  95. void *userData,
  96. edma_handle_t *edmaRxRegToRxDataHandle,
  97. edma_handle_t *edmaTxDataToIntermediaryHandle,
  98. edma_handle_t *edmaIntermediaryToTxRegHandle)
  99. {
  100. assert(handle);
  101. assert(edmaRxRegToRxDataHandle);
  102. #if (!(defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET))
  103. assert(edmaTxDataToIntermediaryHandle);
  104. #endif
  105. assert(edmaIntermediaryToTxRegHandle);
  106. /* Zero the handle. */
  107. memset(handle, 0, sizeof(*handle));
  108. uint32_t instance = DSPI_GetInstance(base);
  109. s_dspiMasterEdmaPrivateHandle[instance].base = base;
  110. s_dspiMasterEdmaPrivateHandle[instance].handle = handle;
  111. handle->callback = callback;
  112. handle->userData = userData;
  113. handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
  114. handle->edmaTxDataToIntermediaryHandle = edmaTxDataToIntermediaryHandle;
  115. handle->edmaIntermediaryToTxRegHandle = edmaIntermediaryToTxRegHandle;
  116. }
  117. status_t DSPI_MasterTransferEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, dspi_transfer_t *transfer)
  118. {
  119. assert(handle);
  120. assert(transfer);
  121. /* If the transfer count is zero, then return immediately.*/
  122. if (transfer->dataSize == 0)
  123. {
  124. return kStatus_InvalidArgument;
  125. }
  126. /* If both send buffer and receive buffer is null */
  127. if ((!(transfer->txData)) && (!(transfer->rxData)))
  128. {
  129. return kStatus_InvalidArgument;
  130. }
  131. /* Check that we're not busy.*/
  132. if (handle->state == kDSPI_Busy)
  133. {
  134. return kStatus_DSPI_Busy;
  135. }
  136. handle->state = kDSPI_Busy;
  137. uint32_t instance = DSPI_GetInstance(base);
  138. uint16_t wordToSend = 0;
  139. uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)];
  140. uint8_t dataAlreadyFed = 0;
  141. uint8_t dataFedMax = 2;
  142. uint32_t rxAddr = DSPI_GetRxRegisterAddress(base);
  143. uint32_t txAddr = DSPI_MasterGetTxRegisterAddress(base);
  144. edma_tcd_t *softwareTCD = (edma_tcd_t *)((uint32_t)(&handle->dspiSoftwareTCD[1]) & (~0x1FU));
  145. edma_transfer_config_t transferConfigA;
  146. edma_transfer_config_t transferConfigB;
  147. handle->txBuffIfNull = ((uint32_t)dummyData << 8) | dummyData;
  148. dspi_command_data_config_t commandStruct;
  149. DSPI_StopTransfer(base);
  150. DSPI_FlushFifo(base, true, true);
  151. DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
  152. commandStruct.whichPcs =
  153. (dspi_which_pcs_t)(1U << ((transfer->configFlags & DSPI_MASTER_PCS_MASK) >> DSPI_MASTER_PCS_SHIFT));
  154. commandStruct.isEndOfQueue = false;
  155. commandStruct.clearTransferCount = false;
  156. commandStruct.whichCtar =
  157. (dspi_ctar_selection_t)((transfer->configFlags & DSPI_MASTER_CTAR_MASK) >> DSPI_MASTER_CTAR_SHIFT);
  158. commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterPcsContinuous);
  159. handle->command = DSPI_MasterGetFormattedCommand(&(commandStruct));
  160. commandStruct.isEndOfQueue = true;
  161. commandStruct.isPcsContinuous = (bool)(transfer->configFlags & kDSPI_MasterActiveAfterTransfer);
  162. handle->lastCommand = DSPI_MasterGetFormattedCommand(&(commandStruct));
  163. handle->bitsPerFrame = ((base->CTAR[commandStruct.whichCtar] & SPI_CTAR_FMSZ_MASK) >> SPI_CTAR_FMSZ_SHIFT) + 1;
  164. if ((base->MCR & SPI_MCR_DIS_RXF_MASK) || (base->MCR & SPI_MCR_DIS_TXF_MASK))
  165. {
  166. handle->fifoSize = 1;
  167. }
  168. else
  169. {
  170. handle->fifoSize = FSL_FEATURE_DSPI_FIFO_SIZEn(base);
  171. }
  172. handle->txData = transfer->txData;
  173. handle->rxData = transfer->rxData;
  174. handle->remainingSendByteCount = transfer->dataSize;
  175. handle->remainingReceiveByteCount = transfer->dataSize;
  176. handle->totalByteCount = transfer->dataSize;
  177. /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer
  178. * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame
  179. */
  180. uint32_t limited_size = 0;
  181. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  182. {
  183. limited_size = 32767u;
  184. }
  185. else
  186. {
  187. limited_size = 511u;
  188. }
  189. if (handle->bitsPerFrame > 8)
  190. {
  191. if (transfer->dataSize > (limited_size << 1u))
  192. {
  193. handle->state = kDSPI_Idle;
  194. return kStatus_DSPI_OutOfRange;
  195. }
  196. }
  197. else
  198. {
  199. if (transfer->dataSize > limited_size)
  200. {
  201. handle->state = kDSPI_Idle;
  202. return kStatus_DSPI_OutOfRange;
  203. }
  204. }
  205. /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */
  206. if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1))
  207. {
  208. handle->state = kDSPI_Idle;
  209. return kStatus_InvalidArgument;
  210. }
  211. DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  212. EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiMasterCallback,
  213. &s_dspiMasterEdmaPrivateHandle[instance]);
  214. /*
  215. (1)For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_B-> channel_C.
  216. channel_A minor link to channel_B , channel_B minor link to channel_C.
  217. Already pushed 1 or 2 data in SPI_PUSHR , then start the DMA tansfer.
  218. channel_A:SPI_POPR to rxData,
  219. channel_B:next txData to handle->command (low 16 bits),
  220. channel_C:handle->command (32 bits) to SPI_PUSHR, and use the scatter/gather to transfer the last data
  221. (handle->lastCommand to SPI_PUSHR).
  222. (2)For DSPI instances with separate RX and TX DMA requests:
  223. Rx DMA request -> channel_A
  224. Tx DMA request -> channel_C -> channel_B .
  225. channel_C major link to channel_B.
  226. So need prepare the first data in "intermediary" before the DMA
  227. transfer and then channel_B is used to prepare the next data to "intermediary"
  228. channel_A:SPI_POPR to rxData,
  229. channel_C: handle->command (32 bits) to SPI_PUSHR,
  230. channel_B: next txData to handle->command (low 16 bits), and use the scatter/gather to prepare the last data
  231. (handle->lastCommand to handle->Command).
  232. */
  233. /*If dspi has separate dma request , prepare the first data in "intermediary" .
  234. else (dspi has shared dma request) , send first 2 data if there is fifo or send first 1 data if there is no fifo*/
  235. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  236. {
  237. /* For DSPI instances with separate RX/TX DMA requests, we'll use the TX DMA request to
  238. * trigger the TX DMA channel and RX DMA request to trigger the RX DMA channel
  239. */
  240. /*Prepare the firt data*/
  241. if (handle->bitsPerFrame > 8)
  242. {
  243. /* If it's the last word */
  244. if (handle->remainingSendByteCount <= 2)
  245. {
  246. if (handle->txData)
  247. {
  248. wordToSend = *(handle->txData);
  249. ++handle->txData; /* increment to next data byte */
  250. wordToSend |= (unsigned)(*(handle->txData)) << 8U;
  251. }
  252. else
  253. {
  254. wordToSend = ((uint32_t)dummyData << 8) | dummyData;
  255. }
  256. handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
  257. handle->command = handle->lastCommand;
  258. }
  259. else /* For all words except the last word , frame > 8bits */
  260. {
  261. if (handle->txData)
  262. {
  263. wordToSend = *(handle->txData);
  264. ++handle->txData; /* increment to next data byte */
  265. wordToSend |= (unsigned)(*(handle->txData)) << 8U;
  266. ++handle->txData; /* increment to next data byte */
  267. }
  268. else
  269. {
  270. wordToSend = ((uint32_t)dummyData << 8) | dummyData;
  271. }
  272. handle->command = (handle->command & 0xffff0000U) | wordToSend;
  273. }
  274. }
  275. else /* Optimized for bits/frame less than or equal to one byte. */
  276. {
  277. if (handle->txData)
  278. {
  279. wordToSend = *(handle->txData);
  280. ++handle->txData; /* increment to next data word*/
  281. }
  282. else
  283. {
  284. wordToSend = dummyData;
  285. }
  286. if (handle->remainingSendByteCount == 1)
  287. {
  288. handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
  289. handle->command = handle->lastCommand;
  290. }
  291. else
  292. {
  293. handle->command = (handle->command & 0xffff0000U) | wordToSend;
  294. }
  295. }
  296. }
  297. else /*dspi has shared dma request*/
  298. {
  299. /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to
  300. * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel.
  301. */
  302. /* If bits/frame is greater than one byte */
  303. if (handle->bitsPerFrame > 8)
  304. {
  305. while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
  306. {
  307. if (handle->remainingSendByteCount <= 2)
  308. {
  309. if (handle->txData)
  310. {
  311. wordToSend = *(handle->txData);
  312. ++handle->txData;
  313. wordToSend |= (unsigned)(*(handle->txData)) << 8U;
  314. }
  315. else
  316. {
  317. wordToSend = ((uint32_t)dummyData << 8) | dummyData;
  318. }
  319. handle->remainingSendByteCount = 0;
  320. base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend;
  321. }
  322. /* For all words except the last word */
  323. else
  324. {
  325. if (handle->txData)
  326. {
  327. wordToSend = *(handle->txData);
  328. ++handle->txData;
  329. wordToSend |= (unsigned)(*(handle->txData)) << 8U;
  330. ++handle->txData;
  331. }
  332. else
  333. {
  334. wordToSend = ((uint32_t)dummyData << 8) | dummyData;
  335. }
  336. handle->remainingSendByteCount -= 2;
  337. base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
  338. }
  339. /* Try to clear the TFFF; if the TX FIFO is full this will clear */
  340. DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
  341. dataAlreadyFed += 2;
  342. /* exit loop if send count is zero, else update local variables for next loop */
  343. if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2)))
  344. {
  345. break;
  346. }
  347. } /* End of TX FIFO fill while loop */
  348. }
  349. else /* Optimized for bits/frame less than or equal to one byte. */
  350. {
  351. while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
  352. {
  353. if (handle->txData)
  354. {
  355. wordToSend = *(handle->txData);
  356. ++handle->txData;
  357. }
  358. else
  359. {
  360. wordToSend = dummyData;
  361. }
  362. if (handle->remainingSendByteCount == 1)
  363. {
  364. base->PUSHR = (handle->lastCommand & 0xffff0000U) | wordToSend;
  365. }
  366. else
  367. {
  368. base->PUSHR = (handle->command & 0xffff0000U) | wordToSend;
  369. }
  370. /* Try to clear the TFFF; if the TX FIFO is full this will clear */
  371. DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
  372. --handle->remainingSendByteCount;
  373. dataAlreadyFed++;
  374. /* exit loop if send count is zero, else update local variables for next loop */
  375. if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax))
  376. {
  377. break;
  378. }
  379. } /* End of TX FIFO fill while loop */
  380. }
  381. }
  382. /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer(rxData)*/
  383. EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
  384. transferConfigA.srcAddr = (uint32_t)rxAddr;
  385. transferConfigA.srcOffset = 0;
  386. if (handle->rxData)
  387. {
  388. transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]);
  389. transferConfigA.destOffset = 1;
  390. }
  391. else
  392. {
  393. transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull);
  394. transferConfigA.destOffset = 0;
  395. }
  396. transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes;
  397. if (handle->bitsPerFrame <= 8)
  398. {
  399. transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes;
  400. transferConfigA.minorLoopBytes = 1;
  401. transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount;
  402. }
  403. else
  404. {
  405. transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes;
  406. transferConfigA.minorLoopBytes = 2;
  407. transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2;
  408. }
  409. /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
  410. handle->nbytes = transferConfigA.minorLoopBytes;
  411. EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  412. &transferConfigA, NULL);
  413. EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  414. kEDMA_MajorInterruptEnable);
  415. /*Calculate the last data : handle->lastCommand*/
  416. if (((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
  417. ((((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) ||
  418. ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8))) &&
  419. (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))))
  420. {
  421. if (handle->txData)
  422. {
  423. uint32_t bufferIndex = 0;
  424. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  425. {
  426. if (handle->bitsPerFrame <= 8)
  427. {
  428. bufferIndex = handle->remainingSendByteCount - 1;
  429. }
  430. else
  431. {
  432. bufferIndex = handle->remainingSendByteCount - 2;
  433. }
  434. }
  435. else
  436. {
  437. bufferIndex = handle->remainingSendByteCount;
  438. }
  439. if (handle->bitsPerFrame <= 8)
  440. {
  441. handle->lastCommand = (handle->lastCommand & 0xffff0000U) | handle->txData[bufferIndex - 1];
  442. }
  443. else
  444. {
  445. handle->lastCommand = (handle->lastCommand & 0xffff0000U) |
  446. ((uint32_t)handle->txData[bufferIndex - 1] << 8) |
  447. handle->txData[bufferIndex - 2];
  448. }
  449. }
  450. else
  451. {
  452. if (handle->bitsPerFrame <= 8)
  453. {
  454. wordToSend = dummyData;
  455. }
  456. else
  457. {
  458. wordToSend = ((uint32_t)dummyData << 8) | dummyData;
  459. }
  460. handle->lastCommand = (handle->lastCommand & 0xffff0000U) | wordToSend;
  461. }
  462. }
  463. /* The feature of GASKET is that the SPI supports 8-bit or 16-bit writes to the PUSH TX FIFO,
  464. * allowing a single write to the command word followed by multiple writes to the transmit word.
  465. * The TX FIFO will save the last command word written, and convert a 8-bit/16-bit write to the
  466. * transmit word into a 32-bit write that pushes both the command word and transmit word into
  467. * the TX FIFO (PUSH TX FIFO Register In Master Mode)
  468. * So, if this feature is supported, we can use use one channel to carry the receive data from
  469. * receive regsiter to user data buffer, use the other channel to carry the data from user data buffer
  470. * to transmit register,and use the scatter/gather function to prepare the last data.
  471. * That is to say, if GASKET feature is supported, we can use only two channels for tansferring data.
  472. */
  473. #if defined(FSL_FEATURE_DSPI_HAS_GASKET) && FSL_FEATURE_DSPI_HAS_GASKET
  474. /* For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data
  475. * (handle->lastCommand) to PUSHR register.
  476. */
  477. EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel);
  478. if ((1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) ||
  479. ((handle->remainingSendByteCount > 0) && (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))))
  480. {
  481. transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand);
  482. transferConfigB.destAddr = (uint32_t)txAddr;
  483. transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes;
  484. transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes;
  485. transferConfigB.srcOffset = 0;
  486. transferConfigB.destOffset = 0;
  487. transferConfigB.minorLoopBytes = 4;
  488. transferConfigB.majorLoopCounts = 1;
  489. EDMA_TcdReset(softwareTCD);
  490. EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL);
  491. }
  492. /*User_Send_Buffer(txData) to PUSHR register. */
  493. if (((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) ||
  494. ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8)))
  495. {
  496. if (handle->txData)
  497. {
  498. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  499. {
  500. /* For DSPI with separate RX and TX DMA requests, one frame data has been carry
  501. * to handle->command, so need to reduce the pointer of txData.
  502. */
  503. transferConfigB.srcAddr =
  504. (uint32_t)((uint8_t *)(handle->txData) - ((handle->bitsPerFrame <= 8) ? (1U) : (2U)));
  505. transferConfigB.srcOffset = 1;
  506. }
  507. else
  508. {
  509. /* For DSPI with shared RX and TX DMA requests, one or two frame data have been carry
  510. * to PUSHR register, so no need to change the pointer of txData.
  511. */
  512. transferConfigB.srcAddr = (uint32_t)((uint8_t *)(handle->txData));
  513. transferConfigB.srcOffset = 1;
  514. }
  515. }
  516. else
  517. {
  518. transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull);
  519. transferConfigB.srcOffset = 0;
  520. }
  521. transferConfigB.destAddr = (uint32_t)txAddr;
  522. transferConfigB.destOffset = 0;
  523. transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes;
  524. if (handle->bitsPerFrame <= 8)
  525. {
  526. transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes;
  527. transferConfigB.minorLoopBytes = 1;
  528. transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 1;
  529. }
  530. else
  531. {
  532. transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes;
  533. transferConfigB.minorLoopBytes = 2;
  534. transferConfigB.majorLoopCounts = (handle->remainingSendByteCount / 2) - 1;
  535. }
  536. EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
  537. handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, softwareTCD);
  538. }
  539. /* If only one word to transmit, only carry the lastcommand. */
  540. else
  541. {
  542. EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
  543. handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigB, NULL);
  544. }
  545. /*Start the EDMA channel_A , channel_C. */
  546. EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
  547. EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle);
  548. /* Set the channel link.
  549. * For DSPI instances with shared TX and RX DMA requests, setup channel minor link, first receive data from the
  550. * receive register, and then carry transmit data to PUSHER register.
  551. * For DSPI instance with separate TX and RX DMA requests, there is no need to set up channel link.
  552. */
  553. if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  554. {
  555. /*Set channel priority*/
  556. uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel;
  557. uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel;
  558. uint8_t t = 0;
  559. if (channelPriorityLow > channelPriorityHigh)
  560. {
  561. t = channelPriorityLow;
  562. channelPriorityLow = channelPriorityHigh;
  563. channelPriorityHigh = t;
  564. }
  565. edma_channel_Preemption_config_t preemption_config_t;
  566. preemption_config_t.enableChannelPreemption = true;
  567. preemption_config_t.enablePreemptAbility = true;
  568. preemption_config_t.channelPriority = channelPriorityLow;
  569. EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  570. &preemption_config_t);
  571. preemption_config_t.channelPriority = channelPriorityHigh;
  572. EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
  573. handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
  574. /*if there is Rx DMA request , carry the 32bits data (handle->command) to user data first , then link to
  575. channelC to carry the next data to PUSHER register.(txData to PUSHER) */
  576. if (handle->remainingSendByteCount > 0)
  577. {
  578. EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  579. kEDMA_MinorLink, handle->edmaIntermediaryToTxRegHandle->channel);
  580. }
  581. }
  582. DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  583. /* Setup control info to PUSHER register. */
  584. *((uint16_t *)&(base->PUSHR) + 1) = (handle->command >> 16U);
  585. #else
  586. /***channel_B *** used for carry the data from User_Send_Buffer to "intermediary" because the SPIx_PUSHR should
  587. write the 32bits at once time . Then use channel_C to carry the "intermediary" to SPIx_PUSHR. Note that the
  588. SPIx_PUSHR upper 16 bits are the "command" and the low 16bits are data */
  589. EDMA_ResetChannel(handle->edmaTxDataToIntermediaryHandle->base, handle->edmaTxDataToIntermediaryHandle->channel);
  590. /*For DSPI instances with separate RX and TX DMA requests: use the scatter/gather to prepare the last data
  591. * (handle->lastCommand) to handle->Command*/
  592. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  593. {
  594. transferConfigB.srcAddr = (uint32_t) & (handle->lastCommand);
  595. transferConfigB.destAddr = (uint32_t) & (handle->command);
  596. transferConfigB.srcTransferSize = kEDMA_TransferSize4Bytes;
  597. transferConfigB.destTransferSize = kEDMA_TransferSize4Bytes;
  598. transferConfigB.srcOffset = 0;
  599. transferConfigB.destOffset = 0;
  600. transferConfigB.minorLoopBytes = 4;
  601. transferConfigB.majorLoopCounts = 1;
  602. EDMA_TcdReset(softwareTCD);
  603. EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigB, NULL);
  604. }
  605. /*User_Send_Buffer(txData) to intermediary(handle->command)*/
  606. if (((((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame <= 8)) ||
  607. ((handle->remainingSendByteCount > 4) && (handle->bitsPerFrame > 8))) &&
  608. (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))) ||
  609. (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
  610. {
  611. if (handle->txData)
  612. {
  613. transferConfigB.srcAddr = (uint32_t)(handle->txData);
  614. transferConfigB.srcOffset = 1;
  615. }
  616. else
  617. {
  618. transferConfigB.srcAddr = (uint32_t)(&handle->txBuffIfNull);
  619. transferConfigB.srcOffset = 0;
  620. }
  621. transferConfigB.destAddr = (uint32_t)(&handle->command);
  622. transferConfigB.destOffset = 0;
  623. transferConfigB.srcTransferSize = kEDMA_TransferSize1Bytes;
  624. if (handle->bitsPerFrame <= 8)
  625. {
  626. transferConfigB.destTransferSize = kEDMA_TransferSize1Bytes;
  627. transferConfigB.minorLoopBytes = 1;
  628. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  629. {
  630. transferConfigB.majorLoopCounts = handle->remainingSendByteCount - 2;
  631. }
  632. else
  633. {
  634. /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is
  635. majorlink , the majorlink would not trigger the channel_C*/
  636. transferConfigB.majorLoopCounts = handle->remainingSendByteCount + 1;
  637. }
  638. }
  639. else
  640. {
  641. transferConfigB.destTransferSize = kEDMA_TransferSize2Bytes;
  642. transferConfigB.minorLoopBytes = 2;
  643. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  644. {
  645. transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 - 2;
  646. }
  647. else
  648. {
  649. /*Only enable channel_B minorlink to channel_C , so need to add one count due to the last time is
  650. * majorlink*/
  651. transferConfigB.majorLoopCounts = handle->remainingSendByteCount / 2 + 1;
  652. }
  653. }
  654. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  655. {
  656. EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
  657. handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, softwareTCD);
  658. EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base,
  659. handle->edmaIntermediaryToTxRegHandle->channel, false);
  660. }
  661. else
  662. {
  663. EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
  664. handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL);
  665. }
  666. }
  667. else
  668. {
  669. EDMA_SetTransferConfig(handle->edmaTxDataToIntermediaryHandle->base,
  670. handle->edmaTxDataToIntermediaryHandle->channel, &transferConfigB, NULL);
  671. }
  672. /***channel_C ***carry the "intermediary" to SPIx_PUSHR. used the edma Scatter Gather function on channel_C to
  673. handle the last data */
  674. edma_transfer_config_t transferConfigC;
  675. EDMA_ResetChannel(handle->edmaIntermediaryToTxRegHandle->base, handle->edmaIntermediaryToTxRegHandle->channel);
  676. /*For DSPI instances with shared RX/TX DMA requests: use the scatter/gather to prepare the last data
  677. * (handle->lastCommand) to SPI_PUSHR*/
  678. if (((1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)) && (handle->remainingSendByteCount > 0)))
  679. {
  680. transferConfigC.srcAddr = (uint32_t) & (handle->lastCommand);
  681. transferConfigC.destAddr = (uint32_t)txAddr;
  682. transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes;
  683. transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes;
  684. transferConfigC.srcOffset = 0;
  685. transferConfigC.destOffset = 0;
  686. transferConfigC.minorLoopBytes = 4;
  687. transferConfigC.majorLoopCounts = 1;
  688. EDMA_TcdReset(softwareTCD);
  689. EDMA_TcdSetTransferConfig(softwareTCD, &transferConfigC, NULL);
  690. }
  691. if (((handle->remainingSendByteCount > 1) && (handle->bitsPerFrame <= 8)) ||
  692. ((handle->remainingSendByteCount > 2) && (handle->bitsPerFrame > 8)) ||
  693. (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base)))
  694. {
  695. transferConfigC.srcAddr = (uint32_t)(&(handle->command));
  696. transferConfigC.destAddr = (uint32_t)txAddr;
  697. transferConfigC.srcTransferSize = kEDMA_TransferSize4Bytes;
  698. transferConfigC.destTransferSize = kEDMA_TransferSize4Bytes;
  699. transferConfigC.srcOffset = 0;
  700. transferConfigC.destOffset = 0;
  701. transferConfigC.minorLoopBytes = 4;
  702. if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  703. {
  704. if (handle->bitsPerFrame <= 8)
  705. {
  706. transferConfigC.majorLoopCounts = handle->remainingSendByteCount - 1;
  707. }
  708. else
  709. {
  710. transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2 - 1;
  711. }
  712. EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
  713. handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, softwareTCD);
  714. }
  715. else
  716. {
  717. transferConfigC.majorLoopCounts = 1;
  718. EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
  719. handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL);
  720. }
  721. EDMA_EnableAutoStopRequest(handle->edmaIntermediaryToTxRegHandle->base,
  722. handle->edmaIntermediaryToTxRegHandle->channel, false);
  723. }
  724. else
  725. {
  726. EDMA_SetTransferConfig(handle->edmaIntermediaryToTxRegHandle->base,
  727. handle->edmaIntermediaryToTxRegHandle->channel, &transferConfigC, NULL);
  728. }
  729. /*Start the EDMA channel_A , channel_B , channel_C transfer*/
  730. EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
  731. EDMA_StartTransfer(handle->edmaTxDataToIntermediaryHandle);
  732. EDMA_StartTransfer(handle->edmaIntermediaryToTxRegHandle);
  733. /*Set channel priority*/
  734. uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel;
  735. uint8_t channelPriorityMid = handle->edmaTxDataToIntermediaryHandle->channel;
  736. uint8_t channelPriorityHigh = handle->edmaIntermediaryToTxRegHandle->channel;
  737. uint8_t t = 0;
  738. if (channelPriorityLow > channelPriorityMid)
  739. {
  740. t = channelPriorityLow;
  741. channelPriorityLow = channelPriorityMid;
  742. channelPriorityMid = t;
  743. }
  744. if (channelPriorityLow > channelPriorityHigh)
  745. {
  746. t = channelPriorityLow;
  747. channelPriorityLow = channelPriorityHigh;
  748. channelPriorityHigh = t;
  749. }
  750. if (channelPriorityMid > channelPriorityHigh)
  751. {
  752. t = channelPriorityMid;
  753. channelPriorityMid = channelPriorityHigh;
  754. channelPriorityHigh = t;
  755. }
  756. edma_channel_Preemption_config_t preemption_config_t;
  757. preemption_config_t.enableChannelPreemption = true;
  758. preemption_config_t.enablePreemptAbility = true;
  759. preemption_config_t.channelPriority = channelPriorityLow;
  760. if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  761. {
  762. EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  763. &preemption_config_t);
  764. preemption_config_t.channelPriority = channelPriorityMid;
  765. EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base,
  766. handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t);
  767. preemption_config_t.channelPriority = channelPriorityHigh;
  768. EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
  769. handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
  770. }
  771. else
  772. {
  773. EDMA_SetChannelPreemptionConfig(handle->edmaIntermediaryToTxRegHandle->base,
  774. handle->edmaIntermediaryToTxRegHandle->channel, &preemption_config_t);
  775. preemption_config_t.channelPriority = channelPriorityMid;
  776. EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToIntermediaryHandle->base,
  777. handle->edmaTxDataToIntermediaryHandle->channel, &preemption_config_t);
  778. preemption_config_t.channelPriority = channelPriorityHigh;
  779. EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  780. &preemption_config_t);
  781. }
  782. /*Set the channel link.*/
  783. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  784. {
  785. /*if there is Tx DMA request , carry the 32bits data (handle->command) to PUSHR first , then link to channelB
  786. to prepare the next 32bits data (txData to handle->command) */
  787. if (handle->remainingSendByteCount > 1)
  788. {
  789. EDMA_SetChannelLink(handle->edmaIntermediaryToTxRegHandle->base,
  790. handle->edmaIntermediaryToTxRegHandle->channel, kEDMA_MajorLink,
  791. handle->edmaTxDataToIntermediaryHandle->channel);
  792. }
  793. DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  794. }
  795. else
  796. {
  797. if (handle->remainingSendByteCount > 0)
  798. {
  799. EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  800. kEDMA_MinorLink, handle->edmaTxDataToIntermediaryHandle->channel);
  801. EDMA_SetChannelLink(handle->edmaTxDataToIntermediaryHandle->base,
  802. handle->edmaTxDataToIntermediaryHandle->channel, kEDMA_MinorLink,
  803. handle->edmaIntermediaryToTxRegHandle->channel);
  804. }
  805. DSPI_EnableDMA(base, kDSPI_RxDmaEnable);
  806. }
  807. #endif
  808. DSPI_StartTransfer(base);
  809. return kStatus_Success;
  810. }
  811. status_t DSPI_MasterHalfDuplexTransferEDMA(SPI_Type *base,
  812. dspi_master_edma_handle_t *handle,
  813. dspi_half_duplex_transfer_t *xfer)
  814. {
  815. assert(xfer);
  816. assert(handle);
  817. dspi_transfer_t tempXfer = {0};
  818. status_t status;
  819. if (xfer->isTransmitFirst)
  820. {
  821. tempXfer.txData = xfer->txData;
  822. tempXfer.rxData = NULL;
  823. tempXfer.dataSize = xfer->txDataSize;
  824. }
  825. else
  826. {
  827. tempXfer.txData = NULL;
  828. tempXfer.rxData = xfer->rxData;
  829. tempXfer.dataSize = xfer->rxDataSize;
  830. }
  831. /* If the pcs pin keep assert between transmit and receive. */
  832. if (xfer->isPcsAssertInTransfer)
  833. {
  834. tempXfer.configFlags = (xfer->configFlags) | kDSPI_MasterActiveAfterTransfer;
  835. }
  836. else
  837. {
  838. tempXfer.configFlags = (xfer->configFlags) & (uint32_t)(~kDSPI_MasterActiveAfterTransfer);
  839. }
  840. status = DSPI_MasterTransferBlocking(base, &tempXfer);
  841. if (status != kStatus_Success)
  842. {
  843. return status;
  844. }
  845. if (xfer->isTransmitFirst)
  846. {
  847. tempXfer.txData = NULL;
  848. tempXfer.rxData = xfer->rxData;
  849. tempXfer.dataSize = xfer->rxDataSize;
  850. }
  851. else
  852. {
  853. tempXfer.txData = xfer->txData;
  854. tempXfer.rxData = NULL;
  855. tempXfer.dataSize = xfer->txDataSize;
  856. }
  857. tempXfer.configFlags = xfer->configFlags;
  858. status = DSPI_MasterTransferEDMA(base, handle, &tempXfer);
  859. return status;
  860. }
  861. static void EDMA_DspiMasterCallback(edma_handle_t *edmaHandle,
  862. void *g_dspiEdmaPrivateHandle,
  863. bool transferDone,
  864. uint32_t tcds)
  865. {
  866. assert(edmaHandle);
  867. assert(g_dspiEdmaPrivateHandle);
  868. dspi_master_edma_private_handle_t *dspiEdmaPrivateHandle;
  869. dspiEdmaPrivateHandle = (dspi_master_edma_private_handle_t *)g_dspiEdmaPrivateHandle;
  870. DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  871. dspiEdmaPrivateHandle->handle->state = kDSPI_Idle;
  872. if (dspiEdmaPrivateHandle->handle->callback)
  873. {
  874. dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle,
  875. kStatus_Success, dspiEdmaPrivateHandle->handle->userData);
  876. }
  877. }
  878. void DSPI_MasterTransferAbortEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle)
  879. {
  880. assert(handle);
  881. DSPI_StopTransfer(base);
  882. DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  883. EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
  884. EDMA_AbortTransfer(handle->edmaTxDataToIntermediaryHandle);
  885. EDMA_AbortTransfer(handle->edmaIntermediaryToTxRegHandle);
  886. handle->state = kDSPI_Idle;
  887. }
  888. status_t DSPI_MasterTransferGetCountEDMA(SPI_Type *base, dspi_master_edma_handle_t *handle, size_t *count)
  889. {
  890. assert(handle);
  891. if (!count)
  892. {
  893. return kStatus_InvalidArgument;
  894. }
  895. /* Catch when there is not an active transfer. */
  896. if (handle->state != kDSPI_Busy)
  897. {
  898. *count = 0;
  899. return kStatus_NoTransferInProgress;
  900. }
  901. size_t bytes;
  902. bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
  903. handle->edmaRxRegToRxDataHandle->channel);
  904. *count = handle->totalByteCount - bytes;
  905. return kStatus_Success;
  906. }
  907. void DSPI_SlaveTransferCreateHandleEDMA(SPI_Type *base,
  908. dspi_slave_edma_handle_t *handle,
  909. dspi_slave_edma_transfer_callback_t callback,
  910. void *userData,
  911. edma_handle_t *edmaRxRegToRxDataHandle,
  912. edma_handle_t *edmaTxDataToTxRegHandle)
  913. {
  914. assert(handle);
  915. assert(edmaRxRegToRxDataHandle);
  916. assert(edmaTxDataToTxRegHandle);
  917. /* Zero the handle. */
  918. memset(handle, 0, sizeof(*handle));
  919. uint32_t instance = DSPI_GetInstance(base);
  920. s_dspiSlaveEdmaPrivateHandle[instance].base = base;
  921. s_dspiSlaveEdmaPrivateHandle[instance].handle = handle;
  922. handle->callback = callback;
  923. handle->userData = userData;
  924. handle->edmaRxRegToRxDataHandle = edmaRxRegToRxDataHandle;
  925. handle->edmaTxDataToTxRegHandle = edmaTxDataToTxRegHandle;
  926. }
  927. status_t DSPI_SlaveTransferEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, dspi_transfer_t *transfer)
  928. {
  929. assert(handle);
  930. assert(transfer);
  931. /* If send/receive length is zero */
  932. if (transfer->dataSize == 0)
  933. {
  934. return kStatus_InvalidArgument;
  935. }
  936. /* If both send buffer and receive buffer is null */
  937. if ((!(transfer->txData)) && (!(transfer->rxData)))
  938. {
  939. return kStatus_InvalidArgument;
  940. }
  941. /* Check that we're not busy.*/
  942. if (handle->state == kDSPI_Busy)
  943. {
  944. return kStatus_DSPI_Busy;
  945. }
  946. handle->state = kDSPI_Busy;
  947. uint32_t instance = DSPI_GetInstance(base);
  948. uint8_t whichCtar = (transfer->configFlags & DSPI_SLAVE_CTAR_MASK) >> DSPI_SLAVE_CTAR_SHIFT;
  949. handle->bitsPerFrame =
  950. (((base->CTAR_SLAVE[whichCtar]) & SPI_CTAR_SLAVE_FMSZ_MASK) >> SPI_CTAR_SLAVE_FMSZ_SHIFT) + 1;
  951. /* If using a shared RX/TX DMA request, then this limits the amount of data we can transfer
  952. * due to the linked channel. The max bytes is 511 if 8-bit/frame or 1022 if 16-bit/frame
  953. */
  954. uint32_t limited_size = 0;
  955. if (1 == FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  956. {
  957. limited_size = 32767u;
  958. }
  959. else
  960. {
  961. limited_size = 511u;
  962. }
  963. if (handle->bitsPerFrame > 8)
  964. {
  965. if (transfer->dataSize > (limited_size << 1u))
  966. {
  967. handle->state = kDSPI_Idle;
  968. return kStatus_DSPI_OutOfRange;
  969. }
  970. }
  971. else
  972. {
  973. if (transfer->dataSize > limited_size)
  974. {
  975. handle->state = kDSPI_Idle;
  976. return kStatus_DSPI_OutOfRange;
  977. }
  978. }
  979. /*The data size should be even if the bitsPerFrame is greater than 8 (that is 2 bytes per frame in dspi) */
  980. if ((handle->bitsPerFrame > 8) && (transfer->dataSize & 0x1))
  981. {
  982. handle->state = kDSPI_Idle;
  983. return kStatus_InvalidArgument;
  984. }
  985. EDMA_SetCallback(handle->edmaRxRegToRxDataHandle, EDMA_DspiSlaveCallback, &s_dspiSlaveEdmaPrivateHandle[instance]);
  986. /* Store transfer information */
  987. handle->txData = transfer->txData;
  988. handle->rxData = transfer->rxData;
  989. handle->remainingSendByteCount = transfer->dataSize;
  990. handle->remainingReceiveByteCount = transfer->dataSize;
  991. handle->totalByteCount = transfer->dataSize;
  992. uint16_t wordToSend = 0;
  993. uint8_t dummyData = s_dummyData[DSPI_GetInstance(base)];
  994. uint8_t dataAlreadyFed = 0;
  995. uint8_t dataFedMax = 2;
  996. uint32_t rxAddr = DSPI_GetRxRegisterAddress(base);
  997. uint32_t txAddr = DSPI_SlaveGetTxRegisterAddress(base);
  998. edma_transfer_config_t transferConfigA;
  999. edma_transfer_config_t transferConfigC;
  1000. DSPI_StopTransfer(base);
  1001. DSPI_FlushFifo(base, true, true);
  1002. DSPI_ClearStatusFlags(base, kDSPI_AllStatusFlag);
  1003. DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  1004. DSPI_StartTransfer(base);
  1005. /*if dspi has separate dma request , need not prepare data first .
  1006. else (dspi has shared dma request) , send first 2 data into fifo if there is fifo or send first 1 data to
  1007. slaveGetTxRegister if there is no fifo*/
  1008. if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  1009. {
  1010. /* For DSPI instances with shared RX/TX DMA requests, we'll use the RX DMA request to
  1011. * trigger ongoing transfers and will link to the TX DMA channel from the RX DMA channel.
  1012. */
  1013. /* If bits/frame is greater than one byte */
  1014. if (handle->bitsPerFrame > 8)
  1015. {
  1016. while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
  1017. {
  1018. if (handle->txData)
  1019. {
  1020. wordToSend = *(handle->txData);
  1021. ++handle->txData; /* Increment to next data byte */
  1022. wordToSend |= (unsigned)(*(handle->txData)) << 8U;
  1023. ++handle->txData; /* Increment to next data byte */
  1024. }
  1025. else
  1026. {
  1027. wordToSend = ((uint32_t)dummyData << 8) | dummyData;
  1028. }
  1029. handle->remainingSendByteCount -= 2; /* decrement remainingSendByteCount by 2 */
  1030. base->PUSHR_SLAVE = wordToSend;
  1031. /* Try to clear the TFFF; if the TX FIFO is full this will clear */
  1032. DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
  1033. dataAlreadyFed += 2;
  1034. /* Exit loop if send count is zero, else update local variables for next loop */
  1035. if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == (dataFedMax * 2)))
  1036. {
  1037. break;
  1038. }
  1039. } /* End of TX FIFO fill while loop */
  1040. }
  1041. else /* Optimized for bits/frame less than or equal to one byte. */
  1042. {
  1043. while (DSPI_GetStatusFlags(base) & kDSPI_TxFifoFillRequestFlag)
  1044. {
  1045. if (handle->txData)
  1046. {
  1047. wordToSend = *(handle->txData);
  1048. /* Increment to next data word*/
  1049. ++handle->txData;
  1050. }
  1051. else
  1052. {
  1053. wordToSend = dummyData;
  1054. }
  1055. base->PUSHR_SLAVE = wordToSend;
  1056. /* Try to clear the TFFF; if the TX FIFO is full this will clear */
  1057. DSPI_ClearStatusFlags(base, kDSPI_TxFifoFillRequestFlag);
  1058. /* Decrement remainingSendByteCount*/
  1059. --handle->remainingSendByteCount;
  1060. dataAlreadyFed++;
  1061. /* Exit loop if send count is zero, else update local variables for next loop */
  1062. if ((handle->remainingSendByteCount == 0) || (dataAlreadyFed == dataFedMax))
  1063. {
  1064. break;
  1065. }
  1066. } /* End of TX FIFO fill while loop */
  1067. }
  1068. }
  1069. /***channel_A *** used for carry the data from Rx_Data_Register(POPR) to User_Receive_Buffer*/
  1070. if (handle->remainingReceiveByteCount > 0)
  1071. {
  1072. EDMA_ResetChannel(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel);
  1073. transferConfigA.srcAddr = (uint32_t)rxAddr;
  1074. transferConfigA.srcOffset = 0;
  1075. if (handle->rxData)
  1076. {
  1077. transferConfigA.destAddr = (uint32_t) & (handle->rxData[0]);
  1078. transferConfigA.destOffset = 1;
  1079. }
  1080. else
  1081. {
  1082. transferConfigA.destAddr = (uint32_t) & (handle->rxBuffIfNull);
  1083. transferConfigA.destOffset = 0;
  1084. }
  1085. transferConfigA.destTransferSize = kEDMA_TransferSize1Bytes;
  1086. if (handle->bitsPerFrame <= 8)
  1087. {
  1088. transferConfigA.srcTransferSize = kEDMA_TransferSize1Bytes;
  1089. transferConfigA.minorLoopBytes = 1;
  1090. transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount;
  1091. }
  1092. else
  1093. {
  1094. transferConfigA.srcTransferSize = kEDMA_TransferSize2Bytes;
  1095. transferConfigA.minorLoopBytes = 2;
  1096. transferConfigA.majorLoopCounts = handle->remainingReceiveByteCount / 2;
  1097. }
  1098. /* Store the initially configured eDMA minor byte transfer count into the DSPI handle */
  1099. handle->nbytes = transferConfigA.minorLoopBytes;
  1100. EDMA_SetTransferConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  1101. &transferConfigA, NULL);
  1102. EDMA_EnableChannelInterrupts(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  1103. kEDMA_MajorInterruptEnable);
  1104. }
  1105. if (handle->remainingSendByteCount > 0)
  1106. {
  1107. /***channel_C *** used for carry the data from User_Send_Buffer to Tx_Data_Register(PUSHR_SLAVE)*/
  1108. EDMA_ResetChannel(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel);
  1109. transferConfigC.destAddr = (uint32_t)txAddr;
  1110. transferConfigC.destOffset = 0;
  1111. if (handle->txData)
  1112. {
  1113. transferConfigC.srcAddr = (uint32_t)(&(handle->txData[0]));
  1114. transferConfigC.srcOffset = 1;
  1115. }
  1116. else
  1117. {
  1118. transferConfigC.srcAddr = (uint32_t)(&handle->txBuffIfNull);
  1119. transferConfigC.srcOffset = 0;
  1120. if (handle->bitsPerFrame <= 8)
  1121. {
  1122. handle->txBuffIfNull = dummyData;
  1123. }
  1124. else
  1125. {
  1126. handle->txBuffIfNull = ((uint32_t)dummyData << 8) | dummyData;
  1127. }
  1128. }
  1129. transferConfigC.srcTransferSize = kEDMA_TransferSize1Bytes;
  1130. if (handle->bitsPerFrame <= 8)
  1131. {
  1132. transferConfigC.destTransferSize = kEDMA_TransferSize1Bytes;
  1133. transferConfigC.minorLoopBytes = 1;
  1134. transferConfigC.majorLoopCounts = handle->remainingSendByteCount;
  1135. }
  1136. else
  1137. {
  1138. transferConfigC.destTransferSize = kEDMA_TransferSize2Bytes;
  1139. transferConfigC.minorLoopBytes = 2;
  1140. transferConfigC.majorLoopCounts = handle->remainingSendByteCount / 2;
  1141. }
  1142. EDMA_SetTransferConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
  1143. &transferConfigC, NULL);
  1144. EDMA_StartTransfer(handle->edmaTxDataToTxRegHandle);
  1145. }
  1146. EDMA_StartTransfer(handle->edmaRxRegToRxDataHandle);
  1147. /*Set channel priority*/
  1148. uint8_t channelPriorityLow = handle->edmaRxRegToRxDataHandle->channel;
  1149. uint8_t channelPriorityHigh = handle->edmaTxDataToTxRegHandle->channel;
  1150. uint8_t t = 0;
  1151. if (channelPriorityLow > channelPriorityHigh)
  1152. {
  1153. t = channelPriorityLow;
  1154. channelPriorityLow = channelPriorityHigh;
  1155. channelPriorityHigh = t;
  1156. }
  1157. edma_channel_Preemption_config_t preemption_config_t;
  1158. preemption_config_t.enableChannelPreemption = true;
  1159. preemption_config_t.enablePreemptAbility = true;
  1160. preemption_config_t.channelPriority = channelPriorityLow;
  1161. if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  1162. {
  1163. EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  1164. &preemption_config_t);
  1165. preemption_config_t.channelPriority = channelPriorityHigh;
  1166. EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
  1167. &preemption_config_t);
  1168. }
  1169. else
  1170. {
  1171. EDMA_SetChannelPreemptionConfig(handle->edmaTxDataToTxRegHandle->base, handle->edmaTxDataToTxRegHandle->channel,
  1172. &preemption_config_t);
  1173. preemption_config_t.channelPriority = channelPriorityHigh;
  1174. EDMA_SetChannelPreemptionConfig(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  1175. &preemption_config_t);
  1176. }
  1177. /*Set the channel link.
  1178. For DSPI instances with shared RX/TX DMA requests: Rx DMA request -> channel_A -> channel_C.
  1179. For DSPI instances with separate RX and TX DMA requests:
  1180. Rx DMA request -> channel_A
  1181. Tx DMA request -> channel_C */
  1182. if (1 != FSL_FEATURE_DSPI_HAS_SEPARATE_DMA_RX_TX_REQn(base))
  1183. {
  1184. if (handle->remainingSendByteCount > 0)
  1185. {
  1186. EDMA_SetChannelLink(handle->edmaRxRegToRxDataHandle->base, handle->edmaRxRegToRxDataHandle->channel,
  1187. kEDMA_MinorLink, handle->edmaTxDataToTxRegHandle->channel);
  1188. }
  1189. DSPI_EnableDMA(base, kDSPI_RxDmaEnable);
  1190. }
  1191. else
  1192. {
  1193. DSPI_EnableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  1194. }
  1195. return kStatus_Success;
  1196. }
  1197. static void EDMA_DspiSlaveCallback(edma_handle_t *edmaHandle,
  1198. void *g_dspiEdmaPrivateHandle,
  1199. bool transferDone,
  1200. uint32_t tcds)
  1201. {
  1202. assert(edmaHandle);
  1203. assert(g_dspiEdmaPrivateHandle);
  1204. dspi_slave_edma_private_handle_t *dspiEdmaPrivateHandle;
  1205. dspiEdmaPrivateHandle = (dspi_slave_edma_private_handle_t *)g_dspiEdmaPrivateHandle;
  1206. DSPI_DisableDMA((dspiEdmaPrivateHandle->base), kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  1207. dspiEdmaPrivateHandle->handle->state = kDSPI_Idle;
  1208. if (dspiEdmaPrivateHandle->handle->callback)
  1209. {
  1210. dspiEdmaPrivateHandle->handle->callback(dspiEdmaPrivateHandle->base, dspiEdmaPrivateHandle->handle,
  1211. kStatus_Success, dspiEdmaPrivateHandle->handle->userData);
  1212. }
  1213. }
  1214. void DSPI_SlaveTransferAbortEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle)
  1215. {
  1216. assert(handle);
  1217. DSPI_StopTransfer(base);
  1218. DSPI_DisableDMA(base, kDSPI_RxDmaEnable | kDSPI_TxDmaEnable);
  1219. EDMA_AbortTransfer(handle->edmaRxRegToRxDataHandle);
  1220. EDMA_AbortTransfer(handle->edmaTxDataToTxRegHandle);
  1221. handle->state = kDSPI_Idle;
  1222. }
  1223. status_t DSPI_SlaveTransferGetCountEDMA(SPI_Type *base, dspi_slave_edma_handle_t *handle, size_t *count)
  1224. {
  1225. assert(handle);
  1226. if (!count)
  1227. {
  1228. return kStatus_InvalidArgument;
  1229. }
  1230. /* Catch when there is not an active transfer. */
  1231. if (handle->state != kDSPI_Busy)
  1232. {
  1233. *count = 0;
  1234. return kStatus_NoTransferInProgress;
  1235. }
  1236. size_t bytes;
  1237. bytes = (uint32_t)handle->nbytes * EDMA_GetRemainingMajorLoopCount(handle->edmaRxRegToRxDataHandle->base,
  1238. handle->edmaRxRegToRxDataHandle->channel);
  1239. *count = handle->totalByteCount - bytes;
  1240. return kStatus_Success;
  1241. }