Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

1531 linhas
62 KiB

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