123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636 |
- /*
- * The Clear BSD License
- * Copyright (c) 2016, Freescale Semiconductor, Inc.
- * Copyright 2016-2017 NXP
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted (subject to the limitations in the disclaimer below) provided
- * that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o Redistributions in binary form must reproduce the above copyright notice, this
- * list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- *
- * o Neither the name of the copyright holder nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include "fsl_dma.h"
- #include "fsl_i2s_dma.h"
- #include "fsl_flexcomm.h"
- #include <string.h>
- /*******************************************************************************
- * Definitions
- ******************************************************************************/
- /* Component ID definition, used by tools. */
- #ifndef FSL_COMPONENT_ID
- #define FSL_COMPONENT_ID "platform.drivers.flexcomm_i2s_dma"
- #endif
- #define DMA_MAX_TRANSFER_BYTES (DMA_MAX_TRANSFER_COUNT * sizeof(uint32_t))
- #define DMA_DESCRIPTORS (2U)
- /*<! @brief Structure for statically allocated private data. */
- typedef struct _i2s_dma_private_handle
- {
- I2S_Type *base; /*!< I2S base address */
- i2s_dma_handle_t *handle; /*!< I2S handle */
- volatile uint16_t enqueuedBytes[DMA_DESCRIPTORS]; /*!< Number of bytes being transferred by DMA descriptors */
- volatile uint8_t enqueuedBytesStart; /*!< First item in enqueuedBytes (for reading) */
- volatile uint8_t enqueuedBytesEnd; /*!< Last item in enqueuedBytes (for adding) */
- volatile uint8_t
- dmaDescriptorsUsed; /*!< Number of DMA descriptors with valid data (in queue, excluding initial descriptor) */
- volatile uint8_t
- descriptor; /*!< Index of next DMA descriptor in s_DmaDescriptors to be configured with data (does not include
- I2S instance offset) */
- volatile uint8_t queueDescriptor; /*!< Queue index of buffer to be actually consumed by DMA
- * (queueUser - advanced when user adds a buffer,
- * queueDescriptor - advanced when user buffer queued to DMA,
- * queueDriver - advanced when DMA queued buffer sent out to I2S) */
- volatile i2s_transfer_t descriptorQueue[I2S_NUM_BUFFERS]; /*!< Transfer data to be queued to DMA */
- volatile bool intA; /*!< If next scheduled DMA transfer will cause interrupt A or B */
- } i2s_dma_private_handle_t;
- /*! @brief I2S DMA transfer private state. */
- enum _i2s_dma_state
- {
- kI2S_DmaStateIdle = 0x0U, /*!< I2S is in idle state */
- kI2S_DmaStateTx, /*!< I2S is busy transmitting data */
- kI2S_DmaStateRx, /*!< I2S is busy receiving data */
- };
- /*******************************************************************************
- * Prototypes
- ******************************************************************************/
- static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer);
- static uint32_t I2S_GetInstance(I2S_Type *base);
- static inline void I2S_DisableDMAInterrupts(i2s_dma_handle_t *handle);
- static inline void I2S_EnableDMAInterrupts(i2s_dma_handle_t *handle);
- static void I2S_TxEnableDMA(I2S_Type *base, bool enable);
- static void I2S_RxEnableDMA(I2S_Type *base, bool enable);
- static uint16_t I2S_GetTransferBytes(volatile i2s_transfer_t *transfer);
- static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
- static void I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle);
- /*******************************************************************************
- * Variables
- ******************************************************************************/
- /*<! @brief DMA transfer descriptors. */
- #if defined(__ICCARM__)
- #pragma data_alignment = 16
- static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
- #elif defined(__CC_ARM)
- __attribute__((aligned(16))) static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
- #elif defined(__GNUC__)
- __attribute__((aligned(16))) static dma_descriptor_t s_DmaDescriptors[DMA_DESCRIPTORS * FSL_FEATURE_SOC_I2S_COUNT];
- #endif
- /*<! @brief Buffer with dummy TX data. */
- #if defined(__ICCARM__)
- #pragma data_alignment = 4
- static uint32_t s_DummyBufferTx = 0U;
- #elif defined(__CC_ARM)
- __attribute__((aligned(4))) static uint32_t s_DummyBufferTx = 0U;
- #elif defined(__GNUC__)
- __attribute__((aligned(4))) static uint32_t s_DummyBufferTx = 0U;
- #endif
- /*<! @brief Buffer to fill with RX data to discard. */
- #if defined(__ICCARM__)
- #pragma data_alignment = 4
- static uint32_t s_DummyBufferRx = 0U;
- #elif defined(__CC_ARM)
- __attribute__((aligned(4))) static uint32_t s_DummyBufferRx = 0U;
- #elif defined(__GNUC__)
- __attribute__((aligned(4))) static uint32_t s_DummyBufferRx = 0U;
- #endif
- /*<! @brief Private array of data associated with available I2S peripherals. */
- static i2s_dma_private_handle_t s_DmaPrivateHandle[FSL_FEATURE_SOC_I2S_COUNT];
- /*<! @brief Base addresses of available I2S peripherals. */
- static const uint32_t s_I2sBaseAddrs[FSL_FEATURE_SOC_I2S_COUNT] = I2S_BASE_ADDRS;
- /*******************************************************************************
- * Code
- ******************************************************************************/
- static status_t I2S_EnqueueUserBuffer(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
- {
- uint32_t instance = I2S_GetInstance(base);
- i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
- /* Validate input data and tranfer buffer */
- assert(handle);
- if (!handle)
- {
- return kStatus_InvalidArgument;
- }
- assert((((uint32_t)transfer.data) % 4U) == 0U);
- if ((((uint32_t)transfer.data) % 4U) != 0U)
- {
- /* Data not 4-bytes aligned */
- return kStatus_InvalidArgument;
- }
- assert(transfer.dataSize != 0U);
- if (transfer.dataSize == 0U)
- {
- /* No data to send or receive */
- return kStatus_InvalidArgument;
- }
- assert((transfer.dataSize % 4U) == 0U);
- if ((transfer.dataSize % 4U) != 0U)
- {
- /* Data length not multiply of 4 bytes */
- return kStatus_InvalidArgument;
- }
- if (handle->i2sQueue[handle->queueUser].dataSize)
- {
- /* Previously prepared buffers not processed yet, reject request */
- return kStatus_I2S_Busy;
- }
- /* Enqueue data */
- privateHandle->descriptorQueue[handle->queueUser].data = transfer.data;
- privateHandle->descriptorQueue[handle->queueUser].dataSize = transfer.dataSize;
- handle->i2sQueue[handle->queueUser].data = transfer.data;
- handle->i2sQueue[handle->queueUser].dataSize = transfer.dataSize;
- handle->queueUser = (handle->queueUser + 1U) % I2S_NUM_BUFFERS;
- return kStatus_Success;
- }
- static uint32_t I2S_GetInstance(I2S_Type *base)
- {
- uint32_t i;
- for (i = 0U; i < ARRAY_SIZE(s_I2sBaseAddrs); i++)
- {
- if ((uint32_t)base == s_I2sBaseAddrs[i])
- {
- return i;
- }
- }
- assert(false);
- return 0U;
- }
- static inline void I2S_DisableDMAInterrupts(i2s_dma_handle_t *handle)
- {
- DMA_DisableChannelInterrupts(handle->dmaHandle->base, handle->dmaHandle->channel);
- }
- static inline void I2S_EnableDMAInterrupts(i2s_dma_handle_t *handle)
- {
- if (handle->state != kI2S_DmaStateIdle)
- {
- DMA_EnableChannelInterrupts(handle->dmaHandle->base, handle->dmaHandle->channel);
- }
- }
- void I2S_TxTransferCreateHandleDMA(I2S_Type *base,
- i2s_dma_handle_t *handle,
- dma_handle_t *dmaHandle,
- i2s_dma_transfer_callback_t callback,
- void *userData)
- {
- assert(handle);
- assert(dmaHandle);
- uint32_t instance = I2S_GetInstance(base);
- i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
- memset(handle, 0U, sizeof(*handle));
- handle->state = kI2S_DmaStateIdle;
- handle->dmaHandle = dmaHandle;
- handle->completionCallback = callback;
- handle->userData = userData;
- memset(privateHandle, 0U, sizeof(*privateHandle));
- privateHandle->base = base;
- privateHandle->handle = handle;
- DMA_SetCallback(dmaHandle, I2S_DMACallback, privateHandle);
- }
- status_t I2S_TxTransferSendDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
- {
- status_t status;
- I2S_DisableDMAInterrupts(handle);
- /* Enqueue transfer buffer */
- status = I2S_EnqueueUserBuffer(base, handle, transfer);
- if (status != kStatus_Success)
- {
- I2S_EnableDMAInterrupts(handle);
- return status;
- }
- /* Initialize DMA transfer */
- if (handle->state == kI2S_DmaStateIdle)
- {
- handle->state = kI2S_DmaStateTx;
- status = I2S_StartTransferDMA(base, handle);
- if (status != kStatus_Success)
- {
- I2S_EnableDMAInterrupts(handle);
- return status;
- }
- }
- I2S_AddTransferDMA(base, handle);
- I2S_EnableDMAInterrupts(handle);
- return kStatus_Success;
- }
- void I2S_TransferAbortDMA(I2S_Type *base, i2s_dma_handle_t *handle)
- {
- assert(handle);
- assert(handle->dmaHandle);
- uint32_t instance = I2S_GetInstance(base);
- i2s_dma_private_handle_t *privateHandle = &(s_DmaPrivateHandle[instance]);
- I2S_DisableDMAInterrupts(handle);
- /* Abort operation */
- DMA_AbortTransfer(handle->dmaHandle);
- if (handle->state == kI2S_DmaStateTx)
- {
- /* Wait until all transmitted data get out of FIFO */
- while ((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U)
- {
- }
- /* The last piece of valid data can be still being transmitted from I2S at this moment */
- /* Write additional data to FIFO */
- base->FIFOWR = 0U;
- while ((base->FIFOSTAT & I2S_FIFOSTAT_TXEMPTY_MASK) == 0U)
- {
- }
- /* At this moment the additional data are out of FIFO, starting being transmitted.
- * This means the preceding valid data has been just transmitted and we can stop I2S. */
- I2S_TxEnableDMA(base, false);
- }
- else
- {
- I2S_RxEnableDMA(base, false);
- }
- I2S_Disable(base);
- /* Reset state */
- handle->state = kI2S_DmaStateIdle;
- /* Clear transfer queue */
- memset((void *)&(handle->i2sQueue), 0U, sizeof(handle->i2sQueue));
- handle->queueDriver = 0U;
- handle->queueUser = 0U;
- /* Clear internal state */
- memset((void *)&(privateHandle->descriptorQueue), 0U, sizeof(privateHandle->descriptorQueue));
- memset((void *)&(privateHandle->enqueuedBytes), 0U, sizeof(privateHandle->enqueuedBytes));
- privateHandle->enqueuedBytesStart = 0U;
- privateHandle->enqueuedBytesEnd = 0U;
- privateHandle->dmaDescriptorsUsed = 0U;
- privateHandle->descriptor = 0U;
- privateHandle->queueDescriptor = 0U;
- privateHandle->intA = false;
- }
- void I2S_RxTransferCreateHandleDMA(I2S_Type *base,
- i2s_dma_handle_t *handle,
- dma_handle_t *dmaHandle,
- i2s_dma_transfer_callback_t callback,
- void *userData)
- {
- I2S_TxTransferCreateHandleDMA(base, handle, dmaHandle, callback, userData);
- }
- status_t I2S_RxTransferReceiveDMA(I2S_Type *base, i2s_dma_handle_t *handle, i2s_transfer_t transfer)
- {
- status_t status;
- I2S_DisableDMAInterrupts(handle);
- /* Enqueue transfer buffer */
- status = I2S_EnqueueUserBuffer(base, handle, transfer);
- if (status != kStatus_Success)
- {
- I2S_EnableDMAInterrupts(handle);
- return status;
- }
- /* Initialize DMA transfer */
- if (handle->state == kI2S_DmaStateIdle)
- {
- handle->state = kI2S_DmaStateRx;
- status = I2S_StartTransferDMA(base, handle);
- if (status != kStatus_Success)
- {
- I2S_EnableDMAInterrupts(handle);
- return status;
- }
- }
- I2S_AddTransferDMA(base, handle);
- I2S_EnableDMAInterrupts(handle);
- return kStatus_Success;
- }
- static void I2S_TxEnableDMA(I2S_Type *base, bool enable)
- {
- if (enable)
- {
- base->FIFOCFG |= I2S_FIFOCFG_DMATX_MASK;
- }
- else
- {
- base->FIFOCFG &= (~I2S_FIFOCFG_DMATX_MASK);
- base->FIFOCFG |= I2S_FIFOCFG_EMPTYTX_MASK;
- }
- }
- static void I2S_RxEnableDMA(I2S_Type *base, bool enable)
- {
- if (enable)
- {
- base->FIFOCFG |= I2S_FIFOCFG_DMARX_MASK;
- }
- else
- {
- base->FIFOCFG &= (~I2S_FIFOCFG_DMARX_MASK);
- base->FIFOCFG |= I2S_FIFOCFG_EMPTYRX_MASK;
- }
- }
- static uint16_t I2S_GetTransferBytes(volatile i2s_transfer_t *transfer)
- {
- assert(transfer);
- uint16_t transferBytes;
- if (transfer->dataSize >= (2 * DMA_MAX_TRANSFER_BYTES))
- {
- transferBytes = DMA_MAX_TRANSFER_BYTES;
- }
- else if (transfer->dataSize > DMA_MAX_TRANSFER_BYTES)
- {
- transferBytes = transfer->dataSize / 2U;
- if ((transferBytes % 4U) != 0U)
- {
- transferBytes -= (transferBytes % 4U);
- }
- }
- else
- {
- transferBytes = transfer->dataSize;
- }
- return transferBytes;
- }
- static status_t I2S_StartTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
- {
- status_t status;
- dma_transfer_config_t xferConfig = {0};
- i2s_dma_private_handle_t *privateHandle;
- volatile i2s_transfer_t *transfer;
- uint16_t transferBytes;
- uint32_t instance;
- int i;
- dma_descriptor_t *descriptor;
- dma_descriptor_t *nextDescriptor;
- dma_xfercfg_t xfercfg;
- instance = I2S_GetInstance(base);
- privateHandle = &(s_DmaPrivateHandle[instance]);
- transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
- transferBytes = I2S_GetTransferBytes(transfer);
- /* Prepare transfer of data via initial DMA transfer descriptor */
- DMA_PrepareTransfer(
- &xferConfig, (void *)((handle->state == kI2S_DmaStateTx) ? (uint32_t)transfer->data : (uint32_t)(&(base->FIFORD))),
- (void *)((handle->state == kI2S_DmaStateTx) ? (uint32_t)(&(base->FIFOWR)) : (uint32_t)transfer->data), sizeof(uint32_t),
- transferBytes, (handle->state == kI2S_DmaStateTx) ? kDMA_MemoryToPeripheral : kDMA_PeripheralToMemory,
- (void *)&(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + 0U]));
- /* Initial descriptor is stored in another place in memory, but treat it as another descriptor for simplicity */
- privateHandle->dmaDescriptorsUsed = 1U;
- privateHandle->intA = false;
- privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
- privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % DMA_DESCRIPTORS;
- transfer->dataSize -= transferBytes;
- transfer->data += transferBytes;
- if (transfer->dataSize == 0U)
- {
- transfer->data = NULL;
- privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
- }
- /* Link the DMA descriptors for the case when no additional transfer is queued before the initial one finishes */
- for (i = 0; i < DMA_DESCRIPTORS; i++)
- {
- descriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + i]);
- nextDescriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + ((i + 1) % DMA_DESCRIPTORS)]);
- xfercfg.valid = true;
- xfercfg.reload = true;
- xfercfg.swtrig = false;
- xfercfg.clrtrig = false;
- xfercfg.intA = false;
- xfercfg.intB = false;
- xfercfg.byteWidth = sizeof(uint32_t);
- xfercfg.srcInc = 0U;
- xfercfg.dstInc = 0U;
- xfercfg.transferCount = 8U;
- DMA_CreateDescriptor(descriptor, &xfercfg,
- ((handle->state == kI2S_DmaStateTx) ? (void *)&s_DummyBufferTx : (void *)(uint32_t)(&(base->FIFORD))),
- ((handle->state == kI2S_DmaStateTx) ? (void *)(uint32_t)(&(base->FIFOWR)) : (void *)&s_DummyBufferRx),
- (void *)nextDescriptor);
- }
- /* Submit and start initial DMA transfer */
- if (handle->state == kI2S_DmaStateTx)
- {
- I2S_TxEnableDMA(base, true);
- }
- else
- {
- I2S_RxEnableDMA(base, true);
- }
- status = DMA_SubmitTransfer(handle->dmaHandle, &xferConfig);
- if (status != kStatus_Success)
- {
- return status;
- }
- DMA_StartTransfer(handle->dmaHandle);
- I2S_Enable(base);
- return kStatus_Success;
- }
- static void I2S_AddTransferDMA(I2S_Type *base, i2s_dma_handle_t *handle)
- {
- dma_xfercfg_t xfercfg;
- volatile i2s_transfer_t *transfer;
- uint16_t transferBytes;
- uint32_t instance;
- i2s_dma_private_handle_t *privateHandle;
- dma_descriptor_t *descriptor;
- dma_descriptor_t *nextDescriptor;
- uint32_t srcAddr = 0, destAddr = 0;
- instance = I2S_GetInstance(base);
- privateHandle = &(s_DmaPrivateHandle[instance]);
- while (privateHandle->dmaDescriptorsUsed < DMA_DESCRIPTORS)
- {
- transfer = &(privateHandle->descriptorQueue[privateHandle->queueDescriptor]);
- if (transfer->dataSize == 0U)
- {
- /* Nothing to be added */
- return;
- }
- /* Determine currently configured descriptor and the other which it will link to */
- descriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + privateHandle->descriptor]);
- privateHandle->descriptor = (privateHandle->descriptor + 1U) % DMA_DESCRIPTORS;
- nextDescriptor = &(s_DmaDescriptors[(instance * DMA_DESCRIPTORS) + privateHandle->descriptor]);
- transferBytes = I2S_GetTransferBytes(transfer);
- privateHandle->enqueuedBytes[privateHandle->enqueuedBytesEnd] = transferBytes;
- privateHandle->enqueuedBytesEnd = (privateHandle->enqueuedBytesEnd + 1U) % DMA_DESCRIPTORS;
- /* Configure descriptor */
- xfercfg.valid = true;
- xfercfg.reload = true;
- xfercfg.swtrig = false;
- xfercfg.clrtrig = false;
- xfercfg.intA = privateHandle->intA;
- xfercfg.intB = !privateHandle->intA;
- xfercfg.byteWidth = sizeof(uint32_t);
- xfercfg.srcInc = (handle->state == kI2S_DmaStateTx) ? 1U : 0U;
- xfercfg.dstInc = (handle->state == kI2S_DmaStateTx) ? 0U : 1U;
- xfercfg.transferCount = transferBytes / sizeof(uint32_t);
- srcAddr = ((handle->state == kI2S_DmaStateTx) ? (uint32_t)transfer->data : (uint32_t)&(base->FIFORD));
- destAddr = ((handle->state == kI2S_DmaStateTx) ? (uint32_t)&(base->FIFOWR) : (uint32_t)transfer->data);
- DMA_CreateDescriptor(descriptor, &xfercfg, (void *)srcAddr, (void *)destAddr, (void *)nextDescriptor);
- /* Advance internal state */
- privateHandle->dmaDescriptorsUsed++;
- privateHandle->intA = !privateHandle->intA;
- transfer->dataSize -= transferBytes;
- transfer->data += transferBytes;
- if (transfer->dataSize == 0U)
- {
- transfer->data = NULL;
- privateHandle->queueDescriptor = (privateHandle->queueDescriptor + 1U) % I2S_NUM_BUFFERS;
- }
- }
- }
- void I2S_DMACallback(dma_handle_t *handle, void *userData, bool transferDone, uint32_t tcds)
- {
- i2s_dma_private_handle_t *privateHandle = (i2s_dma_private_handle_t *)userData;
- i2s_dma_handle_t *i2sHandle = privateHandle->handle;
- I2S_Type *base = privateHandle->base;
- if ((!transferDone) || (i2sHandle->state == kI2S_DmaStateIdle))
- {
- return;
- }
- if (privateHandle->dmaDescriptorsUsed > 0U)
- {
- /* Finished descriptor, decrease amount of data to be processed */
- i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize -=
- privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
- i2sHandle->i2sQueue[i2sHandle->queueDriver].data +=
- privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart];
- privateHandle->enqueuedBytes[privateHandle->enqueuedBytesStart] = 0U;
- privateHandle->enqueuedBytesStart = (privateHandle->enqueuedBytesStart + 1U) % DMA_DESCRIPTORS;
- privateHandle->dmaDescriptorsUsed--;
- if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
- {
- /* Entire user buffer sent or received - advance to next one */
- i2sHandle->i2sQueue[i2sHandle->queueDriver].data = NULL;
- i2sHandle->queueDriver = (i2sHandle->queueDriver + 1U) % I2S_NUM_BUFFERS;
- /* Notify user about buffer completion */
- if (i2sHandle->completionCallback)
- {
- (i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_BufferComplete, i2sHandle->userData);
- }
- }
- }
- if (i2sHandle->i2sQueue[i2sHandle->queueDriver].dataSize == 0U)
- {
- /* All user buffers processed */
- I2S_TransferAbortDMA(base, i2sHandle);
- /* Notify user about completion of the final buffer */
- if (i2sHandle->completionCallback)
- {
- (i2sHandle->completionCallback)(base, i2sHandle, kStatus_I2S_Done, i2sHandle->userData);
- }
- }
- else
- {
- /* Enqueue another user buffer to DMA if it could not be done when in I2S_Rx/TxTransferSendDMA */
- I2S_AddTransferDMA(base, i2sHandle);
- }
- }
|