1 /* 2 * Copyright 2019 - 2020, NXP 3 * All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 #ifndef _FSL_PDM_EDMA_H_ 8 #define _FSL_PDM_EDMA_H_ 9 10 #include "fsl_edma.h" 11 #include "fsl_pdm.h" 12 13 /*! 14 * @addtogroup pdm_edma PDM EDMA Driver 15 * @ingroup pdm 16 * @{ 17 */ 18 19 /******************************************************************************* 20 * Definitions 21 ******************************************************************************/ 22 23 /*! @name Driver version */ 24 /*@{*/ 25 #define FSL_PDM_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 6, 1)) /*!< Version 2.6.1 */ 26 /*@}*/ 27 28 /*! @brief PDM edma handler */ 29 typedef struct _pdm_edma_handle pdm_edma_handle_t; 30 31 /*!@brief pdm multi channel interleave type */ 32 typedef enum _pdm_edma_multi_channel_interleave 33 { 34 kPDM_EDMAMultiChannelInterleavePerChannelSample = 35 0U, /*!< multi channel PDM data interleave per channel sample 36 * ------------------------------------------------------------------------- 37 * |CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL 1 | ....| 38 * ------------------------------------------------------------------------- 39 */ 40 kPDM_EDMAMultiChannelInterleavePerChannelBlock = 41 1U, /*!< multi channel PDM data interleave per channel block 42 * ---------------------------------------------------------------------------------------------------------------------------- 43 * |CHANNEL0 | CHANNEL0 | CHANNEL0 | ...... | CHANNEL1 | CHANNEL 1 | CHANNEL 1 | ....| CHANNEL2 | CHANNEL 2 44 * | CHANNEL 2 | ....| 45 * ---------------------------------------------------------------------------------------------------------------------------- 46 */ 47 } pdm_edma_multi_channel_interleave_t; 48 49 /*! @brief PDM edma transfer */ 50 typedef struct _pdm_edma_transfer 51 { 52 volatile uint8_t *data; /*!< Data start address to transfer. */ 53 volatile size_t dataSize; /*!< Total Transfer bytes size. */ 54 struct _pdm_edma_transfer *linkTransfer; /*!< linked transfer configurations */ 55 } pdm_edma_transfer_t; 56 57 /*! @brief PDM eDMA transfer callback function for finish and error */ 58 typedef void (*pdm_edma_callback_t)(PDM_Type *base, pdm_edma_handle_t *handle, status_t status, void *userData); 59 60 /*! @brief PDM DMA transfer handle, users should not touch the content of the handle.*/ 61 struct _pdm_edma_handle 62 { 63 edma_handle_t *dmaHandle; /*!< DMA handler for PDM send */ 64 uint8_t count; /*!< The transfer data count in a DMA request */ 65 uint32_t receivedBytes; /*!< total transfer count */ 66 uint32_t state; /*!< Internal state for PDM eDMA transfer */ 67 pdm_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */ 68 bool isLoopTransfer; /*!< loop transfer */ 69 void *userData; /*!< User callback parameter */ 70 edma_tcd_t *tcd; /*!< TCD pool for eDMA transfer. */ 71 uint32_t tcdNum; /*!< TCD number */ 72 uint32_t tcdUser; /*!< Index for user to queue transfer. */ 73 uint32_t tcdDriver; /*!< Index for driver to get the transfer data and size */ 74 volatile uint32_t tcdUsedNum; /*!< Index for user to queue transfer. */ 75 76 pdm_edma_multi_channel_interleave_t interleaveType; /*!< multi channel transfer interleave type */ 77 78 uint8_t endChannel; /*!< The last enabled channel */ 79 uint8_t channelNums; /*!< total channel numbers */ 80 }; 81 82 /******************************************************************************* 83 * APIs 84 ******************************************************************************/ 85 #if defined(__cplusplus) 86 extern "C" { 87 #endif 88 89 /*! 90 * @name PDM eDMA Transactional 91 * @{ 92 */ 93 94 /*! 95 * @brief Install EDMA descriptor memory. 96 * 97 * @param handle Pointer to EDMA channel transfer handle. 98 * @param tcdAddr EDMA head descriptor address. 99 * @param tcdNum EDMA link descriptor address. 100 */ 101 void PDM_TransferInstallEDMATCDMemory(pdm_edma_handle_t *handle, void *tcdAddr, size_t tcdNum); 102 103 /*! 104 * @brief Initializes the PDM Rx eDMA handle. 105 * 106 * This function initializes the PDM slave DMA handle, which can be used for other PDM master transactional APIs. 107 * Usually, for a specified PDM instance, call this API once to get the initialized handle. 108 * 109 * @param base PDM base pointer. 110 * @param handle PDM eDMA handle pointer. 111 * @param callback Pointer to user callback function. 112 * @param userData User parameter passed to the callback function. 113 * @param dmaHandle eDMA handle pointer, this handle shall be static allocated by users. 114 */ 115 void PDM_TransferCreateHandleEDMA( 116 PDM_Type *base, pdm_edma_handle_t *handle, pdm_edma_callback_t callback, void *userData, edma_handle_t *dmaHandle); 117 118 /*! 119 * @brief Initializes the multi PDM channel interleave type. 120 * 121 * This function initializes the PDM DMA handle member interleaveType, it shall be called only when application would 122 * like to use type kPDM_EDMAMultiChannelInterleavePerChannelBlock, since the default interleaveType is 123 * kPDM_EDMAMultiChannelInterleavePerChannelSample always 124 * 125 * @param handle PDM eDMA handle pointer. 126 * @param multiChannelInterleaveType Multi channel interleave type. 127 */ 128 void PDM_TransferSetMultiChannelInterleaveType(pdm_edma_handle_t *handle, 129 pdm_edma_multi_channel_interleave_t multiChannelInterleaveType); 130 131 /*! 132 * @brief Configures the PDM channel. 133 * 134 * @param base PDM base pointer. 135 * @param handle PDM eDMA handle pointer. 136 * @param channel channel index. 137 * @param config pdm channel configurations. 138 */ 139 void PDM_TransferSetChannelConfigEDMA(PDM_Type *base, 140 pdm_edma_handle_t *handle, 141 uint32_t channel, 142 const pdm_channel_config_t *config); 143 144 /*! 145 * @brief Performs a non-blocking PDM receive using eDMA. 146 * 147 * @note This interface returns immediately after the transfer initiates. Call 148 * the PDM_GetReceiveRemainingBytes to poll the transfer status and check whether the PDM transfer is finished. 149 * 150 * 1. Scatter gather case: 151 * This functio support dynamic scatter gather and staic scatter gather, 152 * a. for the dynamic scatter gather case: 153 * Application should call PDM_TransferReceiveEDMA function continuously to make sure new receive request is submit 154 * before the previous one finish. b. for the static scatter gather case: Application should use the link transfer 155 * feature and make sure a loop link transfer is provided, such as: 156 * @code pdm_edma_transfer_t pdmXfer[2] = 157 * { 158 * { 159 * .data = s_buffer, 160 * .dataSize = BUFFER_SIZE, 161 * .linkTransfer = &pdmXfer[1], 162 * }, 163 * 164 * { 165 * .data = &s_buffer[BUFFER_SIZE], 166 * .dataSize = BUFFER_SIZE, 167 * .linkTransfer = &pdmXfer[0] 168 * }, 169 * }; 170 * @endcode 171 * 172 * 2. Multi channel case: 173 * This function support receive multi pdm channel data, for example, if two channel is requested, 174 * @code 175 * PDM_TransferSetChannelConfigEDMA(DEMO_PDM, &s_pdmRxHandle_0, DEMO_PDM_ENABLE_CHANNEL_0, &channelConfig); 176 * PDM_TransferSetChannelConfigEDMA(DEMO_PDM, &s_pdmRxHandle_0, DEMO_PDM_ENABLE_CHANNEL_1, &channelConfig); 177 * PDM_TransferReceiveEDMA(DEMO_PDM, &s_pdmRxHandle_0, pdmXfer); 178 * @endcode 179 * The output data will be formatted as below if handle->interleaveType = 180 * kPDM_EDMAMultiChannelInterleavePerChannelSample : 181 * ------------------------------------------------------------------------- 182 * |CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL1 | CHANNEL0 | CHANNEL 1 | ....| 183 * ------------------------------------------------------------------------- 184 * 185 * The output data will be formatted as below if handle->interleaveType = kPDM_EDMAMultiChannelInterleavePerChannelBlock 186 * : 187 * ---------------------------------------------------------------------------------------------------------------------- 188 * |CHANNEL3 | CHANNEL3 | CHANNEL3 | .... | CHANNEL4 | CHANNEL 4 | CHANNEL4 |....| CHANNEL5 | CHANNEL 5 | CHANNEL5 189 * |....| 190 * ---------------------------------------------------------------------------------------------------------------------- 191 * Note: the dataSize of xfer is the total data size, while application using 192 * kPDM_EDMAMultiChannelInterleavePerChannelBlock, the buffer size for each PDM channel is channelSize = dataSize / 193 * channelNums, then there are limitation for this feature, 194 * 1. 3 DMIC array: the dataSize shall be 4 * (channelSize) 195 * The addtional buffer is mandantory for edma modulo feature. 196 * 2. The kPDM_EDMAMultiChannelInterleavePerChannelBlock feature support below dmic array only, 197 * 2 DMIC array: CHANNEL3, CHANNEL4 198 * 3 DMIC array: CHANNEL3, CHANNEL4, CHANNEL5 199 * 4 DMIC array: CHANNEL3, CHANNEL4, CHANNEL5, CHANNEL6 200 * Any other combinations is not support, that is to SAY, THE FEATURE SUPPORT RECEIVE START FROM CHANNEL3 ONLY AND 4 201 * MAXIMUM DMIC CHANNELS. 202 * 203 * @param base PDM base pointer 204 * @param handle PDM eDMA handle pointer. 205 * @param xfer Pointer to DMA transfer structure. 206 * @retval kStatus_Success Start a PDM eDMA receive successfully. 207 * @retval kStatus_InvalidArgument The input argument is invalid. 208 * @retval kStatus_RxBusy PDM is busy receiving data. 209 */ 210 status_t PDM_TransferReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle, pdm_edma_transfer_t *xfer); 211 212 /*! 213 * @brief Terminate all PDM receive. 214 * 215 * This function will clear all transfer slots buffered in the pdm queue. If users only want to abort the 216 * current transfer slot, please call PDM_TransferAbortReceiveEDMA. 217 * 218 * @param base PDM base pointer. 219 * @param handle PDM eDMA handle pointer. 220 */ 221 void PDM_TransferTerminateReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle); 222 223 /*! 224 * @brief Aborts a PDM receive using eDMA. 225 * 226 * This function only aborts the current transfer slots, the other transfer slots' information still kept 227 * in the handler. If users want to terminate all transfer slots, just call PDM_TransferTerminateReceiveEDMA. 228 * 229 * @param base PDM base pointer 230 * @param handle PDM eDMA handle pointer. 231 */ 232 void PDM_TransferAbortReceiveEDMA(PDM_Type *base, pdm_edma_handle_t *handle); 233 234 /*! 235 * @brief Gets byte count received by PDM. 236 * 237 * @param base PDM base pointer 238 * @param handle PDM eDMA handle pointer. 239 * @param count Bytes count received by PDM. 240 * @retval kStatus_Success Succeed get the transfer count. 241 * @retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress. 242 */ 243 status_t PDM_TransferGetReceiveCountEDMA(PDM_Type *base, pdm_edma_handle_t *handle, size_t *count); 244 245 /*! @} */ 246 247 #if defined(__cplusplus) 248 } 249 #endif 250 251 /*! 252 * @} 253 */ 254 #endif 255