diff options
Diffstat (limited to '')
-rw-r--r-- | bsps/arm/imxrt/mcux-sdk/drivers/pdm/fsl_pdm_edma.h | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/bsps/arm/imxrt/mcux-sdk/drivers/pdm/fsl_pdm_edma.h b/bsps/arm/imxrt/mcux-sdk/drivers/pdm/fsl_pdm_edma.h new file mode 100644 index 0000000000..4da78192f9 --- /dev/null +++ b/bsps/arm/imxrt/mcux-sdk/drivers/pdm/fsl_pdm_edma.h @@ -0,0 +1,254 @@ +/* + * Copyright 2019 - 2020, NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef _FSL_PDM_EDMA_H_ +#define _FSL_PDM_EDMA_H_ + +#include "fsl_edma.h" +#include "fsl_pdm.h" + +/*! + * @addtogroup pdm_edma PDM EDMA Driver + * @ingroup pdm + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/*! @name Driver version */ +/*@{*/ +#define FSL_PDM_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 6, 1)) /*!< Version 2.6.1 */ +/*@}*/ + +/*! @brief PDM edma handler */ +typedef struct _pdm_edma_handle pdm_edma_handle_t; + +/*!@brief pdm multi channel interleave type */ +typedef enum _pdm_edma_multi_channel_interleave +{ + kPDM_EDMAMultiChannelInterleavePerChannelSample = + 0U, /*!< multi channel PDM data interleave per channel sample + * ------------------------------------------------------------------------- + * |CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL 1 | ....| + * ------------------------------------------------------------------------- + */ + kPDM_EDMAMultiChannelInterleavePerChannelBlock = + 1U, /*!< multi channel PDM data interleave per channel block + * ---------------------------------------------------------------------------------------------------------------------------- + * |CHANNEL0 | CHANNEL0 | CHANNEL0 | ...... | CHANNEL1 | CHANNEL 1 | CHANNEL 1 | ....| CHANNEL2 | CHANNEL 2 + * | CHANNEL 2 | ....| + * ---------------------------------------------------------------------------------------------------------------------------- + */ +} pdm_edma_multi_channel_interleave_t; + +/*! @brief PDM edma transfer */ +typedef struct _pdm_edma_transfer +{ + volatile uint8_t *data; /*!< Data start address to transfer. */ + volatile size_t dataSize; /*!< Total Transfer bytes size. */ + struct _pdm_edma_transfer *linkTransfer; /*!< linked transfer configurations */ +} pdm_edma_transfer_t; + +/*! @brief PDM eDMA transfer callback function for finish and error */ +typedef void (*pdm_edma_callback_t)(PDM_Type *base, pdm_edma_handle_t *handle, status_t status, void *userData); + +/*! @brief PDM DMA transfer handle, users should not touch the content of the handle.*/ +struct _pdm_edma_handle +{ + edma_handle_t *dmaHandle; /*!< DMA handler for PDM send */ + uint8_t count; /*!< The transfer data count in a DMA request */ + uint32_t receivedBytes; /*!< total transfer count */ + uint32_t state; /*!< Internal state for PDM eDMA transfer */ + pdm_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */ + bool isLoopTransfer; /*!< loop transfer */ + void *userData; /*!< User callback parameter */ + edma_tcd_t *tcd; /*!< TCD pool for eDMA transfer. */ + uint32_t tcdNum; /*!< TCD number */ + uint32_t tcdUser; /*!< Index for user to queue transfer. */ + uint32_t tcdDriver; /*!< Index for driver to get the transfer data and size */ + volatile uint32_t tcdUsedNum; /*!< Index for user to queue transfer. */ + + pdm_edma_multi_channel_interleave_t interleaveType; /*!< multi channel transfer interleave type */ + + uint8_t endChannel; /*!< The last enabled channel */ + uint8_t channelNums; /*!< total channel numbers */ +}; + +/******************************************************************************* + * APIs + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name PDM eDMA Transactional + * @{ + */ + +/*! + * @brief Install EDMA descriptor memory. + * + * @param handle Pointer to EDMA channel transfer handle. + * @param tcdAddr EDMA head descriptor address. + * @param tcdNum EDMA link descriptor address. + */ +void PDM_TransferInstallEDMATCDMemory(pdm_edma_handle_t *handle, void *tcdAddr, size_t tcdNum); + +/*! + * @brief Initializes the PDM Rx eDMA handle. + * + * This function initializes the PDM slave DMA handle, which can be used for other PDM master transactional APIs. + * Usually, for a specified PDM instance, call this API once to get the initialized handle. + * + * @param base PDM base pointer. + * @param handle PDM eDMA handle pointer. + * @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 PDM_TransferCreateHandleEDMA( + PDM_Type *base, pdm_edma_handle_t *handle, pdm_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle); + +/*! + * @brief Initializes the multi PDM channel interleave type. + * + * This function initializes the PDM DMA handle member interleaveType, it shall be called only when application would + * like to use type kPDM_EDMAMultiChannelInterleavePerChannelBlock, since the default interleaveType is + * kPDM_EDMAMultiChannelInterleavePerChannelSample always + * + * @param handle PDM eDMA handle pointer. + * @param multiChannelInterleaveType Multi channel interleave type. + */ +void PDM_TransferSetMultiChannelInterleaveType(pdm_edma_handle_t *handle, + pdm_edma_multi_channel_interleave_t multiChannelInterleaveType); + +/*! + * @brief Configures the PDM channel. + * + * @param base PDM base pointer. + * @param handle PDM eDMA handle pointer. + * @param channel channel index. + * @param config pdm channel configurations. + */ +void PDM_TransferSetChannelConfigEDMA(PDM_Type *base, + pdm_edma_handle_t *handle, + uint32_t channel, + const pdm_channel_config_t *config); + +/*! + * @brief Performs a non-blocking PDM receive using eDMA. + * + * @note This interface returns immediately after the transfer initiates. Call + * the PDM_GetReceiveRemainingBytes to poll the transfer status and check whether the PDM transfer is finished. + * + * 1. Scatter gather case: + * This functio support dynamic scatter gather and staic scatter gather, + * a. for the dynamic scatter gather case: + * Application should call PDM_TransferReceiveEDMA function continuously to make sure new receive request is submit + * before the previous one finish. b. for the static scatter gather case: Application should use the link transfer + * feature and make sure a loop link transfer is provided, such as: + * @code pdm_edma_transfer_t pdmXfer[2] = + * { + * { + * .data = s_buffer, + * .dataSize = BUFFER_SIZE, + * .linkTransfer = &pdmXfer[1], + * }, + * + * { + * .data = &s_buffer[BUFFER_SIZE], + * .dataSize = BUFFER_SIZE, + * .linkTransfer = &pdmXfer[0] + * }, + * }; + * @endcode + * + * 2. Multi channel case: + * This function support receive multi pdm channel data, for example, if two channel is requested, + * @code + * PDM_TransferSetChannelConfigEDMA(DEMO_PDM, &s_pdmRxHandle_0, DEMO_PDM_ENABLE_CHANNEL_0, &channelConfig); + * PDM_TransferSetChannelConfigEDMA(DEMO_PDM, &s_pdmRxHandle_0, DEMO_PDM_ENABLE_CHANNEL_1, &channelConfig); + * PDM_TransferReceiveEDMA(DEMO_PDM, &s_pdmRxHandle_0, pdmXfer); + * @endcode + * The output data will be formatted as below if handle->interleaveType = + * kPDM_EDMAMultiChannelInterleavePerChannelSample : + * ------------------------------------------------------------------------- + * |CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL 1 | ....| + * ------------------------------------------------------------------------- + * + * The output data will be formatted as below if handle->interleaveType = kPDM_EDMAMultiChannelInterleavePerChannelBlock + * : + * ---------------------------------------------------------------------------------------------------------------------- + * |CHANNEL3 | CHANNEL3 | CHANNEL3 | .... | CHANNEL4 | CHANNEL 4 | CHANNEL4 |....| CHANNEL5 | CHANNEL 5 | CHANNEL5 + * |....| + * ---------------------------------------------------------------------------------------------------------------------- + * Note: the dataSize of xfer is the total data size, while application using + * kPDM_EDMAMultiChannelInterleavePerChannelBlock, the buffer size for each PDM channel is channelSize = dataSize / + * channelNums, then there are limitation for this feature, + * 1. 3 DMIC array: the dataSize shall be 4 * (channelSize) + * The addtional buffer is mandantory for edma modulo feature. + * 2. The kPDM_EDMAMultiChannelInterleavePerChannelBlock feature support below dmic array only, + * 2 DMIC array: CHANNEL3, CHANNEL4 + * 3 DMIC array: CHANNEL3, CHANNEL4, CHANNEL5 + * 4 DMIC array: CHANNEL3, CHANNEL4, CHANNEL5, CHANNEL6 + * Any other combinations is not support, that is to SAY, THE FEATURE SUPPORT RECEIVE START FROM CHANNEL3 ONLY AND 4 + * MAXIMUM DMIC CHANNELS. + * + * @param base PDM base pointer + * @param handle PDM eDMA handle pointer. + * @param xfer Pointer to DMA transfer structure. + * @retval kStatus_Success Start a PDM eDMA receive successfully. + * @retval kStatus_InvalidArgument The input argument is invalid. + * @retval kStatus_RxBusy PDM is busy receiving data. + */ +status_t PDM_TransferReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle, pdm_edma_transfer_t *xfer); + +/*! + * @brief Terminate all PDM receive. + * + * This function will clear all transfer slots buffered in the pdm queue. If users only want to abort the + * current transfer slot, please call PDM_TransferAbortReceiveEDMA. + * + * @param base PDM base pointer. + * @param handle PDM eDMA handle pointer. + */ +void PDM_TransferTerminateReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle); + +/*! + * @brief Aborts a PDM 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 PDM_TransferTerminateReceiveEDMA. + * + * @param base PDM base pointer + * @param handle PDM eDMA handle pointer. + */ +void PDM_TransferAbortReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle); + +/*! + * @brief Gets byte count received by PDM. + * + * @param base PDM base pointer + * @param handle PDM eDMA handle pointer. + * @param count Bytes count received by PDM. + * @retval kStatus_Success Succeed get the transfer count. + * @retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress. + */ +status_t PDM_TransferGetReceiveCountEDMA(PDM_Type *base, pdm_edma_handle_t *handle, size_t *count); + +/*! @} */ + +#if defined(__cplusplus) +} +#endif + +/*! + * @} + */ +#endif |