diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.c index a96fa4818d..c9aa4a30f4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.c @@ -170,6 +170,9 @@ status_t FLEXIO_CAMERA_TransferReceiveEDMA(FLEXIO_CAMERA_Type *base, EDMA_PrepareTransfer(&xferConfig, (void *)FLEXIO_CAMERA_GetRxBufferAddress(base), 32, (void *)xfer->dataAddress, 32, 32, xfer->dataNum, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the FLEXIO CAMERA handle */ + handle->nbytes = 32; + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -207,7 +210,9 @@ status_t FLEXIO_CAMERA_TransferGetReceiveCountEDMA(FLEXIO_CAMERA_Type *base, if (kFLEXIO_CAMERA_RxBusy == handle->rxState) { - *count = (handle->rxSize - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel)); + *count = (handle->rxSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel)); } else { diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.h index 68cde16367..a22f130297 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_camera_edma.h @@ -39,7 +39,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -47,21 +46,22 @@ /*! @brief Forward declaration of the handle typedef. */ typedef struct _flexio_camera_edma_handle flexio_camera_edma_handle_t; -/*! @brief CAMERA transfer callback function. */ +/*! @brief Camera transfer callback function. */ typedef void (*flexio_camera_edma_transfer_callback_t)(FLEXIO_CAMERA_Type *base, flexio_camera_edma_handle_t *handle, status_t status, void *userData); /*! -* @brief CAMERA eDMA handle +* @brief Camera eDMA handle */ struct _flexio_camera_edma_handle { flexio_camera_edma_transfer_callback_t callback; /*!< Callback function. */ - void *userData; /*!< CAMERA callback function parameter.*/ + void *userData; /*!< Camera callback function parameter.*/ size_t rxSize; /*!< Total bytes to be received. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -79,15 +79,15 @@ extern "C" { */ /*! - * @brief Initializes the camera handle, which is used in transactional functions. + * @brief Initializes the Camera handle, which is used in transactional functions. * - * @param base pointer to FLEXIO_CAMERA_Type. + * @param base Pointer to the FLEXIO_CAMERA_Type. * @param handle Pointer to flexio_camera_edma_handle_t structure. * @param callback The callback function. * @param userData The parameter of the callback function. * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. * @retval kStatus_Success Successfully create the handle. - * @retval kStatus_OutOfRange The FlexIO camera eDMA type/handle table out of range. + * @retval kStatus_OutOfRange The FlexIO Camera eDMA type/handle table out of range. */ status_t FLEXIO_CAMERA_TransferCreateHandleEDMA(FLEXIO_CAMERA_Type *base, flexio_camera_edma_handle_t *handle, @@ -103,7 +103,7 @@ status_t FLEXIO_CAMERA_TransferCreateHandleEDMA(FLEXIO_CAMERA_Type *base, * * @param base Pointer to the FLEXIO_CAMERA_Type. * @param handle Pointer to the flexio_camera_edma_handle_t structure. - * @param xfer CAMERA eDMA transfer structure, see #flexio_camera_transfer_t. + * @param xfer Camera eDMA transfer structure, see #flexio_camera_transfer_t. * @retval kStatus_Success if succeeded, others failed. * @retval kStatus_CAMERA_RxBusy Previous transfer on going. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.c index f5a2682fe5..bebb7cf6b2 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.c @@ -225,6 +225,9 @@ status_t FLEXIO_I2S_TransferSendEDMA(FLEXIO_I2S_Type *base, EDMA_PrepareTransfer(&config, xfer->data, handle->bytesPerFrame, (void *)destAddr, handle->bytesPerFrame, handle->bytesPerFrame, xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the FLEXIO I2S handle */ + handle->nbytes = handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -272,6 +275,9 @@ status_t FLEXIO_I2S_TransferReceiveEDMA(FLEXIO_I2S_Type *base, EDMA_PrepareTransfer(&config, (void *)srcAddr, handle->bytesPerFrame, xfer->data, handle->bytesPerFrame, handle->bytesPerFrame, xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the FLEXIO I2S handle */ + handle->nbytes = handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -327,7 +333,8 @@ status_t FLEXIO_I2S_TransferGetSendCountEDMA(FLEXIO_I2S_Type *base, flexio_i2s_e else { *count = handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel); } return status; @@ -346,7 +353,8 @@ status_t FLEXIO_I2S_TransferGetReceiveCountEDMA(FLEXIO_I2S_Type *base, flexio_i2 else { *count = handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel); } return status; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.h index 0624701ccf..150c985e59 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_i2s_edma.h @@ -38,7 +38,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -56,6 +55,7 @@ struct _flexio_i2s_edma_handle { edma_handle_t *dmaHandle; /*!< DMA handler for FlexIO I2S send */ uint8_t bytesPerFrame; /*!< Bytes in a frame */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint32_t state; /*!< Internal state for FlexIO I2S eDMA transfer */ flexio_i2s_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurred */ void *userData; /*!< User callback parameter */ @@ -83,13 +83,13 @@ extern "C" { * * This function initializes the FlexIO I2S master DMA handle which can be used for other FlexIO I2S master * transactional APIs. - * Usually, for a specified FlexIO I2S instance, user need only call this API once to get the initialized handle. + * Usually, for a specified FlexIO I2S instance, call this API once to get the initialized handle. * * @param base FlexIO I2S peripheral base address. * @param handle FlexIO I2S eDMA handle pointer. * @param callback FlexIO I2S eDMA callback function called while finished a block. * @param userData User parameter for callback. - * @param dmaHandle eDMA handle for FlexIO I2S. This handle shall be a static value allocated by users. + * @param dmaHandle eDMA handle for FlexIO I2S. This handle is a static value allocated by users. */ void FLEXIO_I2S_TransferTxCreateHandleEDMA(FLEXIO_I2S_Type *base, flexio_i2s_edma_handle_t *handle, @@ -102,13 +102,13 @@ void FLEXIO_I2S_TransferTxCreateHandleEDMA(FLEXIO_I2S_Type *base, * * This function initializes the FlexIO I2S slave DMA handle which can be used for other FlexIO I2S master transactional * APIs. - * Usually, for a specified FlexIO I2S instance, user need only call this API once to get the initialized handle. + * Usually, for a specified FlexIO I2S instance, call this API once to get the initialized handle. * * @param base FlexIO I2S peripheral base address. * @param handle FlexIO I2S eDMA handle pointer. * @param callback FlexIO I2S eDMA callback function called while finished a block. * @param userData User parameter for callback. - * @param dmaHandle eDMA handle for FlexIO I2S. This handle shall be a static value allocated by users. + * @param dmaHandle eDMA handle for FlexIO I2S. This handle is a static value allocated by users. */ void FLEXIO_I2S_TransferRxCreateHandleEDMA(FLEXIO_I2S_Type *base, flexio_i2s_edma_handle_t *handle, @@ -120,7 +120,7 @@ void FLEXIO_I2S_TransferRxCreateHandleEDMA(FLEXIO_I2S_Type *base, * @brief Configures the FlexIO I2S Tx audio format. * * Audio format can be changed in run-time of FlexIO I2S. This function configures the sample rate and audio data - * format to be transferred. This function also sets eDMA parameter according to format. + * format to be transferred. This function also sets the eDMA parameter according to format. * * @param base FlexIO I2S peripheral base address. * @param handle FlexIO I2S eDMA handle pointer @@ -137,8 +137,8 @@ void FLEXIO_I2S_TransferSetFormatEDMA(FLEXIO_I2S_Type *base, /*! * @brief Performs a non-blocking FlexIO I2S transfer using DMA. * - * @note This interface returned immediately after transfer initiates, users should call - * FLEXIO_I2S_GetTransferStatus to poll the transfer status to check whether FlexIO I2S transfer finished. + * @note This interface returned immediately after transfer initiates. Users should call + * FLEXIO_I2S_GetTransferStatus to poll the transfer status and check whether the FlexIO I2S transfer is finished. * * @param base FlexIO I2S peripheral base address. * @param handle FlexIO I2S DMA handle pointer. @@ -154,8 +154,8 @@ status_t FLEXIO_I2S_TransferSendEDMA(FLEXIO_I2S_Type *base, /*! * @brief Performs a non-blocking FlexIO I2S receive using eDMA. * - * @note This interface returned immediately after transfer initiates, users should call - * FLEXIO_I2S_GetReceiveRemainingBytes to poll the transfer status to check whether FlexIO I2S transfer finished. + * @note This interface returned immediately after transfer initiates. Users should call + * FLEXIO_I2S_GetReceiveRemainingBytes to poll the transfer status and check whether the FlexIO I2S transfer is finished. * * @param base FlexIO I2S peripheral base address. * @param handle FlexIO I2S DMA handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.c index f6f69c9ed8..b8b63630c3 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.c @@ -198,7 +198,7 @@ static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base, /* Configure DMA channel. */ if (xfer->txData) { - xferConfig.srcOffset = 1; + xferConfig.srcOffset = bytesPerFrame; xferConfig.srcAddr = (uint32_t)(xfer->txData); } else @@ -210,6 +210,9 @@ static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base, xferConfig.majorLoopCounts = (xfer->dataSize / xferConfig.minorLoopBytes); + /* Store the initially configured eDMA minor byte transfer count into the FLEXIO SPI handle */ + handle->nbytes = xferConfig.minorLoopBytes; + if (handle->txHandle) { EDMA_SubmitTransfer(handle->txHandle, &xferConfig); @@ -219,9 +222,16 @@ static void FLEXIO_SPI_EDMAConfig(FLEXIO_SPI_Type *base, if (xfer->rxData) { xferConfig.srcAddr = FLEXIO_SPI_GetRxDataRegisterAddress(base, direction); + if (bytesPerFrame == 2U) + { + if (direction == kFLEXIO_SPI_LsbFirst) + { + xferConfig.srcAddr -= 1U; + } + } xferConfig.srcOffset = 0; xferConfig.destAddr = (uint32_t)(xfer->rxData); - xferConfig.destOffset = 1; + xferConfig.destOffset = bytesPerFrame; EDMA_SubmitTransfer(handle->rxHandle, &xferConfig); handle->rxInProgress = true; FLEXIO_SPI_EnableDMA(base, kFLEXIO_SPI_RxDmaEnable, true); @@ -349,11 +359,15 @@ status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base, if (handle->rxInProgress) { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->rxHandle->base, handle->rxHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxHandle->base, handle->rxHandle->channel)); } else { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->txHandle->base, handle->txHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txHandle->base, handle->txHandle->channel)); } return kStatus_Success; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.h index 4b942e8cc8..6c2778c86f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_spi_edma.h @@ -38,7 +38,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -65,6 +64,7 @@ typedef void (*flexio_spi_slave_edma_transfer_callback_t)(FLEXIO_SPI_Type *base, struct _flexio_spi_master_edma_handle { size_t transferSize; /*!< Total bytes to be transferred. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ bool txInProgress; /*!< Send transfer in progress */ bool rxInProgress; /*!< Receive transfer in progress */ edma_handle_t *txHandle; /*!< DMA handler for SPI send */ @@ -86,14 +86,14 @@ extern "C" { */ /*! - * @brief Initializes the FLEXO SPI master eDMA handle. + * @brief Initializes the FlexIO SPI master eDMA handle. * - * This function initializes the FLEXO SPI master eDMA handle which can be used for other FLEXO SPI master transactional + * This function initializes the FlexIO SPI master eDMA handle which can be used for other FlexIO SPI master transactional * APIs. - * For a specified FLEXO SPI instance, call this API once to get the initialized handle. + * For a specified FlexIO SPI instance, call this API once to get the initialized handle. * - * @param base pointer to FLEXIO_SPI_Type structure. - * @param handle pointer to flexio_spi_master_edma_handle_t structure to store the transfer state. + * @param base Pointer to FLEXIO_SPI_Type structure. + * @param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state. * @param callback SPI callback, NULL means no callback. * @param userData callback function parameter. * @param txHandle User requested eDMA handle for FlexIO SPI RX eDMA transfer. @@ -112,11 +112,11 @@ status_t FLEXIO_SPI_MasterTransferCreateHandleEDMA(FLEXIO_SPI_Type *base, * @brief Performs a non-blocking FlexIO SPI transfer using eDMA. * * @note This interface returns immediately after transfer initiates. Call - * FLEXIO_SPI_MasterGetTransferCountEDMA to poll the transfer status to check - * whether FlexIO SPI transfer finished. + * FLEXIO_SPI_MasterGetTransferCountEDMA to poll the transfer status and check + * whether the FlexIO SPI transfer is finished. * - * @param base pointer to FLEXIO_SPI_Type structure. - * @param handle pointer to flexio_spi_master_edma_handle_t structure to store the transfer state. + * @param base Pointer to FLEXIO_SPI_Type structure. + * @param handle Pointer to flexio_spi_master_edma_handle_t structure to store the transfer state. * @param xfer Pointer to FlexIO SPI transfer structure. * @retval kStatus_Success Successfully start a transfer. * @retval kStatus_InvalidArgument Input argument is invalid. @@ -129,7 +129,7 @@ status_t FLEXIO_SPI_MasterTransferEDMA(FLEXIO_SPI_Type *base, /*! * @brief Aborts a FlexIO SPI transfer using eDMA. * - * @param base pointer to FLEXIO_SPI_Type structure. + * @param base Pointer to FLEXIO_SPI_Type structure. * @param handle FlexIO SPI eDMA handle pointer. */ void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master_edma_handle_t *handle); @@ -137,7 +137,7 @@ void FLEXIO_SPI_MasterTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_master /*! * @brief Gets the remaining bytes for FlexIO SPI eDMA transfer. * - * @param base pointer to FLEXIO_SPI_Type structure. + * @param base Pointer to FLEXIO_SPI_Type structure. * @param handle FlexIO SPI eDMA handle pointer. * @param count Number of bytes transferred so far by the non-blocking transaction. */ @@ -150,8 +150,8 @@ status_t FLEXIO_SPI_MasterTransferGetCountEDMA(FLEXIO_SPI_Type *base, * * This function initializes the FlexIO SPI slave eDMA handle. * - * @param base pointer to FLEXIO_SPI_Type structure. - * @param handle pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state. + * @param base Pointer to FLEXIO_SPI_Type structure. + * @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state. * @param callback SPI callback, NULL means no callback. * @param userData callback function parameter. * @param txHandle User requested eDMA handle for FlexIO SPI TX eDMA transfer. @@ -171,11 +171,11 @@ static inline void FLEXIO_SPI_SlaveTransferCreateHandleEDMA(FLEXIO_SPI_Type *bas * @brief Performs a non-blocking FlexIO SPI transfer using eDMA. * * @note This interface returns immediately after transfer initiates. Call - * FLEXIO_SPI_SlaveGetTransferCountEDMA to poll the transfer status to - * check whether FlexIO SPI transfer finished. + * FLEXIO_SPI_SlaveGetTransferCountEDMA to poll the transfer status and + * check whether the FlexIO SPI transfer is finished. * - * @param base pointer to FLEXIO_SPI_Type structure. - * @param handle pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state. + * @param base Pointer to FLEXIO_SPI_Type structure. + * @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state. * @param xfer Pointer to FlexIO SPI transfer structure. * @retval kStatus_Success Successfully start a transfer. * @retval kStatus_InvalidArgument Input argument is invalid. @@ -188,8 +188,8 @@ status_t FLEXIO_SPI_SlaveTransferEDMA(FLEXIO_SPI_Type *base, /*! * @brief Aborts a FlexIO SPI transfer using eDMA. * - * @param base pointer to FLEXIO_SPI_Type structure. - * @param handle pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state. + * @param base Pointer to FLEXIO_SPI_Type structure. + * @param handle Pointer to flexio_spi_slave_edma_handle_t structure to store the transfer state. */ static inline void FLEXIO_SPI_SlaveTransferAbortEDMA(FLEXIO_SPI_Type *base, flexio_spi_slave_edma_handle_t *handle) { @@ -199,7 +199,7 @@ static inline void FLEXIO_SPI_SlaveTransferAbortEDMA(FLEXIO_SPI_Type *base, flex /*! * @brief Gets the remaining bytes to be transferred for FlexIO SPI eDMA. * - * @param base pointer to FLEXIO_SPI_Type structure. + * @param base Pointer to FLEXIO_SPI_Type structure. * @param handle FlexIO SPI eDMA handle pointer. * @param count Number of bytes transferred so far by the non-blocking transaction. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.c index 0c3655419c..6367ed83dc 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.c @@ -217,12 +217,16 @@ status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base, else { handle->txState = kFLEXIO_UART_TxBusy; + handle->txDataSizeAll = xfer->dataSize; /* Prepare transfer. */ EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)FLEXIO_UART_GetTxDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -259,11 +263,15 @@ status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base, else { handle->rxState = kFLEXIO_UART_RxBusy; + handle->rxDataSizeAll = xfer->dataSize; /* Prepare transfer. */ EDMA_PrepareTransfer(&xferConfig, (void *)FLEXIO_UART_GetRxDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the FLEXIO UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -307,42 +315,36 @@ status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count) { + assert(handle); assert(handle->rxEdmaHandle); + assert(count); - if (!count) + if (kFLEXIO_UART_RxIdle == handle->rxState) { - return kStatus_InvalidArgument; + return kStatus_NoTransferInProgress; } - if (kFLEXIO_UART_RxBusy == handle->rxState) - { - *count = (handle->rxSize - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel)); - } - else - { - *count = handle->rxSize; - } + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count) { + assert(handle); assert(handle->txEdmaHandle); + assert(count); - if (!count) + if (kFLEXIO_UART_TxIdle == handle->txState) { - return kStatus_InvalidArgument; + return kStatus_NoTransferInProgress; } - if (kFLEXIO_UART_TxBusy == handle->txState) - { - *count = (handle->txSize - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel)); - } - else - { - *count = handle->txSize; - } + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.h index bcd5945c67..817392f3a0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_flexio_uart_edma.h @@ -39,7 +39,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -61,12 +60,14 @@ struct _flexio_uart_edma_handle flexio_uart_edma_transfer_callback_t callback; /*!< Callback function. */ void *userData; /*!< UART callback function parameter.*/ - size_t txSize; /*!< Total bytes to be sent. */ - size_t rxSize; /*!< Total bytes to be received. */ + size_t txDataSizeAll; /*!< Total bytes to be sent. */ + size_t rxDataSizeAll; /*!< Total bytes to be received. */ edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -87,7 +88,7 @@ extern "C" { /*! * @brief Initializes the UART handle which is used in transactional functions. * - * @param base pointer to FLEXIO_UART_Type. + * @param base Pointer to FLEXIO_UART_Type. * @param handle Pointer to flexio_uart_edma_handle_t structure. * @param callback The callback function. * @param userData The parameter of the callback function. @@ -107,9 +108,9 @@ status_t FLEXIO_UART_TransferCreateHandleEDMA(FLEXIO_UART_Type *base, * @brief Sends data using eDMA. * * This function sends data using eDMA. This is a non-blocking function, which returns - * right away. When all data have been sent out, the send callback function is called. + * right away. When all data is sent out, the send callback function is called. * - * @param base pointer to FLEXIO_UART_Type + * @param base Pointer to FLEXIO_UART_Type * @param handle UART handle pointer. * @param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t. * @retval kStatus_Success if succeed, others failed. @@ -123,9 +124,9 @@ status_t FLEXIO_UART_TransferSendEDMA(FLEXIO_UART_Type *base, * @brief Receives data using eDMA. * * This function receives data using eDMA. This is a non-blocking function, which returns - * right away. When all data have been received, the receive callback function is called. + * right away. When all data is received, the receive callback function is called. * - * @param base pointer to FLEXIO_UART_Type + * @param base Pointer to FLEXIO_UART_Type * @param handle Pointer to flexio_uart_edma_handle_t structure * @param xfer UART eDMA transfer structure, see #flexio_uart_transfer_t. * @retval kStatus_Success if succeed, others failed. @@ -140,7 +141,7 @@ status_t FLEXIO_UART_TransferReceiveEDMA(FLEXIO_UART_Type *base, * * This function aborts sent data which using eDMA. * - * @param base pointer to FLEXIO_UART_Type + * @param base Pointer to FLEXIO_UART_Type * @param handle Pointer to flexio_uart_edma_handle_t structure */ void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle); @@ -150,30 +151,34 @@ void FLEXIO_UART_TransferAbortSendEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_ * * This function aborts the receive data which using eDMA. * - * @param base pointer to FLEXIO_UART_Type + * @param base Pointer to FLEXIO_UART_Type * @param handle Pointer to flexio_uart_edma_handle_t structure */ void FLEXIO_UART_TransferAbortReceiveEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle); /*! - * @brief Gets the number of bytes still not sent out. + * @brief Gets the number of bytes sent out. * - * This function gets the number of bytes still not sent out. + * This function gets the number of bytes sent out. * - * @param base pointer to FLEXIO_UART_Type + * @param base Pointer to FLEXIO_UART_Type * @param handle Pointer to flexio_uart_edma_handle_t structure * @param count Number of bytes sent so far by the non-blocking transaction. + * @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress. + * @retval kStatus_Success Successfully return the count. */ status_t FLEXIO_UART_TransferGetSendCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, size_t *count); /*! - * @brief Gets the number of bytes still not received. + * @brief Gets the number of bytes received. * - * This function gets the number of bytes still not received. + * This function gets the number of bytes received. * - * @param base pointer to FLEXIO_UART_Type + * @param base Pointer to FLEXIO_UART_Type * @param handle Pointer to flexio_uart_edma_handle_t structure - * @param count Number of bytes sent so far by the non-blocking transaction. + * @param count Number of bytes received so far by the non-blocking transaction. + * @retval kStatus_NoTransferInProgress transfer has finished or no transfer in progress. + * @retval kStatus_Success Successfully return the count. */ status_t FLEXIO_UART_TransferGetReceiveCountEDMA(FLEXIO_UART_Type *base, flexio_uart_edma_handle_t *handle, diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.c index 290ee3af3d..e008da004a 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.c @@ -53,7 +53,7 @@ enum _qspi_edma_tansfer_states ******************************************************************************/ /*count = base->TBCT + 1; /* Configure TX edma callback */ - EDMA_SetCallback(handle->dmaHandle, QSPI_SendEDMACallback, &s_edmaPrivateHandle[instance]); + EDMA_SetCallback(handle->dmaHandle, QSPI_SendEDMACallback, &s_edmaPrivateHandle[instance][0]); } void QSPI_TransferRxCreateHandleEDMA(QuadSPI_Type *base, @@ -172,8 +172,8 @@ void QSPI_TransferRxCreateHandleEDMA(QuadSPI_Type *base, uint32_t instance = QSPI_GetInstance(base); - s_edmaPrivateHandle[instance].base = base; - s_edmaPrivateHandle[instance].handle = handle; + s_edmaPrivateHandle[instance][1].base = base; + s_edmaPrivateHandle[instance][1].handle = handle; memset(handle, 0, sizeof(*handle)); @@ -187,7 +187,7 @@ void QSPI_TransferRxCreateHandleEDMA(QuadSPI_Type *base, handle->count = (base->RBCT & QuadSPI_RBCT_WMRK_MASK) + 1; /* Configure RX edma callback */ - EDMA_SetCallback(handle->dmaHandle, QSPI_ReceiveEDMACallback, &s_edmaPrivateHandle[instance]); + EDMA_SetCallback(handle->dmaHandle, QSPI_ReceiveEDMACallback, &s_edmaPrivateHandle[instance][1]); } status_t QSPI_TransferSendEDMA(QuadSPI_Type *base, qspi_edma_handle_t *handle, qspi_transfer_t *xfer) @@ -211,6 +211,9 @@ status_t QSPI_TransferSendEDMA(QuadSPI_Type *base, qspi_edma_handle_t *handle, q sizeof(uint32_t), (sizeof(uint32_t) * handle->count), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the QSPI handle */ + handle->nbytes = (sizeof(uint32_t) * handle->count); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->dmaHandle, &xferConfig); EDMA_StartTransfer(handle->dmaHandle); @@ -243,10 +246,13 @@ status_t QSPI_TransferReceiveEDMA(QuadSPI_Type *base, qspi_edma_handle_t *handle /* Prepare transfer. */ EDMA_PrepareTransfer(&xferConfig, (void *)QSPI_GetRxDataRegisterAddress(base), sizeof(uint32_t), xfer->data, sizeof(uint32_t), (sizeof(uint32_t) * handle->count), xfer->dataSize, - kEDMA_PeripheralToMemory); + kEDMA_MemoryToMemory); + /* Store the initially configured eDMA minor byte transfer count into the QSPI handle */ + handle->nbytes = (sizeof(uint32_t) * handle->count); /* Submit transfer. */ EDMA_SubmitTransfer(handle->dmaHandle, &xferConfig); + handle->dmaHandle->base->TCD[handle->dmaHandle->channel].ATTR |= DMA_ATTR_SMOD(0x5U); EDMA_StartTransfer(handle->dmaHandle); /* Enable QSPI TX EDMA. */ @@ -296,7 +302,9 @@ status_t QSPI_TransferGetSendCountEDMA(QuadSPI_Type *base, qspi_edma_handle_t *h } else { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; @@ -314,7 +322,9 @@ status_t QSPI_TransferGetReceiveCountEDMA(QuadSPI_Type *base, qspi_edma_handle_t } else { - *count = (handle->transferSize - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + *count = (handle->transferSize - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.h index b3d6081145..0fa0fa2de0 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KL82Z/drivers/fsl_qspi_edma.h @@ -39,7 +39,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -54,6 +53,7 @@ struct _qspi_edma_handle { edma_handle_t *dmaHandle; /*!< eDMA handler for QSPI send */ size_t transferSize; /*!< Bytes need to transfer. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ uint8_t count; /*!< The transfer data count in a DMA request */ uint32_t state; /*!< Internal state for QSPI eDMA transfer */ qspi_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurred */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.c index 9b1b2f6c49..116d088d9f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.c @@ -1,40 +1,25 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted 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 Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_sai_edma.h" +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.sai_edma" +#endif + /******************************************************************************* * Definitations ******************************************************************************/ /* Used for 32byte aligned */ -#define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)address + 32) & ~0x1FU) +#define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)(address) + 32) & ~0x1FU) + +static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS; /*saiQueue[saiHandle->queueDriver].data == NULL) { - SAI_TransferAbortSendEDMA(privHandle->base, saiHandle); + /* Disable DMA enable bit */ + SAI_TxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false); + EDMA_AbortTransfer(handle); } } @@ -121,10 +126,25 @@ static void SAI_RxEDMACallback(edma_handle_t *handle, void *userData, bool done, /* If all data finished, just stop the transfer */ if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL) { - SAI_TransferAbortReceiveEDMA(privHandle->base, saiHandle); + /* Disable DMA enable bit */ + SAI_RxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false); + EDMA_AbortTransfer(handle); } } +/*! + * brief Initializes the SAI eDMA handle. + * + * This function initializes the SAI master DMA handle, which can be used for other SAI master transactional APIs. + * Usually, for a specified SAI instance, call this API once to get the initialized handle. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param base SAI peripheral base address. + * param callback Pointer to user callback function. + * param userData User parameter passed to the callback function. + * param dmaHandle eDMA handle pointer, this handle shall be static allocated by users. + */ void SAI_TransferTxCreateHandleEDMA( I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle) { @@ -132,6 +152,9 @@ void SAI_TransferTxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -144,12 +167,25 @@ void SAI_TransferTxCreateHandleEDMA( s_edmaPrivateHandle[instance][0].handle = handle; /* Need to use scatter gather */ - EDMA_InstallTCDMemory(dmaHandle, STCD_ADDR(handle->tcd), SAI_XFER_QUEUE_SIZE); + EDMA_InstallTCDMemory(dmaHandle, (edma_tcd_t *)(STCD_ADDR(handle->tcd)), SAI_XFER_QUEUE_SIZE); /* Install callback for Tx dma channel */ EDMA_SetCallback(dmaHandle, SAI_TxEDMACallback, &s_edmaPrivateHandle[instance][0]); } +/*! + * brief Initializes the SAI Rx eDMA handle. + * + * This function initializes the SAI slave DMA handle, which can be used for other SAI master transactional APIs. + * Usually, for a specified SAI instance, call this API once to get the initialized handle. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param base SAI peripheral base address. + * param callback Pointer to user callback function. + * param userData User parameter passed to the callback function. + * param dmaHandle eDMA handle pointer, this handle shall be static allocated by users. + */ void SAI_TransferRxCreateHandleEDMA( I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle) { @@ -157,6 +193,9 @@ void SAI_TransferRxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -175,6 +214,21 @@ void SAI_TransferRxCreateHandleEDMA( EDMA_SetCallback(dmaHandle, SAI_RxEDMACallback, &s_edmaPrivateHandle[instance][1]); } +/*! + * brief Configures the SAI Tx audio format. + * + * The audio format can be changed at run-time. This function configures the sample rate and audio data + * format to be transferred. This function also sets the eDMA parameter according to formatting requirements. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param format Pointer to SAI audio data format structure. + * param mclkSourceClockHz SAI master clock source frequency in Hz. + * param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master + * clock, this value should equals to masterClockHz in format. + * retval kStatus_Success Audio format set successfully. + * retval kStatus_InvalidArgument The input argument is invalid. +*/ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_format_t *format, @@ -187,10 +241,20 @@ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; + + /* Clear the channel enable bits unitl do a send/receive */ + base->TCR3 &= ~I2S_TCR3_TCE_MASK; #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) handle->count = FSL_FEATURE_SAI_FIFO_COUNT - format->watermark; #else @@ -198,6 +262,21 @@ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ } +/*! + * brief Configures the SAI Rx audio format. + * + * The audio format can be changed at run-time. This function configures the sample rate and audio data + * format to be transferred. This function also sets the eDMA parameter according to formatting requirements. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param format Pointer to SAI audio data format structure. + * param mclkSourceClockHz SAI master clock source frequency in Hz. + * param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is the master + * clock, this value should equal to masterClockHz in format. + * retval kStatus_Success Audio format set successfully. + * retval kStatus_InvalidArgument The input argument is invalid. +*/ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_format_t *format, @@ -210,11 +289,20 @@ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; + /* Clear the channel enable bits unitl do a send/receive */ + base->RCR3 &= ~I2S_RCR3_RCE_MASK; #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) handle->count = format->watermark; #else @@ -222,6 +310,19 @@ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ } +/*! + * brief Performs a non-blocking SAI transfer using DMA. + * + * note This interface returns immediately after the transfer initiates. Call + * SAI_GetTransferStatus to poll the transfer status and check whether the SAI transfer is finished. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param xfer Pointer to the DMA transfer structure. + * retval kStatus_Success Start a SAI eDMA send successfully. + * retval kStatus_InvalidArgument The input argument is invalid. + * retval kStatus_TxBusy SAI is busy sending data. + */ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer) { assert(handle && xfer); @@ -253,6 +354,9 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra EDMA_PrepareTransfer(&config, xfer->data, handle->bytesPerFrame, (void *)destAddr, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -264,9 +368,25 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra /* Enable SAI Tx clock */ SAI_TxEnable(base, true); + /* Enable the channel FIFO */ + base->TCR3 |= I2S_TCR3_TCE(1U << handle->channel); + return kStatus_Success; } +/*! + * brief Performs a non-blocking SAI receive using eDMA. + * + * note This interface returns immediately after the transfer initiates. Call + * the SAI_GetReceiveRemainingBytes to poll the transfer status and check whether the SAI transfer is finished. + * + * param base SAI base pointer + * param handle SAI eDMA handle pointer. + * param xfer Pointer to DMA transfer structure. + * retval kStatus_Success Start a SAI eDMA receive successfully. + * retval kStatus_InvalidArgument The input argument is invalid. + * retval kStatus_RxBusy SAI is busy receiving data. + */ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer) { assert(handle && xfer); @@ -298,6 +418,9 @@ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_ EDMA_PrepareTransfer(&config, (void *)srcAddr, handle->bytesPerFrame, xfer->data, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -306,12 +429,24 @@ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_ /* Enable DMA enable bit */ SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, true); + /* Enable the channel FIFO */ + base->RCR3 |= I2S_RCR3_RCE(1U << handle->channel); + /* Enable SAI Rx clock */ SAI_RxEnable(base, true); return kStatus_Success; } +/*! + * brief Aborts a SAI transfer using eDMA. + * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateSendEDMA. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + */ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) { assert(handle); @@ -319,13 +454,36 @@ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable dma */ EDMA_AbortTransfer(handle->dmaHandle); + /* Disable the channel FIFO */ + base->TCR3 &= ~I2S_TCR3_TCE_MASK; + /* Disable DMA enable bit */ SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Tx */ + SAI_TxEnable(base, false); + + /* Reset the FIFO pointer, at the same time clear all error flags if set */ + base->TCSR |= (I2S_TCSR_FR_MASK | I2S_TCSR_SR_MASK); + base->TCSR &= ~I2S_TCSR_SR_MASK; + + /* Handle the queue index */ + memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t)); + handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE; + /* Set the handle state */ handle->state = kSAI_Idle; } +/*! + * brief Aborts a SAI receive using eDMA. + * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateReceiveEDMA. + * + * param base SAI base pointer + * param handle SAI eDMA handle pointer. + */ void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) { assert(handle); @@ -333,13 +491,84 @@ void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable dma */ EDMA_AbortTransfer(handle->dmaHandle); + /* Disable the channel FIFO */ + base->RCR3 &= ~I2S_RCR3_RCE_MASK; + /* Disable DMA enable bit */ SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Rx */ + SAI_RxEnable(base, false); + + /* Reset the FIFO pointer, at the same time clear all error flags if set */ + base->RCSR |= (I2S_RCSR_FR_MASK | I2S_RCSR_SR_MASK); + base->RCSR &= ~I2S_RCSR_SR_MASK; + + /* Handle the queue index */ + memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t)); + handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE; + /* Set the handle state */ handle->state = kSAI_Idle; } +/*! + * brief Terminate all SAI send. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortSendEDMA. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) +{ + assert(handle); + + /* Abort the current transfer */ + SAI_TransferAbortSendEDMA(base, handle); + + /* Clear all the internal information */ + memset(handle->tcd, 0U, sizeof(handle->tcd)); + memset(handle->saiQueue, 0U, sizeof(handle->saiQueue)); + memset(handle->transferSize, 0U, sizeof(handle->transferSize)); + handle->queueUser = 0U; + handle->queueDriver = 0U; +} + +/*! + * brief Terminate all SAI receive. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortReceiveEDMA. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) +{ + assert(handle); + + /* Abort the current transfer */ + SAI_TransferAbortReceiveEDMA(base, handle); + + /* Clear all the internal information */ + memset(handle->tcd, 0U, sizeof(handle->tcd)); + memset(handle->saiQueue, 0U, sizeof(handle->saiQueue)); + memset(handle->transferSize, 0U, sizeof(handle->transferSize)); + handle->queueUser = 0U; + handle->queueDriver = 0U; +} + +/*! + * brief Gets byte count sent by SAI. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param count Bytes count sent by SAI. + * retval kStatus_Success Succeed get the transfer count. + * retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress. + */ status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count) { assert(handle); @@ -353,12 +582,22 @@ status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; } +/*! + * brief Gets byte count received by SAI. + * + * param base SAI base pointer + * param handle SAI eDMA handle pointer. + * param count Bytes count received by SAI. + * retval kStatus_Success Succeed get the transfer count. + * retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress. + */ status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count) { assert(handle); @@ -372,7 +611,8 @@ status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *hand else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.h index 03c2e51451..b3d913948b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_sai_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted 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 Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SAI_EDMA_H_ #define _FSL_SAI_EDMA_H_ @@ -38,11 +16,15 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ +/*! @name Driver version */ +/*@{*/ +#define FSL_SAI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 5)) /*!< Version 2.1.5 */ +/*@}*/ + typedef struct _sai_edma_handle sai_edma_handle_t; /*! @brief SAI eDMA transfer callback function for finish and error */ @@ -51,18 +33,19 @@ typedef void (*sai_edma_callback_t)(I2S_Type *base, sai_edma_handle_t *handle, s /*! @brief SAI DMA transfer handle, users should not touch the content of the handle.*/ struct _sai_edma_handle { - edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */ - uint8_t bytesPerFrame; /*!< Bytes in a frame */ - uint8_t channel; /*!< Which data channel */ - uint8_t count; /*!< The transfer data count in a DMA request */ - uint32_t state; /*!< Internal state for SAI eDMA transfer */ - sai_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */ - void *userData; /*!< User callback parameter */ - edma_tcd_t tcd[SAI_XFER_QUEUE_SIZE + 1U]; /*!< TCD pool for eDMA transfer. */ - sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */ - size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */ - volatile uint8_t queueUser; /*!< Index for user to queue transfer. */ - volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */ + edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + uint8_t bytesPerFrame; /*!< Bytes in a frame */ + uint8_t channel; /*!< Which data channel */ + uint8_t count; /*!< The transfer data count in a DMA request */ + uint32_t state; /*!< Internal state for SAI eDMA transfer */ + sai_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */ + void *userData; /*!< User callback parameter */ + uint8_t tcd[(SAI_XFER_QUEUE_SIZE + 1U) * sizeof(edma_tcd_t)]; /*!< TCD pool for eDMA transfer. */ + sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */ + size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */ + volatile uint8_t queueUser; /*!< Index for user to queue transfer. */ + volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */ }; /******************************************************************************* @@ -181,9 +164,34 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra */ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer); +/*! + * @brief Terminate all SAI send. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortSendEDMA. + * + * @param base SAI base pointer. + * @param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateSendEDMA(I2S_Type *base, sai_edma_handle_t *handle); + +/*! + * @brief Terminate all SAI receive. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortReceiveEDMA. + * + * @param base SAI base pointer. + * @param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle); + /*! * @brief Aborts a SAI transfer using eDMA. * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateSendEDMA. + * * @param base SAI base pointer. * @param handle SAI eDMA handle pointer. */ @@ -192,6 +200,9 @@ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle); /*! * @brief Aborts a SAI receive using eDMA. * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateReceiveEDMA. + * * @param base SAI base pointer * @param handle SAI eDMA handle pointer. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.c index a4faa9449f..c51e493463 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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. * @@ -246,6 +246,9 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -284,6 +287,9 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -336,7 +342,9 @@ status_t UART_TransferGetReceiveCountEDMA(UART_Type *base, uart_edma_handle_t *h return kStatus_NoTransferInProgress; } - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } @@ -352,7 +360,9 @@ status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *hand return kStatus_NoTransferInProgress; } - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.h index ea0974a274..e411ffd7a4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_KW24D/drivers/fsl_uart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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. * @@ -39,7 +39,6 @@ * @{ */ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -66,6 +65,8 @@ struct _uart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -86,18 +87,18 @@ extern "C" { /*! * @brief Initializes the UART handle which is used in transactional functions. * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param callback UART callback, NULL means no callback. * @param userData User callback function data. - * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. - * @param txEdmaHandle User requested DMA handle for TX DMA transfer. + * @param rxEdmaHandle User-requested DMA handle for RX DMA transfer. + * @param txEdmaHandle User-requested DMA handle for TX DMA transfer. */ void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -108,23 +109,23 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_TxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_TxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Receive data using eDMA. + * @brief Receives data using eDMA. * * This function receives data using eDMA. This is a non-blocking function, which returns * right away. When all data is received, the receive callback function is called. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_RxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); @@ -135,7 +136,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran * This function aborts sent data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); @@ -145,12 +146,12 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); * This function aborts receive data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes that have been written to UART TX register. * * This function gets the number of bytes that have been written to UART TX * register by DMA. @@ -165,9 +166,9 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base UART peripheral base address. * @param handle UART handle pointer. diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.c index 9b1b2f6c49..116d088d9f 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.c @@ -1,40 +1,25 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted 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 Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 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. + * SPDX-License-Identifier: BSD-3-Clause */ #include "fsl_sai_edma.h" +/* Component ID definition, used by tools. */ +#ifndef FSL_COMPONENT_ID +#define FSL_COMPONENT_ID "platform.drivers.sai_edma" +#endif + /******************************************************************************* * Definitations ******************************************************************************/ /* Used for 32byte aligned */ -#define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)address + 32) & ~0x1FU) +#define STCD_ADDR(address) (edma_tcd_t *)(((uint32_t)(address) + 32) & ~0x1FU) + +static I2S_Type *const s_saiBases[] = I2S_BASE_PTRS; /*saiQueue[saiHandle->queueDriver].data == NULL) { - SAI_TransferAbortSendEDMA(privHandle->base, saiHandle); + /* Disable DMA enable bit */ + SAI_TxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false); + EDMA_AbortTransfer(handle); } } @@ -121,10 +126,25 @@ static void SAI_RxEDMACallback(edma_handle_t *handle, void *userData, bool done, /* If all data finished, just stop the transfer */ if (saiHandle->saiQueue[saiHandle->queueDriver].data == NULL) { - SAI_TransferAbortReceiveEDMA(privHandle->base, saiHandle); + /* Disable DMA enable bit */ + SAI_RxEnableDMA(privHandle->base, kSAI_FIFORequestDMAEnable, false); + EDMA_AbortTransfer(handle); } } +/*! + * brief Initializes the SAI eDMA handle. + * + * This function initializes the SAI master DMA handle, which can be used for other SAI master transactional APIs. + * Usually, for a specified SAI instance, call this API once to get the initialized handle. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param base SAI peripheral base address. + * param callback Pointer to user callback function. + * param userData User parameter passed to the callback function. + * param dmaHandle eDMA handle pointer, this handle shall be static allocated by users. + */ void SAI_TransferTxCreateHandleEDMA( I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle) { @@ -132,6 +152,9 @@ void SAI_TransferTxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -144,12 +167,25 @@ void SAI_TransferTxCreateHandleEDMA( s_edmaPrivateHandle[instance][0].handle = handle; /* Need to use scatter gather */ - EDMA_InstallTCDMemory(dmaHandle, STCD_ADDR(handle->tcd), SAI_XFER_QUEUE_SIZE); + EDMA_InstallTCDMemory(dmaHandle, (edma_tcd_t *)(STCD_ADDR(handle->tcd)), SAI_XFER_QUEUE_SIZE); /* Install callback for Tx dma channel */ EDMA_SetCallback(dmaHandle, SAI_TxEDMACallback, &s_edmaPrivateHandle[instance][0]); } +/*! + * brief Initializes the SAI Rx eDMA handle. + * + * This function initializes the SAI slave DMA handle, which can be used for other SAI master transactional APIs. + * Usually, for a specified SAI instance, call this API once to get the initialized handle. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param base SAI peripheral base address. + * param callback Pointer to user callback function. + * param userData User parameter passed to the callback function. + * param dmaHandle eDMA handle pointer, this handle shall be static allocated by users. + */ void SAI_TransferRxCreateHandleEDMA( I2S_Type *base, sai_edma_handle_t *handle, sai_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle) { @@ -157,6 +193,9 @@ void SAI_TransferRxCreateHandleEDMA( uint32_t instance = SAI_GetInstance(base); + /* Zero the handle */ + memset(handle, 0, sizeof(*handle)); + /* Set sai base to handle */ handle->dmaHandle = dmaHandle; handle->callback = callback; @@ -175,6 +214,21 @@ void SAI_TransferRxCreateHandleEDMA( EDMA_SetCallback(dmaHandle, SAI_RxEDMACallback, &s_edmaPrivateHandle[instance][1]); } +/*! + * brief Configures the SAI Tx audio format. + * + * The audio format can be changed at run-time. This function configures the sample rate and audio data + * format to be transferred. This function also sets the eDMA parameter according to formatting requirements. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param format Pointer to SAI audio data format structure. + * param mclkSourceClockHz SAI master clock source frequency in Hz. + * param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master + * clock, this value should equals to masterClockHz in format. + * retval kStatus_Success Audio format set successfully. + * retval kStatus_InvalidArgument The input argument is invalid. +*/ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_format_t *format, @@ -187,10 +241,20 @@ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, SAI_TxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; + + /* Clear the channel enable bits unitl do a send/receive */ + base->TCR3 &= ~I2S_TCR3_TCE_MASK; #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) handle->count = FSL_FEATURE_SAI_FIFO_COUNT - format->watermark; #else @@ -198,6 +262,21 @@ void SAI_TransferTxSetFormatEDMA(I2S_Type *base, #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ } +/*! + * brief Configures the SAI Rx audio format. + * + * The audio format can be changed at run-time. This function configures the sample rate and audio data + * format to be transferred. This function also sets the eDMA parameter according to formatting requirements. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param format Pointer to SAI audio data format structure. + * param mclkSourceClockHz SAI master clock source frequency in Hz. + * param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is the master + * clock, this value should equal to masterClockHz in format. + * retval kStatus_Success Audio format set successfully. + * retval kStatus_InvalidArgument The input argument is invalid. +*/ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_format_t *format, @@ -210,11 +289,20 @@ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, SAI_RxSetFormat(base, format, mclkSourceClockHz, bclkSourceClockHz); /* Get the tranfer size from format, this should be used in EDMA configuration */ - handle->bytesPerFrame = format->bitWidth / 8U; + if (format->bitWidth == 24U) + { + handle->bytesPerFrame = 4U; + } + else + { + handle->bytesPerFrame = format->bitWidth / 8U; + } /* Update the data channel SAI used */ handle->channel = format->channel; + /* Clear the channel enable bits unitl do a send/receive */ + base->RCR3 &= ~I2S_RCR3_RCE_MASK; #if defined(FSL_FEATURE_SAI_FIFO_COUNT) && (FSL_FEATURE_SAI_FIFO_COUNT > 1) handle->count = format->watermark; #else @@ -222,6 +310,19 @@ void SAI_TransferRxSetFormatEDMA(I2S_Type *base, #endif /* FSL_FEATURE_SAI_FIFO_COUNT */ } +/*! + * brief Performs a non-blocking SAI transfer using DMA. + * + * note This interface returns immediately after the transfer initiates. Call + * SAI_GetTransferStatus to poll the transfer status and check whether the SAI transfer is finished. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param xfer Pointer to the DMA transfer structure. + * retval kStatus_Success Start a SAI eDMA send successfully. + * retval kStatus_InvalidArgument The input argument is invalid. + * retval kStatus_TxBusy SAI is busy sending data. + */ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer) { assert(handle && xfer); @@ -253,6 +354,9 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra EDMA_PrepareTransfer(&config, xfer->data, handle->bytesPerFrame, (void *)destAddr, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -264,9 +368,25 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra /* Enable SAI Tx clock */ SAI_TxEnable(base, true); + /* Enable the channel FIFO */ + base->TCR3 |= I2S_TCR3_TCE(1U << handle->channel); + return kStatus_Success; } +/*! + * brief Performs a non-blocking SAI receive using eDMA. + * + * note This interface returns immediately after the transfer initiates. Call + * the SAI_GetReceiveRemainingBytes to poll the transfer status and check whether the SAI transfer is finished. + * + * param base SAI base pointer + * param handle SAI eDMA handle pointer. + * param xfer Pointer to DMA transfer structure. + * retval kStatus_Success Start a SAI eDMA receive successfully. + * retval kStatus_InvalidArgument The input argument is invalid. + * retval kStatus_RxBusy SAI is busy receiving data. + */ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer) { assert(handle && xfer); @@ -298,6 +418,9 @@ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_ EDMA_PrepareTransfer(&config, (void *)srcAddr, handle->bytesPerFrame, xfer->data, handle->bytesPerFrame, handle->count * handle->bytesPerFrame, xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the SAI handle */ + handle->nbytes = handle->count * handle->bytesPerFrame; + EDMA_SubmitTransfer(handle->dmaHandle, &config); /* Start DMA transfer */ @@ -306,12 +429,24 @@ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_ /* Enable DMA enable bit */ SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, true); + /* Enable the channel FIFO */ + base->RCR3 |= I2S_RCR3_RCE(1U << handle->channel); + /* Enable SAI Rx clock */ SAI_RxEnable(base, true); return kStatus_Success; } +/*! + * brief Aborts a SAI transfer using eDMA. + * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateSendEDMA. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + */ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) { assert(handle); @@ -319,13 +454,36 @@ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable dma */ EDMA_AbortTransfer(handle->dmaHandle); + /* Disable the channel FIFO */ + base->TCR3 &= ~I2S_TCR3_TCE_MASK; + /* Disable DMA enable bit */ SAI_TxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Tx */ + SAI_TxEnable(base, false); + + /* Reset the FIFO pointer, at the same time clear all error flags if set */ + base->TCSR |= (I2S_TCSR_FR_MASK | I2S_TCSR_SR_MASK); + base->TCSR &= ~I2S_TCSR_SR_MASK; + + /* Handle the queue index */ + memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t)); + handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE; + /* Set the handle state */ handle->state = kSAI_Idle; } +/*! + * brief Aborts a SAI receive using eDMA. + * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateReceiveEDMA. + * + * param base SAI base pointer + * param handle SAI eDMA handle pointer. + */ void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) { assert(handle); @@ -333,13 +491,84 @@ void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) /* Disable dma */ EDMA_AbortTransfer(handle->dmaHandle); + /* Disable the channel FIFO */ + base->RCR3 &= ~I2S_RCR3_RCE_MASK; + /* Disable DMA enable bit */ SAI_RxEnableDMA(base, kSAI_FIFORequestDMAEnable, false); + /* Disable Rx */ + SAI_RxEnable(base, false); + + /* Reset the FIFO pointer, at the same time clear all error flags if set */ + base->RCSR |= (I2S_RCSR_FR_MASK | I2S_RCSR_SR_MASK); + base->RCSR &= ~I2S_RCSR_SR_MASK; + + /* Handle the queue index */ + memset(&handle->saiQueue[handle->queueDriver], 0, sizeof(sai_transfer_t)); + handle->queueDriver = (handle->queueDriver + 1) % SAI_XFER_QUEUE_SIZE; + /* Set the handle state */ handle->state = kSAI_Idle; } +/*! + * brief Terminate all SAI send. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortSendEDMA. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateSendEDMA(I2S_Type *base, sai_edma_handle_t *handle) +{ + assert(handle); + + /* Abort the current transfer */ + SAI_TransferAbortSendEDMA(base, handle); + + /* Clear all the internal information */ + memset(handle->tcd, 0U, sizeof(handle->tcd)); + memset(handle->saiQueue, 0U, sizeof(handle->saiQueue)); + memset(handle->transferSize, 0U, sizeof(handle->transferSize)); + handle->queueUser = 0U; + handle->queueDriver = 0U; +} + +/*! + * brief Terminate all SAI receive. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortReceiveEDMA. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle) +{ + assert(handle); + + /* Abort the current transfer */ + SAI_TransferAbortReceiveEDMA(base, handle); + + /* Clear all the internal information */ + memset(handle->tcd, 0U, sizeof(handle->tcd)); + memset(handle->saiQueue, 0U, sizeof(handle->saiQueue)); + memset(handle->transferSize, 0U, sizeof(handle->transferSize)); + handle->queueUser = 0U; + handle->queueDriver = 0U; +} + +/*! + * brief Gets byte count sent by SAI. + * + * param base SAI base pointer. + * param handle SAI eDMA handle pointer. + * param count Bytes count sent by SAI. + * retval kStatus_Success Succeed get the transfer count. + * retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress. + */ status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count) { assert(handle); @@ -353,12 +582,22 @@ status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; } +/*! + * brief Gets byte count received by SAI. + * + * param base SAI base pointer + * param handle SAI eDMA handle pointer. + * param count Bytes count received by SAI. + * retval kStatus_Success Succeed get the transfer count. + * retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress. + */ status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count) { assert(handle); @@ -372,7 +611,8 @@ status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *hand else { *count = (handle->transferSize[handle->queueDriver] - - EDMA_GetRemainingBytes(handle->dmaHandle->base, handle->dmaHandle->channel)); + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->dmaHandle->base, handle->dmaHandle->channel)); } return status; diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.h index 44506fa039..b3d913948b 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_sai_edma.h @@ -1,31 +1,9 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2017 NXP * All rights reserved. * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted 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 Freescale Semiconductor, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * 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. + * SPDX-License-Identifier: BSD-3-Clause */ #ifndef _FSL_SAI_EDMA_H_ #define _FSL_SAI_EDMA_H_ @@ -38,12 +16,15 @@ * @{ */ -/*! @file */ - /******************************************************************************* * Definitions ******************************************************************************/ +/*! @name Driver version */ +/*@{*/ +#define FSL_SAI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 5)) /*!< Version 2.1.5 */ +/*@}*/ + typedef struct _sai_edma_handle sai_edma_handle_t; /*! @brief SAI eDMA transfer callback function for finish and error */ @@ -52,18 +33,19 @@ typedef void (*sai_edma_callback_t)(I2S_Type *base, sai_edma_handle_t *handle, s /*! @brief SAI DMA transfer handle, users should not touch the content of the handle.*/ struct _sai_edma_handle { - edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */ - uint8_t bytesPerFrame; /*!< Bytes in a frame */ - uint8_t channel; /*!< Which data channel */ - uint8_t count; /*!< The transfer data count in a DMA request */ - uint32_t state; /*!< Internal state for SAI eDMA transfer */ - sai_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */ - void *userData; /*!< User callback parameter */ - edma_tcd_t tcd[SAI_XFER_QUEUE_SIZE + 1U]; /*!< TCD pool for eDMA transfer. */ - sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */ - size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */ - volatile uint8_t queueUser; /*!< Index for user to queue transfer. */ - volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */ + edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + uint8_t bytesPerFrame; /*!< Bytes in a frame */ + uint8_t channel; /*!< Which data channel */ + uint8_t count; /*!< The transfer data count in a DMA request */ + uint32_t state; /*!< Internal state for SAI eDMA transfer */ + sai_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */ + void *userData; /*!< User callback parameter */ + uint8_t tcd[(SAI_XFER_QUEUE_SIZE + 1U) * sizeof(edma_tcd_t)]; /*!< TCD pool for eDMA transfer. */ + sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */ + size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */ + volatile uint8_t queueUser; /*!< Index for user to queue transfer. */ + volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */ }; /******************************************************************************* @@ -182,9 +164,34 @@ status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_tra */ status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer); +/*! + * @brief Terminate all SAI send. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortSendEDMA. + * + * @param base SAI base pointer. + * @param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateSendEDMA(I2S_Type *base, sai_edma_handle_t *handle); + +/*! + * @brief Terminate all SAI receive. + * + * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the + * current transfer slot, please call SAI_TransferAbortReceiveEDMA. + * + * @param base SAI base pointer. + * @param handle SAI eDMA handle pointer. + */ +void SAI_TransferTerminateReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle); + /*! * @brief Aborts a SAI transfer using eDMA. * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateSendEDMA. + * * @param base SAI base pointer. * @param handle SAI eDMA handle pointer. */ @@ -193,6 +200,9 @@ void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle); /*! * @brief Aborts a SAI receive using eDMA. * + * This function only aborts the current transfer slots, the other transfer slots' information still kept + * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateReceiveEDMA. + * * @param base SAI base pointer * @param handle SAI eDMA handle pointer. */ diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.c b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.c index 3673404486..c51e493463 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.c +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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. * @@ -125,6 +125,8 @@ extern uint32_t UART_GetInstance(UART_Type *base); static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param; /* Avoid the warning for unused variables. */ @@ -145,6 +147,8 @@ static void UART_SendEDMACallback(edma_handle_t *handle, void *param, bool trans static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool transferDone, uint32_t tcds) { + assert(param); + uart_edma_private_handle_t *uartPrivateHandle = (uart_edma_private_handle_t *)param; /* Avoid warning for unused parameters. */ @@ -165,11 +169,11 @@ static void UART_ReceiveEDMACallback(edma_handle_t *handle, void *param, bool tr } void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle) + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle) { assert(handle); @@ -219,17 +223,15 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer) { + assert(handle); assert(handle->txEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous TX not finished. */ if (kUART_TxBusy == handle->txState) { @@ -244,6 +246,9 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe EDMA_PrepareTransfer(&xferConfig, xfer->data, sizeof(uint8_t), (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_MemoryToPeripheral); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->txEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->txEdmaHandle); @@ -259,17 +264,15 @@ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfe status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer) { + assert(handle); assert(handle->rxEdmaHandle); + assert(xfer); + assert(xfer->data); + assert(xfer->dataSize); edma_transfer_config_t xferConfig; status_t status; - /* Return error if xfer invalid. */ - if ((0U == xfer->dataSize) || (NULL == xfer->data)) - { - return kStatus_InvalidArgument; - } - /* If previous RX not finished. */ if (kUART_RxBusy == handle->rxState) { @@ -284,6 +287,9 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran EDMA_PrepareTransfer(&xferConfig, (void *)UART_GetDataRegisterAddress(base), sizeof(uint8_t), xfer->data, sizeof(uint8_t), sizeof(uint8_t), xfer->dataSize, kEDMA_PeripheralToMemory); + /* Store the initially configured eDMA minor byte transfer count into the UART handle */ + handle->nbytes = sizeof(uint8_t); + /* Submit transfer. */ EDMA_SubmitTransfer(handle->rxEdmaHandle, &xferConfig); EDMA_StartTransfer(handle->rxEdmaHandle); @@ -299,6 +305,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle) { + assert(handle); assert(handle->txEdmaHandle); /* Disable UART TX EDMA. */ @@ -312,6 +319,7 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle) void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle) { + assert(handle); assert(handle->rxEdmaHandle); /* Disable UART RX EDMA. */ @@ -325,38 +333,36 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle) status_t UART_TransferGetReceiveCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->rxEdmaHandle); + assert(count); if (kUART_RxIdle == handle->rxState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->rxDataSizeAll - EDMA_GetRemainingBytes(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); + *count = handle->rxDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->rxEdmaHandle->base, handle->rxEdmaHandle->channel); return kStatus_Success; } status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count) { + assert(handle); assert(handle->txEdmaHandle); + assert(count); if (kUART_TxIdle == handle->txState) { return kStatus_NoTransferInProgress; } - if (!count) - { - return kStatus_InvalidArgument; - } - - *count = handle->txDataSizeAll - EDMA_GetRemainingBytes(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); + *count = handle->txDataSizeAll - + (uint32_t)handle->nbytes * + EDMA_GetRemainingMajorLoopCount(handle->txEdmaHandle->base, handle->txEdmaHandle->channel); return kStatus_Success; } diff --git a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.h b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.h index 52cc7373a9..e411ffd7a4 100644 --- a/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.h +++ b/targets/TARGET_Freescale/TARGET_MCUXpresso_MCUS/TARGET_MCU_K22F/drivers/fsl_uart_edma.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Freescale Semiconductor, Inc. - * All rights reserved. + * Copyright 2016-2017 NXP * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: @@ -12,7 +12,7 @@ * list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * - * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * 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. * @@ -39,8 +39,6 @@ * @{ */ -/*! @file*/ - /******************************************************************************* * Definitions ******************************************************************************/ @@ -67,6 +65,8 @@ struct _uart_edma_handle edma_handle_t *txEdmaHandle; /*!< The eDMA TX channel used. */ edma_handle_t *rxEdmaHandle; /*!< The eDMA RX channel used. */ + uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */ + volatile uint8_t txState; /*!< TX transfer state. */ volatile uint8_t rxState; /*!< RX transfer state */ }; @@ -87,18 +87,18 @@ extern "C" { /*! * @brief Initializes the UART handle which is used in transactional functions. * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param callback UART callback, NULL means no callback. * @param userData User callback function data. - * @param rxEdmaHandle User requested DMA handle for RX DMA transfer. - * @param txEdmaHandle User requested DMA handle for TX DMA transfer. + * @param rxEdmaHandle User-requested DMA handle for RX DMA transfer. + * @param txEdmaHandle User-requested DMA handle for TX DMA transfer. */ void UART_TransferCreateHandleEDMA(UART_Type *base, - uart_edma_handle_t *handle, - uart_edma_transfer_callback_t callback, - void *userData, - edma_handle_t *txEdmaHandle, - edma_handle_t *rxEdmaHandle); + uart_edma_handle_t *handle, + uart_edma_transfer_callback_t callback, + void *userData, + edma_handle_t *txEdmaHandle, + edma_handle_t *rxEdmaHandle); /*! * @brief Sends data using eDMA. @@ -109,23 +109,23 @@ void UART_TransferCreateHandleEDMA(UART_Type *base, * @param base UART peripheral base address. * @param handle UART handle pointer. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_TxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_TxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_SendEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); /*! - * @brief Receive data using eDMA. + * @brief Receives data using eDMA. * * This function receives data using eDMA. This is a non-blocking function, which returns * right away. When all data is received, the receive callback function is called. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. * @param xfer UART eDMA transfer structure. See #uart_transfer_t. - * @retval kStatus_Success if succeed, others failed. - * @retval kStatus_UART_RxBusy Previous transfer on going. + * @retval kStatus_Success if succeeded; otherwise failed. + * @retval kStatus_UART_RxBusy Previous transfer ongoing. * @retval kStatus_InvalidArgument Invalid argument. */ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_transfer_t *xfer); @@ -136,7 +136,7 @@ status_t UART_ReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle, uart_tran * This function aborts sent data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); @@ -146,12 +146,12 @@ void UART_TransferAbortSendEDMA(UART_Type *base, uart_edma_handle_t *handle); * This function aborts receive data using eDMA. * * @param base UART peripheral base address. - * @param handle Pointer to uart_edma_handle_t structure. + * @param handle Pointer to the uart_edma_handle_t structure. */ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); /*! - * @brief Get the number of bytes that have been written to UART TX register. + * @brief Gets the number of bytes that have been written to UART TX register. * * This function gets the number of bytes that have been written to UART TX * register by DMA. @@ -166,9 +166,9 @@ void UART_TransferAbortReceiveEDMA(UART_Type *base, uart_edma_handle_t *handle); status_t UART_TransferGetSendCountEDMA(UART_Type *base, uart_edma_handle_t *handle, uint32_t *count); /*! - * @brief Get the number of bytes that have been received. + * @brief Gets the number of received bytes. * - * This function gets the number of bytes that have been received. + * This function gets the number of received bytes. * * @param base UART peripheral base address. * @param handle UART handle pointer.