Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:00

0001 /*
0002  * Copyright 2019 - 2020, NXP
0003  * All rights reserved.
0004  *
0005  * SPDX-License-Identifier: BSD-3-Clause
0006  */
0007 #ifndef _FSL_PDM_EDMA_H_
0008 #define _FSL_PDM_EDMA_H_
0009 
0010 #include "fsl_edma.h"
0011 #include "fsl_pdm.h"
0012 
0013 /*!
0014  * @addtogroup pdm_edma PDM EDMA Driver
0015  * @ingroup pdm
0016  * @{
0017  */
0018 
0019 /*******************************************************************************
0020  * Definitions
0021  ******************************************************************************/
0022 
0023 /*! @name Driver version */
0024 /*@{*/
0025 #define FSL_PDM_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 6, 1)) /*!< Version 2.6.1 */
0026 /*@}*/
0027 
0028 /*! @brief PDM edma handler */
0029 typedef struct _pdm_edma_handle pdm_edma_handle_t;
0030 
0031 /*!@brief pdm multi channel interleave type */
0032 typedef enum _pdm_edma_multi_channel_interleave
0033 {
0034     kPDM_EDMAMultiChannelInterleavePerChannelSample =
0035         0U, /*!< multi channel PDM data interleave per channel sample
0036              * -------------------------------------------------------------------------
0037              * |CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL 1 | ....|
0038              * -------------------------------------------------------------------------
0039              */
0040     kPDM_EDMAMultiChannelInterleavePerChannelBlock =
0041         1U, /*!< multi channel PDM data interleave per channel block
0042              * ----------------------------------------------------------------------------------------------------------------------------
0043              * |CHANNEL0 | CHANNEL0 | CHANNEL0 | ...... | CHANNEL1 | CHANNEL 1 | CHANNEL 1 | ....| CHANNEL2 | CHANNEL 2
0044              * | CHANNEL 2 | ....|
0045              * ----------------------------------------------------------------------------------------------------------------------------
0046              */
0047 } pdm_edma_multi_channel_interleave_t;
0048 
0049 /*! @brief PDM edma transfer */
0050 typedef struct _pdm_edma_transfer
0051 {
0052     volatile uint8_t *data;                  /*!< Data start address to transfer. */
0053     volatile size_t dataSize;                /*!< Total Transfer bytes size. */
0054     struct _pdm_edma_transfer *linkTransfer; /*!< linked transfer configurations */
0055 } pdm_edma_transfer_t;
0056 
0057 /*! @brief PDM eDMA transfer callback function for finish and error */
0058 typedef void (*pdm_edma_callback_t)(PDM_Type *base, pdm_edma_handle_t *handle, status_t status, void *userData);
0059 
0060 /*! @brief PDM DMA transfer handle, users should not touch the content of the handle.*/
0061 struct _pdm_edma_handle
0062 {
0063     edma_handle_t *dmaHandle;     /*!< DMA handler for PDM send */
0064     uint8_t count;                /*!< The transfer data count in a DMA request */
0065     uint32_t receivedBytes;       /*!< total transfer count */
0066     uint32_t state;               /*!< Internal state for PDM eDMA transfer */
0067     pdm_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */
0068     bool isLoopTransfer;          /*!< loop transfer */
0069     void *userData;               /*!< User callback parameter */
0070     edma_tcd_t *tcd;              /*!< TCD pool for eDMA transfer. */
0071     uint32_t tcdNum;              /*!< TCD number */
0072     uint32_t tcdUser;             /*!< Index for user to queue transfer. */
0073     uint32_t tcdDriver;           /*!< Index for driver to get the transfer data and size */
0074     volatile uint32_t tcdUsedNum; /*!< Index for user to queue transfer. */
0075 
0076     pdm_edma_multi_channel_interleave_t interleaveType; /*!< multi channel transfer interleave type */
0077 
0078     uint8_t endChannel;  /*!< The last enabled channel */
0079     uint8_t channelNums; /*!< total channel numbers */
0080 };
0081 
0082 /*******************************************************************************
0083  * APIs
0084  ******************************************************************************/
0085 #if defined(__cplusplus)
0086 extern "C" {
0087 #endif
0088 
0089 /*!
0090  * @name PDM eDMA Transactional
0091  * @{
0092  */
0093 
0094 /*!
0095  * @brief Install EDMA descriptor memory.
0096  *
0097  * @param handle Pointer to EDMA channel transfer handle.
0098  * @param tcdAddr EDMA head descriptor address.
0099  * @param tcdNum EDMA link descriptor address.
0100  */
0101 void PDM_TransferInstallEDMATCDMemory(pdm_edma_handle_t *handle, void *tcdAddr, size_t tcdNum);
0102 
0103 /*!
0104  * @brief Initializes the PDM Rx eDMA handle.
0105  *
0106  * This function initializes the PDM slave DMA handle, which can be used for other PDM master transactional APIs.
0107  * Usually, for a specified PDM instance, call this API once to get the initialized handle.
0108  *
0109  * @param base PDM base pointer.
0110  * @param handle PDM eDMA handle pointer.
0111  * @param callback Pointer to user callback function.
0112  * @param userData User parameter passed to the callback function.
0113  * @param dmaHandle eDMA handle pointer, this handle shall be static allocated by users.
0114  */
0115 void PDM_TransferCreateHandleEDMA(
0116     PDM_Type *base, pdm_edma_handle_t *handle, pdm_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle);
0117 
0118 /*!
0119  * @brief Initializes the multi PDM channel interleave type.
0120  *
0121  * This function initializes the PDM DMA handle member interleaveType, it shall be called only when application would
0122  * like to use type kPDM_EDMAMultiChannelInterleavePerChannelBlock, since the default interleaveType is
0123  * kPDM_EDMAMultiChannelInterleavePerChannelSample always
0124  *
0125  * @param handle PDM eDMA handle pointer.
0126  * @param multiChannelInterleaveType Multi channel interleave type.
0127  */
0128 void PDM_TransferSetMultiChannelInterleaveType(pdm_edma_handle_t *handle,
0129                                                pdm_edma_multi_channel_interleave_t multiChannelInterleaveType);
0130 
0131 /*!
0132  * @brief Configures the PDM channel.
0133  *
0134  * @param base PDM base pointer.
0135  * @param handle PDM eDMA handle pointer.
0136  * @param channel channel index.
0137  * @param config pdm channel configurations.
0138  */
0139 void PDM_TransferSetChannelConfigEDMA(PDM_Type *base,
0140                                       pdm_edma_handle_t *handle,
0141                                       uint32_t channel,
0142                                       const pdm_channel_config_t *config);
0143 
0144 /*!
0145  * @brief Performs a non-blocking PDM receive using eDMA.
0146  *
0147  * @note This interface returns immediately after the transfer initiates. Call
0148  * the PDM_GetReceiveRemainingBytes to poll the transfer status and check whether the PDM transfer is finished.
0149  *
0150  * 1. Scatter gather case:
0151  * This functio support dynamic scatter gather and staic scatter gather,
0152  * a. for the dynamic scatter gather case:
0153  * Application should call PDM_TransferReceiveEDMA function continuously to make sure new receive request is submit
0154  * before the previous one finish. b. for the static scatter gather case: Application should use the link transfer
0155  * feature and make sure a loop link transfer is provided, such as:
0156  * @code pdm_edma_transfer_t pdmXfer[2] =
0157  *   {
0158  *       {
0159  *       .data  = s_buffer,
0160  *       .dataSize = BUFFER_SIZE,
0161  *       .linkTransfer = &pdmXfer[1],
0162  *       },
0163  *
0164  *       {
0165  *       .data  = &s_buffer[BUFFER_SIZE],
0166  *       .dataSize = BUFFER_SIZE,
0167  *       .linkTransfer = &pdmXfer[0]
0168  *       },
0169  *   };
0170  * @endcode
0171  *
0172  * 2. Multi channel case:
0173  * This function support receive multi pdm channel data, for example, if two channel is requested,
0174  * @code
0175  * PDM_TransferSetChannelConfigEDMA(DEMO_PDM, &s_pdmRxHandle_0, DEMO_PDM_ENABLE_CHANNEL_0, &channelConfig);
0176  * PDM_TransferSetChannelConfigEDMA(DEMO_PDM, &s_pdmRxHandle_0, DEMO_PDM_ENABLE_CHANNEL_1, &channelConfig);
0177  * PDM_TransferReceiveEDMA(DEMO_PDM, &s_pdmRxHandle_0, pdmXfer);
0178  * @endcode
0179  * The output data will be formatted as below if handle->interleaveType =
0180  * kPDM_EDMAMultiChannelInterleavePerChannelSample :
0181  * -------------------------------------------------------------------------
0182  * |CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL 1 | ....|
0183  * -------------------------------------------------------------------------
0184  *
0185  * The output data will be formatted as below if handle->interleaveType = kPDM_EDMAMultiChannelInterleavePerChannelBlock
0186  * :
0187  * ----------------------------------------------------------------------------------------------------------------------
0188  * |CHANNEL3 | CHANNEL3 | CHANNEL3 | .... | CHANNEL4 | CHANNEL 4 | CHANNEL4 |....| CHANNEL5 | CHANNEL 5 | CHANNEL5
0189  * |....|
0190  * ----------------------------------------------------------------------------------------------------------------------
0191  * Note: the dataSize of xfer is the total data size, while application using
0192  * kPDM_EDMAMultiChannelInterleavePerChannelBlock, the buffer size for each PDM channel is channelSize = dataSize /
0193  * channelNums, then there are limitation for this feature,
0194  * 1. 3 DMIC array: the dataSize shall be 4 * (channelSize)
0195  * The addtional buffer is mandantory for edma modulo feature.
0196  * 2. The kPDM_EDMAMultiChannelInterleavePerChannelBlock feature support below dmic array only,
0197  *    2 DMIC array: CHANNEL3, CHANNEL4
0198  *    3 DMIC array: CHANNEL3, CHANNEL4, CHANNEL5
0199  *    4 DMIC array: CHANNEL3, CHANNEL4, CHANNEL5, CHANNEL6
0200  * Any other combinations is not support, that is to SAY, THE FEATURE SUPPORT RECEIVE START FROM CHANNEL3 ONLY AND 4
0201  * MAXIMUM DMIC CHANNELS.
0202  *
0203  * @param base PDM base pointer
0204  * @param handle PDM eDMA handle pointer.
0205  * @param xfer Pointer to DMA transfer structure.
0206  * @retval kStatus_Success Start a PDM eDMA receive successfully.
0207  * @retval kStatus_InvalidArgument The input argument is invalid.
0208  * @retval kStatus_RxBusy PDM is busy receiving data.
0209  */
0210 status_t PDM_TransferReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle, pdm_edma_transfer_t *xfer);
0211 
0212 /*!
0213  * @brief Terminate all PDM receive.
0214  *
0215  * This function will clear all transfer slots buffered in the pdm queue. If users only want to abort the
0216  * current transfer slot, please call PDM_TransferAbortReceiveEDMA.
0217  *
0218  * @param base PDM base pointer.
0219  * @param handle PDM eDMA handle pointer.
0220  */
0221 void PDM_TransferTerminateReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle);
0222 
0223 /*!
0224  * @brief Aborts a PDM receive using eDMA.
0225  *
0226  * This function only aborts the current transfer slots, the other transfer slots' information still kept
0227  * in the handler. If users want to terminate all transfer slots, just call PDM_TransferTerminateReceiveEDMA.
0228  *
0229  * @param base PDM base pointer
0230  * @param handle PDM eDMA handle pointer.
0231  */
0232 void PDM_TransferAbortReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle);
0233 
0234 /*!
0235  * @brief Gets byte count received by PDM.
0236  *
0237  * @param base PDM base pointer
0238  * @param handle PDM eDMA handle pointer.
0239  * @param count Bytes count received by PDM.
0240  * @retval kStatus_Success Succeed get the transfer count.
0241  * @retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress.
0242  */
0243 status_t PDM_TransferGetReceiveCountEDMA(PDM_Type *base, pdm_edma_handle_t *handle, size_t *count);
0244 
0245 /*! @} */
0246 
0247 #if defined(__cplusplus)
0248 }
0249 #endif
0250 
0251 /*!
0252  * @}
0253  */
0254 #endif