fsl_sai_edma.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  3. * Copyright 2016-2017 NXP
  4. * All rights reserved.
  5. *
  6. * SPDX-License-Identifier: BSD-3-Clause
  7. */
  8. #ifndef _FSL_SAI_EDMA_H_
  9. #define _FSL_SAI_EDMA_H_
  10. #include "fsl_edma.h"
  11. #include "fsl_sai.h"
  12. /*!
  13. * @addtogroup sai_edma SAI EDMA Driver
  14. * @ingroup sai
  15. * @{
  16. */
  17. /*******************************************************************************
  18. * Definitions
  19. ******************************************************************************/
  20. /*! @name Driver version */
  21. /*@{*/
  22. #define FSL_SAI_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 5, 0)) /*!< Version 2.5.0 */
  23. /*@}*/
  24. typedef struct sai_edma_handle sai_edma_handle_t;
  25. /*! @brief SAI eDMA transfer callback function for finish and error */
  26. typedef void (*sai_edma_callback_t)(I2S_Type *base, sai_edma_handle_t *handle, status_t status, void *userData);
  27. /*! @brief SAI DMA transfer handle, users should not touch the content of the handle.*/
  28. struct sai_edma_handle
  29. {
  30. edma_handle_t *dmaHandle; /*!< DMA handler for SAI send */
  31. uint8_t nbytes; /*!< eDMA minor byte transfer count initially configured. */
  32. uint8_t bytesPerFrame; /*!< Bytes in a frame */
  33. uint8_t channelMask; /*!< Enabled channel mask value, reference _sai_channel_mask */
  34. uint8_t channelNums; /*!< total enabled channel nums */
  35. uint8_t channel; /*!< Which data channel */
  36. uint8_t count; /*!< The transfer data count in a DMA request */
  37. uint32_t state; /*!< Internal state for SAI eDMA transfer */
  38. sai_edma_callback_t callback; /*!< Callback for users while transfer finish or error occurs */
  39. void *userData; /*!< User callback parameter */
  40. uint8_t tcd[(SAI_XFER_QUEUE_SIZE + 1U) * sizeof(edma_tcd_t)]; /*!< TCD pool for eDMA transfer. */
  41. sai_transfer_t saiQueue[SAI_XFER_QUEUE_SIZE]; /*!< Transfer queue storing queued transfer. */
  42. size_t transferSize[SAI_XFER_QUEUE_SIZE]; /*!< Data bytes need to transfer */
  43. volatile uint8_t queueUser; /*!< Index for user to queue transfer. */
  44. volatile uint8_t queueDriver; /*!< Index for driver to get the transfer data and size */
  45. };
  46. /*******************************************************************************
  47. * APIs
  48. ******************************************************************************/
  49. #if defined(__cplusplus)
  50. extern "C" {
  51. #endif
  52. /*!
  53. * @name eDMA Transactional
  54. * @{
  55. */
  56. /*!
  57. * @brief Initializes the SAI eDMA handle.
  58. *
  59. * This function initializes the SAI master DMA handle, which can be used for other SAI master transactional APIs.
  60. * Usually, for a specified SAI instance, call this API once to get the initialized handle.
  61. *
  62. * @param base SAI base pointer.
  63. * @param handle SAI eDMA handle pointer.
  64. * @param base SAI peripheral base address.
  65. * @param callback Pointer to user callback function.
  66. * @param userData User parameter passed to the callback function.
  67. * @param txDmaHandle eDMA handle pointer, this handle shall be static allocated by users.
  68. */
  69. void SAI_TransferTxCreateHandleEDMA(I2S_Type *base,
  70. sai_edma_handle_t *handle,
  71. sai_edma_callback_t callback,
  72. void *userData,
  73. edma_handle_t *txDmaHandle);
  74. /*!
  75. * @brief Initializes the SAI Rx eDMA handle.
  76. *
  77. * This function initializes the SAI slave DMA handle, which can be used for other SAI master transactional APIs.
  78. * Usually, for a specified SAI instance, call this API once to get the initialized handle.
  79. *
  80. * @param base SAI base pointer.
  81. * @param handle SAI eDMA handle pointer.
  82. * @param base SAI peripheral base address.
  83. * @param callback Pointer to user callback function.
  84. * @param userData User parameter passed to the callback function.
  85. * @param rxDmaHandle eDMA handle pointer, this handle shall be static allocated by users.
  86. */
  87. void SAI_TransferRxCreateHandleEDMA(I2S_Type *base,
  88. sai_edma_handle_t *handle,
  89. sai_edma_callback_t callback,
  90. void *userData,
  91. edma_handle_t *rxDmaHandle);
  92. /*!
  93. * @brief Configures the SAI Tx audio format.
  94. *
  95. * @deprecated Do not use this function. It has been superceded by @ref SAI_TransferTxSetConfigEDMA
  96. *
  97. * The audio format can be changed at run-time. This function configures the sample rate and audio data
  98. * format to be transferred. This function also sets the eDMA parameter according to formatting requirements.
  99. *
  100. * @param base SAI base pointer.
  101. * @param handle SAI eDMA handle pointer.
  102. * @param format Pointer to SAI audio data format structure.
  103. * @param mclkSourceClockHz SAI master clock source frequency in Hz.
  104. * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If bit clock source is master
  105. * clock, this value should equals to masterClockHz in format.
  106. * @retval kStatus_Success Audio format set successfully.
  107. * @retval kStatus_InvalidArgument The input argument is invalid.
  108. */
  109. void SAI_TransferTxSetFormatEDMA(I2S_Type *base,
  110. sai_edma_handle_t *handle,
  111. sai_transfer_format_t *format,
  112. uint32_t mclkSourceClockHz,
  113. uint32_t bclkSourceClockHz);
  114. /*!
  115. * @brief Configures the SAI Rx audio format.
  116. *
  117. * @deprecated Do not use this function. It has been superceded by @ref SAI_TransferRxSetConfigEDMA
  118. *
  119. * The audio format can be changed at run-time. This function configures the sample rate and audio data
  120. * format to be transferred. This function also sets the eDMA parameter according to formatting requirements.
  121. *
  122. * @param base SAI base pointer.
  123. * @param handle SAI eDMA handle pointer.
  124. * @param format Pointer to SAI audio data format structure.
  125. * @param mclkSourceClockHz SAI master clock source frequency in Hz.
  126. * @param bclkSourceClockHz SAI bit clock source frequency in Hz. If a bit clock source is the master
  127. * clock, this value should equal to masterClockHz in format.
  128. * @retval kStatus_Success Audio format set successfully.
  129. * @retval kStatus_InvalidArgument The input argument is invalid.
  130. */
  131. void SAI_TransferRxSetFormatEDMA(I2S_Type *base,
  132. sai_edma_handle_t *handle,
  133. sai_transfer_format_t *format,
  134. uint32_t mclkSourceClockHz,
  135. uint32_t bclkSourceClockHz);
  136. /*!
  137. * @brief Configures the SAI Tx.
  138. *
  139. * @note SAI eDMA supports data transfer in a multiple SAI channels if the FIFO Combine feature is supported.
  140. * To activate the multi-channel transfer enable SAI channels by filling the channelMask
  141. * of sai_transceiver_t with the corresponding values of _sai_channel_mask enum, enable the FIFO Combine
  142. * mode by assigning kSAI_FifoCombineModeEnabledOnWrite to the fifoCombine member of sai_fifo_combine_t
  143. * which is a member of sai_transceiver_t.
  144. * This is an example of multi-channel data transfer configuration step.
  145. * @code
  146. * sai_transceiver_t config;
  147. * SAI_GetClassicI2SConfig(&config, kSAI_WordWidth16bits, kSAI_Stereo, kSAI_Channel0Mask|kSAI_Channel1Mask);
  148. * config.fifo.fifoCombine = kSAI_FifoCombineModeEnabledOnWrite;
  149. * SAI_TransferTxSetConfigEDMA(I2S0, &edmaHandle, &config);
  150. * @endcode
  151. *
  152. * @param base SAI base pointer.
  153. * @param handle SAI eDMA handle pointer.
  154. * @param saiConfig sai configurations.
  155. */
  156. void SAI_TransferTxSetConfigEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transceiver_t *saiConfig);
  157. /*!
  158. * @brief Configures the SAI Rx.
  159. *
  160. * @note SAI eDMA supports data transfer in a multiple SAI channels if the FIFO Combine feature is supported.
  161. * To activate the multi-channel transfer enable SAI channels by filling the channelMask
  162. * of sai_transceiver_t with the corresponding values of _sai_channel_mask enum, enable the FIFO Combine
  163. * mode by assigning kSAI_FifoCombineModeEnabledOnRead to the fifoCombine member of sai_fifo_combine_t
  164. * which is a member of sai_transceiver_t.
  165. * This is an example of multi-channel data transfer configuration step.
  166. * @code
  167. * sai_transceiver_t config;
  168. * SAI_GetClassicI2SConfig(&config, kSAI_WordWidth16bits, kSAI_Stereo, kSAI_Channel0Mask|kSAI_Channel1Mask);
  169. * config.fifo.fifoCombine = kSAI_FifoCombineModeEnabledOnRead;
  170. * SAI_TransferRxSetConfigEDMA(I2S0, &edmaHandle, &config);
  171. * @endcode
  172. * @param base SAI base pointer.
  173. * @param handle SAI eDMA handle pointer.
  174. * @param saiConfig sai configurations.
  175. */
  176. void SAI_TransferRxSetConfigEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transceiver_t *saiConfig);
  177. /*!
  178. * @brief Performs a non-blocking SAI transfer using DMA.
  179. *
  180. * @note This interface returns immediately after the transfer initiates. Call
  181. * SAI_GetTransferStatus to poll the transfer status and check whether the SAI transfer is finished.
  182. *
  183. * This function support multi channel transfer,
  184. * 1. for the sai IP support fifo combine mode, application should enable the fifo combine mode, no limitation
  185. * on channel numbers
  186. * 2. for the sai IP not support fifo combine mode, sai edma provide another solution which using
  187. * EDMA modulo feature, but support 2 or 4 channels only.
  188. *
  189. * @param base SAI base pointer.
  190. * @param handle SAI eDMA handle pointer.
  191. * @param xfer Pointer to the DMA transfer structure.
  192. * @retval kStatus_Success Start a SAI eDMA send successfully.
  193. * @retval kStatus_InvalidArgument The input argument is invalid.
  194. * @retval kStatus_TxBusy SAI is busy sending data.
  195. */
  196. status_t SAI_TransferSendEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer);
  197. /*!
  198. * @brief Performs a non-blocking SAI receive using eDMA.
  199. *
  200. * @note This interface returns immediately after the transfer initiates. Call
  201. * the SAI_GetReceiveRemainingBytes to poll the transfer status and check whether the SAI transfer is finished.
  202. *
  203. * This function support multi channel transfer,
  204. * 1. for the sai IP support fifo combine mode, application should enable the fifo combine mode, no limitation
  205. * on channel numbers
  206. * 2. for the sai IP not support fifo combine mode, sai edma provide another solution which using
  207. * EDMA modulo feature, but support 2 or 4 channels only.
  208. *
  209. * @param base SAI base pointer
  210. * @param handle SAI eDMA handle pointer.
  211. * @param xfer Pointer to DMA transfer structure.
  212. * @retval kStatus_Success Start a SAI eDMA receive successfully.
  213. * @retval kStatus_InvalidArgument The input argument is invalid.
  214. * @retval kStatus_RxBusy SAI is busy receiving data.
  215. */
  216. status_t SAI_TransferReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle, sai_transfer_t *xfer);
  217. /*!
  218. * @brief Performs a non-blocking SAI loop transfer using eDMA.
  219. *
  220. * @note This function support loop transfer only,such as A->B->...->A, application must be aware of
  221. * that the more counts of the loop transfer, then more tcd memory required, as the function use the tcd pool in
  222. * sai_edma_handle_t, so application could redefine the SAI_XFER_QUEUE_SIZE to determine the proper TCD pool size.
  223. *
  224. * Once the loop transfer start, application can use function SAI_TransferAbortSendEDMA to stop the loop transfer.
  225. *
  226. * @param base SAI base pointer.
  227. * @param handle SAI eDMA handle pointer.
  228. * @param xfer Pointer to the DMA transfer structure, should be a array with elements counts >=1(loopTransferCount).
  229. * @param loopTransferCount the counts of xfer array.
  230. * @retval kStatus_Success Start a SAI eDMA send successfully.
  231. * @retval kStatus_InvalidArgument The input argument is invalid.
  232. */
  233. status_t SAI_TransferSendLoopEDMA(I2S_Type *base,
  234. sai_edma_handle_t *handle,
  235. sai_transfer_t *xfer,
  236. uint32_t loopTransferCount);
  237. /*!
  238. * @brief Performs a non-blocking SAI loop transfer using eDMA.
  239. *
  240. * @note This function support loop transfer only,such as A->B->...->A, application must be aware of
  241. * that the more counts of the loop transfer, then more tcd memory required, as the function use the tcd pool in
  242. * sai_edma_handle_t, so application could redefine the SAI_XFER_QUEUE_SIZE to determine the proper TCD pool size.
  243. *
  244. * Once the loop transfer start, application can use function SAI_TransferAbortReceiveEDMA to stop the loop transfer.
  245. *
  246. * @param base SAI base pointer.
  247. * @param handle SAI eDMA handle pointer.
  248. * @param xfer Pointer to the DMA transfer structure, should be a array with elements counts >=1(loopTransferCount).
  249. * @param loopTransferCount the counts of xfer array.
  250. * @retval kStatus_Success Start a SAI eDMA receive successfully.
  251. * @retval kStatus_InvalidArgument The input argument is invalid.
  252. */
  253. status_t SAI_TransferReceiveLoopEDMA(I2S_Type *base,
  254. sai_edma_handle_t *handle,
  255. sai_transfer_t *xfer,
  256. uint32_t loopTransferCount);
  257. /*!
  258. * @brief Terminate all SAI send.
  259. *
  260. * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the
  261. * current transfer slot, please call SAI_TransferAbortSendEDMA.
  262. *
  263. * @param base SAI base pointer.
  264. * @param handle SAI eDMA handle pointer.
  265. */
  266. void SAI_TransferTerminateSendEDMA(I2S_Type *base, sai_edma_handle_t *handle);
  267. /*!
  268. * @brief Terminate all SAI receive.
  269. *
  270. * This function will clear all transfer slots buffered in the sai queue. If users only want to abort the
  271. * current transfer slot, please call SAI_TransferAbortReceiveEDMA.
  272. *
  273. * @param base SAI base pointer.
  274. * @param handle SAI eDMA handle pointer.
  275. */
  276. void SAI_TransferTerminateReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle);
  277. /*!
  278. * @brief Aborts a SAI transfer using eDMA.
  279. *
  280. * This function only aborts the current transfer slots, the other transfer slots' information still kept
  281. * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateSendEDMA.
  282. *
  283. * @param base SAI base pointer.
  284. * @param handle SAI eDMA handle pointer.
  285. */
  286. void SAI_TransferAbortSendEDMA(I2S_Type *base, sai_edma_handle_t *handle);
  287. /*!
  288. * @brief Aborts a SAI receive using eDMA.
  289. *
  290. * This function only aborts the current transfer slots, the other transfer slots' information still kept
  291. * in the handler. If users want to terminate all transfer slots, just call SAI_TransferTerminateReceiveEDMA.
  292. *
  293. * @param base SAI base pointer
  294. * @param handle SAI eDMA handle pointer.
  295. */
  296. void SAI_TransferAbortReceiveEDMA(I2S_Type *base, sai_edma_handle_t *handle);
  297. /*!
  298. * @brief Gets byte count sent by SAI.
  299. *
  300. * @param base SAI base pointer.
  301. * @param handle SAI eDMA handle pointer.
  302. * @param count Bytes count sent by SAI.
  303. * @retval kStatus_Success Succeed get the transfer count.
  304. * @retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress.
  305. */
  306. status_t SAI_TransferGetSendCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count);
  307. /*!
  308. * @brief Gets byte count received by SAI.
  309. *
  310. * @param base SAI base pointer
  311. * @param handle SAI eDMA handle pointer.
  312. * @param count Bytes count received by SAI.
  313. * @retval kStatus_Success Succeed get the transfer count.
  314. * @retval kStatus_NoTransferInProgress There is no non-blocking transaction in progress.
  315. */
  316. status_t SAI_TransferGetReceiveCountEDMA(I2S_Type *base, sai_edma_handle_t *handle, size_t *count);
  317. /*!
  318. * @brief Gets valid transfer slot.
  319. *
  320. * This function can be used to query the valid transfer request slot that the application can submit.
  321. * It should be called in the critical section, that means the application could call it in the corresponding callback
  322. * function or disable IRQ before calling it in the application, otherwise, the returned value may not correct.
  323. *
  324. * @param base SAI base pointer
  325. * @param handle SAI eDMA handle pointer.
  326. * @retval valid slot count that application submit.
  327. */
  328. uint32_t SAI_TransferGetValidTransferSlotsEDMA(I2S_Type *base, sai_edma_handle_t *handle);
  329. /*! @} */
  330. #if defined(__cplusplus)
  331. }
  332. #endif
  333. /*!
  334. * @}
  335. */
  336. #endif