fsl_i2s_dma.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2016, 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_dma.h"
  35. #include "fsl_i2s_dma.h"
  36. #include "fsl_flexcomm.h"
  37. #include <string.h>
  38. /*******************************************************************************
  39. * Definitions
  40. ******************************************************************************/
  41. /* Component ID definition, used by tools. */
  42. #ifndef FSL_COMPONENT_ID
  43. #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2s_dma"
  44. #endif
  45. #define DMA_MAX_TRANSFER_BYTES (DMA_MAX_TRANSFER_COUNT * sizeof(uint32_t))
  46. #define DMA_DESCRIPTORS (2U)
  47. /*<! @brief Structure for statically allocated private data. */
  48. typedef struct _i2s_dma_private_handle
  49. {
  50. I2S_Type *base; /*!< I2S base address */
  51. i2s_dma_handle_t *handle; /*!< I2S handle */
  52. volatile uint16_t enqueuedBytes[DMA_DESCRIPTORS]; /*!< Number of bytes being transferred by DMA descriptors */
  53. volatile uint8_t enqueuedBytesStart; /*!< First item in enqueuedBytes (for reading) */
  54. volatile uint8_t enqueuedBytesEnd; /*!< Last item in enqueuedBytes (for adding) */
  55. volatile uint8_t
  56. dmaDescriptorsUsed; /*!< Number of DMA descriptors with valid data (in queue, excluding initial descriptor) */
  57. volatile uint8_t
  58. descriptor; /*!< Index of next DMA descriptor in s_DmaDescriptors to be configured with data (does not include
  59. I2S instance offset) */
  60. volatile uint8_t queueDescriptor; /*!< Queue index of buffer to be actually consumed by DMA
  61. * (queueUser - advanced when user adds a buffer,
  62. * queueDescriptor - advanced when user buffer queued to DMA,
  63. * queueDriver - advanced when DMA queued buffer sent out to I2S) */
  64. volatile i2s_transfer_t descriptorQueue[I2S_NUM_BUFFERS]; /*!< Transfer data to be queued to DMA */
  65. volatile bool intA; /*!< If next scheduled DMA transfer will cause interrupt A or B */
  66. } i2s_dma_private_handle_t;
  67. /*! @brief I2S DMA transfer private state. */
  68. enum _i2s_dma_state
  69. {
  70. kI2S_DmaStateIdle = 0x0U, /*!< I2S is in idle state */
  71. kI2S_DmaStateTx, /*!< I2S is busy transmitting data */
  72. kI2S_DmaStateRx, /*!< I2S is busy receiving data */
  73. };
  74. /*******************************************************************************
  75. * Prototypes
  76. ******************************************************************************/
  77. static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
  78. static uint32_t I2S_GetInstance(I2S_Type *base);
  79. static inline void I2S_DisableDMAInterrupts(i2s_dma_handle_t *handle);
  80. static inline void I2S_EnableDMAInterrupts(i2s_dma_handle_t *handle);
  81. static void I2S_TxEnableDMA(I2S_Type *base, bool enable);
  82. static void I2S_RxEnableDMA(I2S_Type *base, bool enable);
  83. static uint16_t I2S_GetTransferBytes(volatile i2s_transfer_t *transfer);
  84. static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
  85. static void I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
  86. /*******************************************************************************
  87. * Variables
  88. ******************************************************************************/
  89. /*<! @brief DMA transfer descriptors. */
  90. #if defined(__ICCARM__)
  91. #pragma data_alignment = 16
  92. static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
  93. #elif defined(__CC_ARM)
  94. __attribute__((aligned(16))) static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
  95. #elif defined(__GNUC__)
  96. __attribute__((aligned(16))) static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
  97. #endif
  98. /*<! @brief Buffer with dummy TX data. */
  99. #if defined(__ICCARM__)
  100. #pragma data_alignment = 4
  101. static uint32_t s_DummyBufferTx = 0U;
  102. #elif defined(__CC_ARM)
  103. __attribute__((aligned(4))) static uint32_t s_DummyBufferTx = 0U;
  104. #elif defined(__GNUC__)
  105. __attribute__((aligned(4))) static uint32_t s_DummyBufferTx = 0U;
  106. #endif
  107. /*<! @brief Buffer to fill with RX data to discard. */
  108. #if defined(__ICCARM__)
  109. #pragma data_alignment = 4
  110. static uint32_t s_DummyBufferRx = 0U;
  111. #elif defined(__CC_ARM)
  112. __attribute__((aligned(4))) static uint32_t s_DummyBufferRx = 0U;
  113. #elif defined(__GNUC__)
  114. __attribute__((aligned(4))) static uint32_t s_DummyBufferRx = 0U;
  115. #endif
  116. /*<! @brief Private array of data associated with available I2S peripherals. */
  117. static i2s_dma_private_handle_t s_DmaPrivateHandle[FSL_FEATURE_SOC_I2S_COUNT];
  118. /*<! @brief Base addresses of available I2S peripherals. */
  119. static const uint32_t s_I2sBaseAddrs[FSL_FEATURE_SOC_I2S_COUNT] = I2S_BASE_ADDRS;
  120. /*******************************************************************************
  121. * Code
  122. ******************************************************************************/
  123. static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
  124. {
  125. uint32_t instance = I2S_GetInstance(base);
  126. i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
  127. /* Validate input data and tranfer buffer */
  128. assert(handle);
  129. if (!handle)
  130. {
  131. return kStatus_InvalidArgument;
  132. }
  133. assert((((uint32_t)transfer.data) % 4U) == 0U);
  134. if ((((uint32_t)transfer.data) % 4U) != 0U)
  135. {
  136. /* Data not 4-bytes aligned */
  137. return kStatus_InvalidArgument;
  138. }
  139. assert(transfer.dataSize != 0U);
  140. if (transfer.dataSize == 0U)
  141. {
  142. /* No data to send or receive */
  143. return kStatus_InvalidArgument;
  144. }
  145. assert((transfer.dataSize % 4U) == 0U);
  146. if ((transfer.dataSize % 4U) != 0U)
  147. {
  148. /* Data length not multiply of 4 bytes */
  149. return kStatus_InvalidArgument;
  150. }
  151. if (handle->i2sQueue[handle->queueUser].dataSize)
  152. {
  153. /* Previously prepared buffers not processed yet, reject request */
  154. return kStatus_I2S_Busy;
  155. }
  156. /* Enqueue data */
  157. privateHandle->descriptorQueue[handle->queueUser].data = transfer.data;
  158. privateHandle->descriptorQueue[handle->queueUser].dataSize = transfer.dataSize;
  159. handle->i2sQueue[handle->queueUser].data = transfer.data;
  160. handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
  161. handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
  162. return kStatus_Success;
  163. }
  164. static uint32_t I2S_GetInstance(I2S_Type *base)
  165. {
  166. uint32_t i;
  167. for (i = 0U; i < ARRAY_SIZE(s_I2sBaseAddrs); i++)
  168. {
  169. if ((uint32_t)base == s_I2sBaseAddrs[i])
  170. {
  171. return i;
  172. }
  173. }
  174. assert(false);
  175. return 0U;
  176. }
  177. static inline void I2S_DisableDMAInterrupts(i2s_dma_handle_t *handle)
  178. {
  179. DMA_DisableChannelInterrupts(handle->dmaHandle->base, handle->dmaHandle->channel);
  180. }
  181. static inline void I2S_EnableDMAInterrupts(i2s_dma_handle_t *handle)
  182. {
  183. if (handle->state != kI2S_DmaStateIdle)
  184. {
  185. DMA_EnableChannelInterrupts(handle->dmaHandle->base, handle->dmaHandle->channel);
  186. }
  187. }
  188. void I2S_TxTransferCreateHandleDMA(I2S_Type *base,
  189. i2s_dma_handle_t *handle,
  190. dma_handle_t *dmaHandle,
  191. i2s_dma_transfer_callback_t callback,
  192. void *userData)
  193. {
  194. assert(handle);
  195. assert(dmaHandle);
  196. uint32_t instance = I2S_GetInstance(base);
  197. i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
  198. memset(handle, 0U, sizeof(*handle));
  199. handle->state = kI2S_DmaStateIdle;
  200. handle->dmaHandle = dmaHandle;
  201. handle->completionCallback = callback;
  202. handle->userData = userData;
  203. memset(privateHandle, 0U, sizeof(*privateHandle));
  204. privateHandle->base = base;
  205. privateHandle->handle = handle;
  206. DMA_SetCallback(dmaHandle, I2S_DMACallback, privateHandle);
  207. }
  208. status_t I2S_TxTransferSendDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
  209. {
  210. status_t status;
  211. I2S_DisableDMAInterrupts(handle);
  212. /* Enqueue transfer buffer */
  213. status = I2S_EnqueueUserBuffer(base, handle, transfer);
  214. if (status != kStatus_Success)
  215. {
  216. I2S_EnableDMAInterrupts(handle);
  217. return status;
  218. }
  219. /* Initialize DMA transfer */
  220. if (handle->state == kI2S_DmaStateIdle)
  221. {
  222. handle->state = kI2S_DmaStateTx;
  223. status = I2S_StartTransferDMA(base, handle);
  224. if (status != kStatus_Success)
  225. {
  226. I2S_EnableDMAInterrupts(handle);
  227. return status;
  228. }
  229. }
  230. I2S_AddTransferDMA(base, handle);
  231. I2S_EnableDMAInterrupts(handle);
  232. return kStatus_Success;
  233. }
  234. void I2S_TransferAbortDMA(I2S_Type *base, i2s_dma_handle_t *handle)
  235. {
  236. assert(handle);
  237. assert(handle->dmaHandle);
  238. uint32_t instance = I2S_GetInstance(base);
  239. i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
  240. I2S_DisableDMAInterrupts(handle);
  241. /* Abort operation */
  242. DMA_AbortTransfer(handle->dmaHandle);
  243. if (handle->state == kI2S_DmaStateTx)
  244. {
  245. /* Wait until all transmitted data get out of FIFO */
  246. while ((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U)
  247. {
  248. }
  249. /* The last piece of valid data can be still being transmitted from I2S at this moment */
  250. /* Write additional data to FIFO */
  251. base->FIFOWR = 0U;
  252. while ((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U)
  253. {
  254. }
  255. /* At this moment the additional data are out of FIFO, starting being transmitted.
  256. * This means the preceding valid data has been just transmitted and we can stop I2S. */
  257. I2S_TxEnableDMA(base, false);
  258. }
  259. else
  260. {
  261. I2S_RxEnableDMA(base, false);
  262. }
  263. I2S_Disable(base);
  264. /* Reset state */
  265. handle->state = kI2S_DmaStateIdle;
  266. /* Clear transfer queue */
  267. memset((void *)&(handle->i2sQueue), 0U, sizeof(handle->i2sQueue));
  268. handle->queueDriver = 0U;
  269. handle->queueUser = 0U;
  270. /* Clear internal state */
  271. memset((void *)&(privateHandle->descriptorQueue), 0U, sizeof(privateHandle->descriptorQueue));
  272. memset((void *)&(privateHandle->enqueuedBytes), 0U, sizeof(privateHandle->enqueuedBytes));
  273. privateHandle->enqueuedBytesStart = 0U;
  274. privateHandle->enqueuedBytesEnd = 0U;
  275. privateHandle->dmaDescriptorsUsed = 0U;
  276. privateHandle->descriptor = 0U;
  277. privateHandle->queueDescriptor = 0U;
  278. privateHandle->intA = false;
  279. }
  280. void I2S_RxTransferCreateHandleDMA(I2S_Type *base,
  281. i2s_dma_handle_t *handle,
  282. dma_handle_t *dmaHandle,
  283. i2s_dma_transfer_callback_t callback,
  284. void *userData)
  285. {
  286. I2S_TxTransferCreateHandleDMA(base, handle, dmaHandle, callback, userData);
  287. }
  288. status_t I2S_RxTransferReceiveDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
  289. {
  290. status_t status;
  291. I2S_DisableDMAInterrupts(handle);
  292. /* Enqueue transfer buffer */
  293. status = I2S_EnqueueUserBuffer(base, handle, transfer);
  294. if (status != kStatus_Success)
  295. {
  296. I2S_EnableDMAInterrupts(handle);
  297. return status;
  298. }
  299. /* Initialize DMA transfer */
  300. if (handle->state == kI2S_DmaStateIdle)
  301. {
  302. handle->state = kI2S_DmaStateRx;
  303. status = I2S_StartTransferDMA(base, handle);
  304. if (status != kStatus_Success)
  305. {
  306. I2S_EnableDMAInterrupts(handle);
  307. return status;
  308. }
  309. }
  310. I2S_AddTransferDMA(base, handle);
  311. I2S_EnableDMAInterrupts(handle);
  312. return kStatus_Success;
  313. }
  314. static void I2S_TxEnableDMA(I2S_Type *base, bool enable)
  315. {
  316. if (enable)
  317. {
  318. base->FIFOCFG |= I2S_FIFOCFG_DMATX_MASK;
  319. }
  320. else
  321. {
  322. base->FIFOCFG &= (~I2S_FIFOCFG_DMATX_MASK);
  323. base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
  324. }
  325. }
  326. static void I2S_RxEnableDMA(I2S_Type *base, bool enable)
  327. {
  328. if (enable)
  329. {
  330. base->FIFOCFG |= I2S_FIFOCFG_DMARX_MASK;
  331. }
  332. else
  333. {
  334. base->FIFOCFG &= (~I2S_FIFOCFG_DMARX_MASK);
  335. base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
  336. }
  337. }
  338. static uint16_t I2S_GetTransferBytes(volatile i2s_transfer_t *transfer)
  339. {
  340. assert(transfer);
  341. uint16_t transferBytes;
  342. if (transfer->dataSize >= (2 * DMA_MAX_TRANSFER_BYTES))
  343. {
  344. transferBytes = DMA_MAX_TRANSFER_BYTES;
  345. }
  346. else if (transfer->dataSize > DMA_MAX_TRANSFER_BYTES)
  347. {
  348. transferBytes = transfer->dataSize / 2U;
  349. if ((transferBytes % 4U) != 0U)
  350. {
  351. transferBytes -= (transferBytes % 4U);
  352. }
  353. }
  354. else
  355. {
  356. transferBytes = transfer->dataSize;
  357. }
  358. return transferBytes;
  359. }
  360. static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
  361. {
  362. status_t status;
  363. dma_transfer_config_t xferConfig = {0};
  364. i2s_dma_private_handle_t *privateHandle;
  365. volatile i2s_transfer_t *transfer;
  366. uint16_t transferBytes;
  367. uint32_t instance;
  368. int i;
  369. dma_descriptor_t *descriptor;
  370. dma_descriptor_t *nextDescriptor;
  371. dma_xfercfg_t xfercfg;
  372. instance = I2S_GetInstance(base);
  373. privateHandle = &(s_DmaPrivateHandle[instance]);
  374. transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
  375. transferBytes = I2S_GetTransferBytes(transfer);
  376. /* Prepare transfer of data via initial DMA transfer descriptor */
  377. DMA_PrepareTransfer(
  378. &xferConfig, (void *)((handle->state == kI2S_DmaStateTx) ? (uint32_t)transfer->data : (uint32_t)(&(base->FIFORD))),
  379. (void *)((handle->state == kI2S_DmaStateTx) ? (uint32_t)(&(base->FIFOWR)) : (uint32_t)transfer->data), sizeof(uint32_t),
  380. transferBytes, (handle->state == kI2S_DmaStateTx) ? kDMA_MemoryToPeripheral : kDMA_PeripheralToMemory,
  381. (void *)&(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + 0U]));
  382. /* Initial descriptor is stored in another place in memory, but treat it as another descriptor for simplicity */
  383. privateHandle->dmaDescriptorsUsed = 1U;
  384. privateHandle->intA = false;
  385. privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
  386. privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % DMA_DESCRIPTORS;
  387. transfer->dataSize -= transferBytes;
  388. transfer->data += transferBytes;
  389. if (transfer->dataSize == 0U)
  390. {
  391. transfer->data = NULL;
  392. privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
  393. }
  394. /* Link the DMA descriptors for the case when no additional transfer is queued before the initial one finishes */
  395. for (i = 0; i < DMA_DESCRIPTORS; i++)
  396. {
  397. descriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + i]);
  398. nextDescriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + ((i + 1) % DMA_DESCRIPTORS)]);
  399. xfercfg.valid = true;
  400. xfercfg.reload = true;
  401. xfercfg.swtrig = false;
  402. xfercfg.clrtrig = false;
  403. xfercfg.intA = false;
  404. xfercfg.intB = false;
  405. xfercfg.byteWidth = sizeof(uint32_t);
  406. xfercfg.srcInc = 0U;
  407. xfercfg.dstInc = 0U;
  408. xfercfg.transferCount = 8U;
  409. DMA_CreateDescriptor(descriptor, &xfercfg,
  410. ((handle->state == kI2S_DmaStateTx) ? (void *)&s_DummyBufferTx : (void *)(uint32_t)(&(base->FIFORD))),
  411. ((handle->state == kI2S_DmaStateTx) ? (void *)(uint32_t)(&(base->FIFOWR)) : (void *)&s_DummyBufferRx),
  412. (void *)nextDescriptor);
  413. }
  414. /* Submit and start initial DMA transfer */
  415. if (handle->state == kI2S_DmaStateTx)
  416. {
  417. I2S_TxEnableDMA(base, true);
  418. }
  419. else
  420. {
  421. I2S_RxEnableDMA(base, true);
  422. }
  423. status = DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
  424. if (status != kStatus_Success)
  425. {
  426. return status;
  427. }
  428. DMA_StartTransfer(handle->dmaHandle);
  429. I2S_Enable(base);
  430. return kStatus_Success;
  431. }
  432. static void I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
  433. {
  434. dma_xfercfg_t xfercfg;
  435. volatile i2s_transfer_t *transfer;
  436. uint16_t transferBytes;
  437. uint32_t instance;
  438. i2s_dma_private_handle_t *privateHandle;
  439. dma_descriptor_t *descriptor;
  440. dma_descriptor_t *nextDescriptor;
  441. uint32_t srcAddr = 0, destAddr = 0;
  442. instance = I2S_GetInstance(base);
  443. privateHandle = &(s_DmaPrivateHandle[instance]);
  444. while (privateHandle->dmaDescriptorsUsed < DMA_DESCRIPTORS)
  445. {
  446. transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
  447. if (transfer->dataSize == 0U)
  448. {
  449. /* Nothing to be added */
  450. return;
  451. }
  452. /* Determine currently configured descriptor and the other which it will link to */
  453. descriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + privateHandle->descriptor]);
  454. privateHandle->descriptor = (privateHandle->descriptor + 1U) % DMA_DESCRIPTORS;
  455. nextDescriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + privateHandle->descriptor]);
  456. transferBytes = I2S_GetTransferBytes(transfer);
  457. privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
  458. privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % DMA_DESCRIPTORS;
  459. /* Configure descriptor */
  460. xfercfg.valid = true;
  461. xfercfg.reload = true;
  462. xfercfg.swtrig = false;
  463. xfercfg.clrtrig = false;
  464. xfercfg.intA = privateHandle->intA;
  465. xfercfg.intB = !privateHandle->intA;
  466. xfercfg.byteWidth = sizeof(uint32_t);
  467. xfercfg.srcInc = (handle->state == kI2S_DmaStateTx) ? 1U : 0U;
  468. xfercfg.dstInc = (handle->state == kI2S_DmaStateTx) ? 0U : 1U;
  469. xfercfg.transferCount = transferBytes / sizeof(uint32_t);
  470. srcAddr = ((handle->state == kI2S_DmaStateTx) ? (uint32_t)transfer->data : (uint32_t)&(base->FIFORD));
  471. destAddr = ((handle->state == kI2S_DmaStateTx) ? (uint32_t)&(base->FIFOWR) : (uint32_t)transfer->data);
  472. DMA_CreateDescriptor(descriptor, &xfercfg, (void *)srcAddr, (void *)destAddr, (void *)nextDescriptor);
  473. /* Advance internal state */
  474. privateHandle->dmaDescriptorsUsed++;
  475. privateHandle->intA = !privateHandle->intA;
  476. transfer->dataSize -= transferBytes;
  477. transfer->data += transferBytes;
  478. if (transfer->dataSize == 0U)
  479. {
  480. transfer->data = NULL;
  481. privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
  482. }
  483. }
  484. }
  485. void I2S_DMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
  486. {
  487. i2s_dma_private_handle_t *privateHandle = (i2s_dma_private_handle_t *)userData;
  488. i2s_dma_handle_t *i2sHandle = privateHandle->handle;
  489. I2S_Type *base = privateHandle->base;
  490. if ((!transferDone) || (i2sHandle->state == kI2S_DmaStateIdle))
  491. {
  492. return;
  493. }
  494. if (privateHandle->dmaDescriptorsUsed > 0U)
  495. {
  496. /* Finished descriptor, decrease amount of data to be processed */
  497. i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize -=
  498. privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
  499. i2sHandle->i2sQueue[i2sHandle->queueDriver].data +=
  500. privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
  501. privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] = 0U;
  502. privateHandle->enqueuedBytesStart = (privateHandle->enqueuedBytesStart + 1U) % DMA_DESCRIPTORS;
  503. privateHandle->dmaDescriptorsUsed--;
  504. if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
  505. {
  506. /* Entire user buffer sent or received - advance to next one */
  507. i2sHandle->i2sQueue[i2sHandle->queueDriver].data = NULL;
  508. i2sHandle->queueDriver = (i2sHandle->queueDriver + 1U) % I2S_NUM_BUFFERS;
  509. /* Notify user about buffer completion */
  510. if (i2sHandle->completionCallback)
  511. {
  512. (i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_BufferComplete, i2sHandle->userData);
  513. }
  514. }
  515. }
  516. if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
  517. {
  518. /* All user buffers processed */
  519. I2S_TransferAbortDMA(base, i2sHandle);
  520. /* Notify user about completion of the final buffer */
  521. if (i2sHandle->completionCallback)
  522. {
  523. (i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_Done, i2sHandle->userData);
  524. }
  525. }
  526. else
  527. {
  528. /* Enqueue another user buffer to DMA if it could not be done when in I2S_Rx/TxTransferSendDMA */
  529. I2S_AddTransferDMA(base, i2sHandle);
  530. }
  531. }