fsl_edma.h 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2015, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #ifndef _FSL_EDMA_H_
  35. #define _FSL_EDMA_H_
  36. #include "fsl_common.h"
  37. /*!
  38. * @addtogroup edma
  39. * @{
  40. */
  41. /*******************************************************************************
  42. * Definitions
  43. ******************************************************************************/
  44. /*! @name Driver version */
  45. /*@{*/
  46. /*! @brief eDMA driver version */
  47. #define FSL_EDMA_DRIVER_VERSION (MAKE_VERSION(2, 1, 2)) /*!< Version 2.1.2. */
  48. /*@}*/
  49. /*! @brief Compute the offset unit from DCHPRI3 */
  50. #define DMA_DCHPRI_INDEX(channel) (((channel) & ~0x03U) | (3 - ((channel)&0x03U)))
  51. /*! @brief Get the pointer of DCHPRIn */
  52. #define DMA_DCHPRIn(base, channel) ((volatile uint8_t *)&((base)->DCHPRI3))[DMA_DCHPRI_INDEX(channel)]
  53. /*! @brief eDMA transfer configuration */
  54. typedef enum _edma_transfer_size
  55. {
  56. kEDMA_TransferSize1Bytes = 0x0U, /*!< Source/Destination data transfer size is 1 byte every time */
  57. kEDMA_TransferSize2Bytes = 0x1U, /*!< Source/Destination data transfer size is 2 bytes every time */
  58. kEDMA_TransferSize4Bytes = 0x2U, /*!< Source/Destination data transfer size is 4 bytes every time */
  59. kEDMA_TransferSize8Bytes = 0x3U, /*!< Source/Destination data transfer size is 8 bytes every time */
  60. kEDMA_TransferSize16Bytes = 0x4U, /*!< Source/Destination data transfer size is 16 bytes every time */
  61. kEDMA_TransferSize32Bytes = 0x5U, /*!< Source/Destination data transfer size is 32 bytes every time */
  62. } edma_transfer_size_t;
  63. /*! @brief eDMA modulo configuration */
  64. typedef enum _edma_modulo
  65. {
  66. kEDMA_ModuloDisable = 0x0U, /*!< Disable modulo */
  67. kEDMA_Modulo2bytes, /*!< Circular buffer size is 2 bytes. */
  68. kEDMA_Modulo4bytes, /*!< Circular buffer size is 4 bytes. */
  69. kEDMA_Modulo8bytes, /*!< Circular buffer size is 8 bytes. */
  70. kEDMA_Modulo16bytes, /*!< Circular buffer size is 16 bytes. */
  71. kEDMA_Modulo32bytes, /*!< Circular buffer size is 32 bytes. */
  72. kEDMA_Modulo64bytes, /*!< Circular buffer size is 64 bytes. */
  73. kEDMA_Modulo128bytes, /*!< Circular buffer size is 128 bytes. */
  74. kEDMA_Modulo256bytes, /*!< Circular buffer size is 256 bytes. */
  75. kEDMA_Modulo512bytes, /*!< Circular buffer size is 512 bytes. */
  76. kEDMA_Modulo1Kbytes, /*!< Circular buffer size is 1 K bytes. */
  77. kEDMA_Modulo2Kbytes, /*!< Circular buffer size is 2 K bytes. */
  78. kEDMA_Modulo4Kbytes, /*!< Circular buffer size is 4 K bytes. */
  79. kEDMA_Modulo8Kbytes, /*!< Circular buffer size is 8 K bytes. */
  80. kEDMA_Modulo16Kbytes, /*!< Circular buffer size is 16 K bytes. */
  81. kEDMA_Modulo32Kbytes, /*!< Circular buffer size is 32 K bytes. */
  82. kEDMA_Modulo64Kbytes, /*!< Circular buffer size is 64 K bytes. */
  83. kEDMA_Modulo128Kbytes, /*!< Circular buffer size is 128 K bytes. */
  84. kEDMA_Modulo256Kbytes, /*!< Circular buffer size is 256 K bytes. */
  85. kEDMA_Modulo512Kbytes, /*!< Circular buffer size is 512 K bytes. */
  86. kEDMA_Modulo1Mbytes, /*!< Circular buffer size is 1 M bytes. */
  87. kEDMA_Modulo2Mbytes, /*!< Circular buffer size is 2 M bytes. */
  88. kEDMA_Modulo4Mbytes, /*!< Circular buffer size is 4 M bytes. */
  89. kEDMA_Modulo8Mbytes, /*!< Circular buffer size is 8 M bytes. */
  90. kEDMA_Modulo16Mbytes, /*!< Circular buffer size is 16 M bytes. */
  91. kEDMA_Modulo32Mbytes, /*!< Circular buffer size is 32 M bytes. */
  92. kEDMA_Modulo64Mbytes, /*!< Circular buffer size is 64 M bytes. */
  93. kEDMA_Modulo128Mbytes, /*!< Circular buffer size is 128 M bytes. */
  94. kEDMA_Modulo256Mbytes, /*!< Circular buffer size is 256 M bytes. */
  95. kEDMA_Modulo512Mbytes, /*!< Circular buffer size is 512 M bytes. */
  96. kEDMA_Modulo1Gbytes, /*!< Circular buffer size is 1 G bytes. */
  97. kEDMA_Modulo2Gbytes, /*!< Circular buffer size is 2 G bytes. */
  98. } edma_modulo_t;
  99. /*! @brief Bandwidth control */
  100. typedef enum _edma_bandwidth
  101. {
  102. kEDMA_BandwidthStallNone = 0x0U, /*!< No eDMA engine stalls. */
  103. kEDMA_BandwidthStall4Cycle = 0x2U, /*!< eDMA engine stalls for 4 cycles after each read/write. */
  104. kEDMA_BandwidthStall8Cycle = 0x3U, /*!< eDMA engine stalls for 8 cycles after each read/write. */
  105. } edma_bandwidth_t;
  106. /*! @brief Channel link type */
  107. typedef enum _edma_channel_link_type
  108. {
  109. kEDMA_LinkNone = 0x0U, /*!< No channel link */
  110. kEDMA_MinorLink, /*!< Channel link after each minor loop */
  111. kEDMA_MajorLink, /*!< Channel link while major loop count exhausted */
  112. } edma_channel_link_type_t;
  113. /*!@brief eDMA channel status flags. */
  114. enum _edma_channel_status_flags
  115. {
  116. kEDMA_DoneFlag = 0x1U, /*!< DONE flag, set while transfer finished, CITER value exhausted*/
  117. kEDMA_ErrorFlag = 0x2U, /*!< eDMA error flag, an error occurred in a transfer */
  118. kEDMA_InterruptFlag = 0x4U, /*!< eDMA interrupt flag, set while an interrupt occurred of this channel */
  119. };
  120. /*! @brief eDMA channel error status flags. */
  121. enum _edma_error_status_flags
  122. {
  123. kEDMA_DestinationBusErrorFlag = DMA_ES_DBE_MASK, /*!< Bus error on destination address */
  124. kEDMA_SourceBusErrorFlag = DMA_ES_SBE_MASK, /*!< Bus error on the source address */
  125. kEDMA_ScatterGatherErrorFlag = DMA_ES_SGE_MASK, /*!< Error on the Scatter/Gather address, not 32byte aligned. */
  126. kEDMA_NbytesErrorFlag = DMA_ES_NCE_MASK, /*!< NBYTES/CITER configuration error */
  127. kEDMA_DestinationOffsetErrorFlag = DMA_ES_DOE_MASK, /*!< Destination offset not aligned with destination size */
  128. kEDMA_DestinationAddressErrorFlag = DMA_ES_DAE_MASK, /*!< Destination address not aligned with destination size */
  129. kEDMA_SourceOffsetErrorFlag = DMA_ES_SOE_MASK, /*!< Source offset not aligned with source size */
  130. kEDMA_SourceAddressErrorFlag = DMA_ES_SAE_MASK, /*!< Source address not aligned with source size*/
  131. kEDMA_ErrorChannelFlag = DMA_ES_ERRCHN_MASK, /*!< Error channel number of the cancelled channel number */
  132. kEDMA_ChannelPriorityErrorFlag = DMA_ES_CPE_MASK, /*!< Channel priority is not unique. */
  133. kEDMA_TransferCanceledFlag = DMA_ES_ECX_MASK, /*!< Transfer cancelled */
  134. #if defined(FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT) && FSL_FEATURE_EDMA_CHANNEL_GROUP_COUNT > 1
  135. kEDMA_GroupPriorityErrorFlag = DMA_ES_GPE_MASK, /*!< Group priority is not unique. */
  136. #endif
  137. kEDMA_ValidFlag = DMA_ES_VLD_MASK, /*!< No error occurred, this bit is 0. Otherwise, it is 1. */
  138. };
  139. /*! @brief eDMA interrupt source */
  140. typedef enum _edma_interrupt_enable
  141. {
  142. kEDMA_ErrorInterruptEnable = 0x1U, /*!< Enable interrupt while channel error occurs. */
  143. kEDMA_MajorInterruptEnable = DMA_CSR_INTMAJOR_MASK, /*!< Enable interrupt while major count exhausted. */
  144. kEDMA_HalfInterruptEnable = DMA_CSR_INTHALF_MASK, /*!< Enable interrupt while major count to half value. */
  145. } edma_interrupt_enable_t;
  146. /*! @brief eDMA transfer type */
  147. typedef enum _edma_transfer_type
  148. {
  149. kEDMA_MemoryToMemory = 0x0U, /*!< Transfer from memory to memory */
  150. kEDMA_PeripheralToMemory, /*!< Transfer from peripheral to memory */
  151. kEDMA_MemoryToPeripheral, /*!< Transfer from memory to peripheral */
  152. } edma_transfer_type_t;
  153. /*! @brief eDMA transfer status */
  154. enum _edma_transfer_status
  155. {
  156. kStatus_EDMA_QueueFull = MAKE_STATUS(kStatusGroup_EDMA, 0), /*!< TCD queue is full. */
  157. kStatus_EDMA_Busy = MAKE_STATUS(kStatusGroup_EDMA, 1), /*!< Channel is busy and can't handle the
  158. transfer request. */
  159. };
  160. /*! @brief eDMA global configuration structure.*/
  161. typedef struct _edma_config
  162. {
  163. bool enableContinuousLinkMode; /*!< Enable (true) continuous link mode. Upon minor loop completion, the channel
  164. activates again if that channel has a minor loop channel link enabled and
  165. the link channel is itself. */
  166. bool enableHaltOnError; /*!< Enable (true) transfer halt on error. Any error causes the HALT bit to set.
  167. Subsequently, all service requests are ignored until the HALT bit is cleared.*/
  168. bool enableRoundRobinArbitration; /*!< Enable (true) round robin channel arbitration method or fixed priority
  169. arbitration is used for channel selection */
  170. bool enableDebugMode; /*!< Enable(true) eDMA debug mode. When in debug mode, the eDMA stalls the start of
  171. a new channel. Executing channels are allowed to complete. */
  172. } edma_config_t;
  173. /*!
  174. * @brief eDMA transfer configuration
  175. *
  176. * This structure configures the source/destination transfer attribute.
  177. */
  178. typedef struct _edma_transfer_config
  179. {
  180. uint32_t srcAddr; /*!< Source data address. */
  181. uint32_t destAddr; /*!< Destination data address. */
  182. edma_transfer_size_t srcTransferSize; /*!< Source data transfer size. */
  183. edma_transfer_size_t destTransferSize; /*!< Destination data transfer size. */
  184. int16_t srcOffset; /*!< Sign-extended offset applied to the current source address to
  185. form the next-state value as each source read is completed. */
  186. int16_t destOffset; /*!< Sign-extended offset applied to the current destination address to
  187. form the next-state value as each destination write is completed. */
  188. uint32_t minorLoopBytes; /*!< Bytes to transfer in a minor loop*/
  189. uint32_t majorLoopCounts; /*!< Major loop iteration count. */
  190. } edma_transfer_config_t;
  191. /*! @brief eDMA channel priority configuration */
  192. typedef struct _edma_channel_Preemption_config
  193. {
  194. bool enableChannelPreemption; /*!< If true: a channel can be suspended by other channel with higher priority */
  195. bool enablePreemptAbility; /*!< If true: a channel can suspend other channel with low priority */
  196. uint8_t channelPriority; /*!< Channel priority */
  197. } edma_channel_Preemption_config_t;
  198. /*! @brief eDMA minor offset configuration */
  199. typedef struct _edma_minor_offset_config
  200. {
  201. bool enableSrcMinorOffset; /*!< Enable(true) or Disable(false) source minor loop offset. */
  202. bool enableDestMinorOffset; /*!< Enable(true) or Disable(false) destination minor loop offset. */
  203. uint32_t minorOffset; /*!< Offset for a minor loop mapping. */
  204. } edma_minor_offset_config_t;
  205. /*!
  206. * @brief eDMA TCD.
  207. *
  208. * This structure is same as TCD register which is described in reference manual,
  209. * and is used to configure the scatter/gather feature as a next hardware TCD.
  210. */
  211. typedef struct _edma_tcd
  212. {
  213. __IO uint32_t SADDR; /*!< SADDR register, used to save source address */
  214. __IO uint16_t SOFF; /*!< SOFF register, save offset bytes every transfer */
  215. __IO uint16_t ATTR; /*!< ATTR register, source/destination transfer size and modulo */
  216. __IO uint32_t NBYTES; /*!< Nbytes register, minor loop length in bytes */
  217. __IO uint32_t SLAST; /*!< SLAST register */
  218. __IO uint32_t DADDR; /*!< DADDR register, used for destination address */
  219. __IO uint16_t DOFF; /*!< DOFF register, used for destination offset */
  220. __IO uint16_t CITER; /*!< CITER register, current minor loop numbers, for unfinished minor loop.*/
  221. __IO uint32_t DLAST_SGA; /*!< DLASTSGA register, next stcd address used in scatter-gather mode */
  222. __IO uint16_t CSR; /*!< CSR register, for TCD control status */
  223. __IO uint16_t BITER; /*!< BITER register, begin minor loop count. */
  224. } edma_tcd_t;
  225. /*! @brief Callback for eDMA */
  226. struct _edma_handle;
  227. /*! @brief Define callback function for eDMA.
  228. *
  229. * This callback function is called in the EDMA interrupt handle.
  230. * In normal mode, run into callback function means the transfer users need is done.
  231. * In scatter gather mode, run into callback function means a transfer control block (tcd) is finished. Not
  232. * all transfer finished, users can get the finished tcd numbers using interface EDMA_GetUnusedTCDNumber.
  233. *
  234. * @param handle EDMA handle pointer, users shall not touch the values inside.
  235. * @param userData The callback user paramter pointer. Users can use this paramter to involve things users need to
  236. * change in EDMA callback function.
  237. * @param transferDone If the current loaded transfer done. In normal mode it means if all transfer done. In scatter
  238. * gather mode, this paramter shows is the current transfer block in EDMA regsiter is done. As the
  239. * load of core is different, it will be different if the new tcd loaded into EDMA registers while
  240. * this callback called. If true, it always means new tcd still not loaded into registers, while
  241. * false means new tcd already loaded into registers.
  242. * @param tcds How many tcds are done from the last callback. This parameter only used in scatter gather mode. It
  243. * tells user how many tcds are finished between the last callback and this.
  244. */
  245. typedef void (*edma_callback)(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds);
  246. /*! @brief eDMA transfer handle structure */
  247. typedef struct _edma_handle
  248. {
  249. edma_callback callback; /*!< Callback function for major count exhausted. */
  250. void *userData; /*!< Callback function parameter. */
  251. DMA_Type *base; /*!< eDMA peripheral base address. */
  252. edma_tcd_t *tcdPool; /*!< Pointer to memory stored TCDs. */
  253. uint8_t channel; /*!< eDMA channel number. */
  254. volatile int8_t header; /*!< The first TCD index. Should point to the next TCD to be loaded into the eDMA engine. */
  255. volatile int8_t tail; /*!< The last TCD index. Should point to the next TCD to be stored into the memory pool. */
  256. volatile int8_t tcdUsed; /*!< The number of used TCD slots. Should reflect the number of TCDs can be used/loaded in
  257. the memory. */
  258. volatile int8_t tcdSize; /*!< The total number of TCD slots in the queue. */
  259. uint8_t flags; /*!< The status of the current channel. */
  260. } edma_handle_t;
  261. /*******************************************************************************
  262. * APIs
  263. ******************************************************************************/
  264. #if defined(__cplusplus)
  265. extern "C" {
  266. #endif /* __cplusplus */
  267. /*!
  268. * @name eDMA initialization and de-initialization
  269. * @{
  270. */
  271. /*!
  272. * @brief Initializes the eDMA peripheral.
  273. *
  274. * This function ungates the eDMA clock and configures the eDMA peripheral according
  275. * to the configuration structure.
  276. *
  277. * @param base eDMA peripheral base address.
  278. * @param config A pointer to the configuration structure, see "edma_config_t".
  279. * @note This function enables the minor loop map feature.
  280. */
  281. void EDMA_Init(DMA_Type *base, const edma_config_t *config);
  282. /*!
  283. * @brief Deinitializes the eDMA peripheral.
  284. *
  285. * This function gates the eDMA clock.
  286. *
  287. * @param base eDMA peripheral base address.
  288. */
  289. void EDMA_Deinit(DMA_Type *base);
  290. /*!
  291. * @brief Push content of TCD structure into hardware TCD register.
  292. *
  293. * @param base EDMA peripheral base address.
  294. * @param channel EDMA channel number.
  295. * @param tcd Point to TCD structure.
  296. */
  297. void EDMA_InstallTCD(DMA_Type *base, uint32_t channel, edma_tcd_t *tcd);
  298. /*!
  299. * @brief Gets the eDMA default configuration structure.
  300. *
  301. * This function sets the configuration structure to default values.
  302. * The default configuration is set to the following values.
  303. * @code
  304. * config.enableContinuousLinkMode = false;
  305. * config.enableHaltOnError = true;
  306. * config.enableRoundRobinArbitration = false;
  307. * config.enableDebugMode = false;
  308. * @endcode
  309. *
  310. * @param config A pointer to the eDMA configuration structure.
  311. */
  312. void EDMA_GetDefaultConfig(edma_config_t *config);
  313. /* @} */
  314. /*!
  315. * @name eDMA Channel Operation
  316. * @{
  317. */
  318. /*!
  319. * @brief Sets all TCD registers to default values.
  320. *
  321. * This function sets TCD registers for this channel to default values.
  322. *
  323. * @param base eDMA peripheral base address.
  324. * @param channel eDMA channel number.
  325. * @note This function must not be called while the channel transfer is ongoing
  326. * or it causes unpredictable results.
  327. * @note This function enables the auto stop request feature.
  328. */
  329. void EDMA_ResetChannel(DMA_Type *base, uint32_t channel);
  330. /*!
  331. * @brief Configures the eDMA transfer attribute.
  332. *
  333. * This function configures the transfer attribute, including source address, destination address,
  334. * transfer size, address offset, and so on. It also configures the scatter gather feature if the
  335. * user supplies the TCD address.
  336. * Example:
  337. * @code
  338. * edma_transfer_t config;
  339. * edma_tcd_t tcd;
  340. * config.srcAddr = ..;
  341. * config.destAddr = ..;
  342. * ...
  343. * EDMA_SetTransferConfig(DMA0, channel, &config, &stcd);
  344. * @endcode
  345. *
  346. * @param base eDMA peripheral base address.
  347. * @param channel eDMA channel number.
  348. * @param config Pointer to eDMA transfer configuration structure.
  349. * @param nextTcd Point to TCD structure. It can be NULL if users
  350. * do not want to enable scatter/gather feature.
  351. * @note If nextTcd is not NULL, it means scatter gather feature is enabled
  352. * and DREQ bit is cleared in the previous transfer configuration, which
  353. * is set in the eDMA_ResetChannel.
  354. */
  355. void EDMA_SetTransferConfig(DMA_Type *base,
  356. uint32_t channel,
  357. const edma_transfer_config_t *config,
  358. edma_tcd_t *nextTcd);
  359. /*!
  360. * @brief Configures the eDMA minor offset feature.
  361. *
  362. * The minor offset means that the signed-extended value is added to the source address or destination
  363. * address after each minor loop.
  364. *
  365. * @param base eDMA peripheral base address.
  366. * @param channel eDMA channel number.
  367. * @param config A pointer to the minor offset configuration structure.
  368. */
  369. void EDMA_SetMinorOffsetConfig(DMA_Type *base, uint32_t channel, const edma_minor_offset_config_t *config);
  370. /*!
  371. * @brief Configures the eDMA channel preemption feature.
  372. *
  373. * This function configures the channel preemption attribute and the priority of the channel.
  374. *
  375. * @param base eDMA peripheral base address.
  376. * @param channel eDMA channel number
  377. * @param config A pointer to the channel preemption configuration structure.
  378. */
  379. static inline void EDMA_SetChannelPreemptionConfig(DMA_Type *base,
  380. uint32_t channel,
  381. const edma_channel_Preemption_config_t *config)
  382. {
  383. assert(channel < FSL_FEATURE_EDMA_MODULE_CHANNEL);
  384. assert(config != NULL);
  385. DMA_DCHPRIn(base, channel) =
  386. (DMA_DCHPRI0_DPA(!config->enablePreemptAbility) | DMA_DCHPRI0_ECP(config->enableChannelPreemption) |
  387. DMA_DCHPRI0_CHPRI(config->channelPriority));
  388. }
  389. /*!
  390. * @brief Sets the channel link for the eDMA transfer.
  391. *
  392. * This function configures either the minor link or the major link mode. The minor link means that the channel link is
  393. * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is
  394. * exhausted.
  395. *
  396. * @param base eDMA peripheral base address.
  397. * @param channel eDMA channel number.
  398. * @param type A channel link type, which can be one of the following:
  399. * @arg kEDMA_LinkNone
  400. * @arg kEDMA_MinorLink
  401. * @arg kEDMA_MajorLink
  402. * @param linkedChannel The linked channel number.
  403. * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
  404. */
  405. void EDMA_SetChannelLink(DMA_Type *base, uint32_t channel, edma_channel_link_type_t type, uint32_t linkedChannel);
  406. /*!
  407. * @brief Sets the bandwidth for the eDMA transfer.
  408. *
  409. * Because the eDMA processes the minor loop, it continuously generates read/write sequences
  410. * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
  411. * each read/write access to control the bus request bandwidth seen by the crossbar switch.
  412. *
  413. * @param base eDMA peripheral base address.
  414. * @param channel eDMA channel number.
  415. * @param bandWidth A bandwidth setting, which can be one of the following:
  416. * @arg kEDMABandwidthStallNone
  417. * @arg kEDMABandwidthStall4Cycle
  418. * @arg kEDMABandwidthStall8Cycle
  419. */
  420. void EDMA_SetBandWidth(DMA_Type *base, uint32_t channel, edma_bandwidth_t bandWidth);
  421. /*!
  422. * @brief Sets the source modulo and the destination modulo for the eDMA transfer.
  423. *
  424. * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
  425. * calculation is performed or the original register value. It provides the ability to implement a circular data
  426. * queue easily.
  427. *
  428. * @param base eDMA peripheral base address.
  429. * @param channel eDMA channel number.
  430. * @param srcModulo A source modulo value.
  431. * @param destModulo A destination modulo value.
  432. */
  433. void EDMA_SetModulo(DMA_Type *base, uint32_t channel, edma_modulo_t srcModulo, edma_modulo_t destModulo);
  434. #if defined(FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT) && FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT
  435. /*!
  436. * @brief Enables an async request for the eDMA transfer.
  437. *
  438. * @param base eDMA peripheral base address.
  439. * @param channel eDMA channel number.
  440. * @param enable The command to enable (true) or disable (false).
  441. */
  442. static inline void EDMA_EnableAsyncRequest(DMA_Type *base, uint32_t channel, bool enable)
  443. {
  444. assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
  445. base->EARS = (base->EARS & (~(1U << channel))) | ((uint32_t)enable << channel);
  446. }
  447. #endif /* FSL_FEATURE_EDMA_ASYNCHRO_REQUEST_CHANNEL_COUNT */
  448. /*!
  449. * @brief Enables an auto stop request for the eDMA transfer.
  450. *
  451. * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
  452. *
  453. * @param base eDMA peripheral base address.
  454. * @param channel eDMA channel number.
  455. * @param enable The command to enable (true) or disable (false).
  456. */
  457. static inline void EDMA_EnableAutoStopRequest(DMA_Type *base, uint32_t channel, bool enable)
  458. {
  459. assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
  460. base->TCD[channel].CSR = (base->TCD[channel].CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
  461. }
  462. /*!
  463. * @brief Enables the interrupt source for the eDMA transfer.
  464. *
  465. * @param base eDMA peripheral base address.
  466. * @param channel eDMA channel number.
  467. * @param mask The mask of interrupt source to be set. Users need to use
  468. * the defined edma_interrupt_enable_t type.
  469. */
  470. void EDMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
  471. /*!
  472. * @brief Disables the interrupt source for the eDMA transfer.
  473. *
  474. * @param base eDMA peripheral base address.
  475. * @param channel eDMA channel number.
  476. * @param mask The mask of the interrupt source to be set. Use
  477. * the defined edma_interrupt_enable_t type.
  478. */
  479. void EDMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel, uint32_t mask);
  480. /* @} */
  481. /*!
  482. * @name eDMA TCD Operation
  483. * @{
  484. */
  485. /*!
  486. * @brief Sets all fields to default values for the TCD structure.
  487. *
  488. * This function sets all fields for this TCD structure to default value.
  489. *
  490. * @param tcd Pointer to the TCD structure.
  491. * @note This function enables the auto stop request feature.
  492. */
  493. void EDMA_TcdReset(edma_tcd_t *tcd);
  494. /*!
  495. * @brief Configures the eDMA TCD transfer attribute.
  496. *
  497. * The TCD is a transfer control descriptor. The content of the TCD is the same as the hardware TCD registers.
  498. * The STCD is used in the scatter-gather mode.
  499. * This function configures the TCD transfer attribute, including source address, destination address,
  500. * transfer size, address offset, and so on. It also configures the scatter gather feature if the
  501. * user supplies the next TCD address.
  502. * Example:
  503. * @code
  504. * edma_transfer_t config = {
  505. * ...
  506. * }
  507. * edma_tcd_t tcd __aligned(32);
  508. * edma_tcd_t nextTcd __aligned(32);
  509. * EDMA_TcdSetTransferConfig(&tcd, &config, &nextTcd);
  510. * @endcode
  511. *
  512. * @param tcd Pointer to the TCD structure.
  513. * @param config Pointer to eDMA transfer configuration structure.
  514. * @param nextTcd Pointer to the next TCD structure. It can be NULL if users
  515. * do not want to enable scatter/gather feature.
  516. * @note TCD address should be 32 bytes aligned or it causes an eDMA error.
  517. * @note If the nextTcd is not NULL, the scatter gather feature is enabled
  518. * and DREQ bit is cleared in the previous transfer configuration, which
  519. * is set in the EDMA_TcdReset.
  520. */
  521. void EDMA_TcdSetTransferConfig(edma_tcd_t *tcd, const edma_transfer_config_t *config, edma_tcd_t *nextTcd);
  522. /*!
  523. * @brief Configures the eDMA TCD minor offset feature.
  524. *
  525. * A minor offset is a signed-extended value added to the source address or a destination
  526. * address after each minor loop.
  527. *
  528. * @param tcd A point to the TCD structure.
  529. * @param config A pointer to the minor offset configuration structure.
  530. */
  531. void EDMA_TcdSetMinorOffsetConfig(edma_tcd_t *tcd, const edma_minor_offset_config_t *config);
  532. /*!
  533. * @brief Sets the channel link for the eDMA TCD.
  534. *
  535. * This function configures either a minor link or a major link. The minor link means the channel link is
  536. * triggered every time CITER decreases by 1. The major link means that the channel link is triggered when the CITER is
  537. * exhausted.
  538. *
  539. * @note Users should ensure that DONE flag is cleared before calling this interface, or the configuration is invalid.
  540. * @param tcd Point to the TCD structure.
  541. * @param type Channel link type, it can be one of:
  542. * @arg kEDMA_LinkNone
  543. * @arg kEDMA_MinorLink
  544. * @arg kEDMA_MajorLink
  545. * @param linkedChannel The linked channel number.
  546. */
  547. void EDMA_TcdSetChannelLink(edma_tcd_t *tcd, edma_channel_link_type_t type, uint32_t linkedChannel);
  548. /*!
  549. * @brief Sets the bandwidth for the eDMA TCD.
  550. *
  551. * Because the eDMA processes the minor loop, it continuously generates read/write sequences
  552. * until the minor count is exhausted. The bandwidth forces the eDMA to stall after the completion of
  553. * each read/write access to control the bus request bandwidth seen by the crossbar switch.
  554. * @param tcd A pointer to the TCD structure.
  555. * @param bandWidth A bandwidth setting, which can be one of the following:
  556. * @arg kEDMABandwidthStallNone
  557. * @arg kEDMABandwidthStall4Cycle
  558. * @arg kEDMABandwidthStall8Cycle
  559. */
  560. static inline void EDMA_TcdSetBandWidth(edma_tcd_t *tcd, edma_bandwidth_t bandWidth)
  561. {
  562. assert(tcd != NULL);
  563. assert(((uint32_t)tcd & 0x1FU) == 0);
  564. tcd->CSR = (tcd->CSR & (~DMA_CSR_BWC_MASK)) | DMA_CSR_BWC(bandWidth);
  565. }
  566. /*!
  567. * @brief Sets the source modulo and the destination modulo for the eDMA TCD.
  568. *
  569. * This function defines a specific address range specified to be the value after (SADDR + SOFF)/(DADDR + DOFF)
  570. * calculation is performed or the original register value. It provides the ability to implement a circular data
  571. * queue easily.
  572. *
  573. * @param tcd A pointer to the TCD structure.
  574. * @param srcModulo A source modulo value.
  575. * @param destModulo A destination modulo value.
  576. */
  577. void EDMA_TcdSetModulo(edma_tcd_t *tcd, edma_modulo_t srcModulo, edma_modulo_t destModulo);
  578. /*!
  579. * @brief Sets the auto stop request for the eDMA TCD.
  580. *
  581. * If enabling the auto stop request, the eDMA hardware automatically disables the hardware channel request.
  582. *
  583. * @param tcd A pointer to the TCD structure.
  584. * @param enable The command to enable (true) or disable (false).
  585. */
  586. static inline void EDMA_TcdEnableAutoStopRequest(edma_tcd_t *tcd, bool enable)
  587. {
  588. assert(tcd != NULL);
  589. assert(((uint32_t)tcd & 0x1FU) == 0);
  590. tcd->CSR = (tcd->CSR & (~DMA_CSR_DREQ_MASK)) | DMA_CSR_DREQ(enable);
  591. }
  592. /*!
  593. * @brief Enables the interrupt source for the eDMA TCD.
  594. *
  595. * @param tcd Point to the TCD structure.
  596. * @param mask The mask of interrupt source to be set. Users need to use
  597. * the defined edma_interrupt_enable_t type.
  598. */
  599. void EDMA_TcdEnableInterrupts(edma_tcd_t *tcd, uint32_t mask);
  600. /*!
  601. * @brief Disables the interrupt source for the eDMA TCD.
  602. *
  603. * @param tcd Point to the TCD structure.
  604. * @param mask The mask of interrupt source to be set. Users need to use
  605. * the defined edma_interrupt_enable_t type.
  606. */
  607. void EDMA_TcdDisableInterrupts(edma_tcd_t *tcd, uint32_t mask);
  608. /*! @} */
  609. /*!
  610. * @name eDMA Channel Transfer Operation
  611. * @{
  612. */
  613. /*!
  614. * @brief Enables the eDMA hardware channel request.
  615. *
  616. * This function enables the hardware channel request.
  617. *
  618. * @param base eDMA peripheral base address.
  619. * @param channel eDMA channel number.
  620. */
  621. static inline void EDMA_EnableChannelRequest(DMA_Type *base, uint32_t channel)
  622. {
  623. assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
  624. base->SERQ = DMA_SERQ_SERQ(channel);
  625. }
  626. /*!
  627. * @brief Disables the eDMA hardware channel request.
  628. *
  629. * This function disables the hardware channel request.
  630. *
  631. * @param base eDMA peripheral base address.
  632. * @param channel eDMA channel number.
  633. */
  634. static inline void EDMA_DisableChannelRequest(DMA_Type *base, uint32_t channel)
  635. {
  636. assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
  637. base->CERQ = DMA_CERQ_CERQ(channel);
  638. }
  639. /*!
  640. * @brief Starts the eDMA transfer by using the software trigger.
  641. *
  642. * This function starts a minor loop transfer.
  643. *
  644. * @param base eDMA peripheral base address.
  645. * @param channel eDMA channel number.
  646. */
  647. static inline void EDMA_TriggerChannelStart(DMA_Type *base, uint32_t channel)
  648. {
  649. assert(channel < FSL_FEATURE_DMAMUX_MODULE_CHANNEL);
  650. base->SSRT = DMA_SSRT_SSRT(channel);
  651. }
  652. /*! @} */
  653. /*!
  654. * @name eDMA Channel Status Operation
  655. * @{
  656. */
  657. /*!
  658. * @brief Gets the remaining major loop count from the eDMA current channel TCD.
  659. *
  660. * This function checks the TCD (Task Control Descriptor) status for a specified
  661. * eDMA channel and returns the number of major loop count that has not finished.
  662. *
  663. * @param base eDMA peripheral base address.
  664. * @param channel eDMA channel number.
  665. * @return Major loop count which has not been transferred yet for the current TCD.
  666. * @note 1. This function can only be used to get unfinished major loop count of transfer without
  667. * the next TCD, or it might be inaccuracy.
  668. * 2. The unfinished/remaining transfer bytes cannot be obtained directly from registers while
  669. * the channel is running.
  670. * Because to calculate the remaining bytes, the initial NBYTES configured in DMA_TCDn_NBYTES_MLNO
  671. * register is needed while the eDMA IP does not support getting it while a channel is active.
  672. * In another word, the NBYTES value reading is always the actual (decrementing) NBYTES value the dma_engine
  673. * is working with while a channel is running.
  674. * Consequently, to get the remaining transfer bytes, a software-saved initial value of NBYTES (for example
  675. * copied before enabling the channel) is needed. The formula to calculate it is shown below:
  676. * RemainingBytes = RemainingMajorLoopCount * NBYTES(initially configured)
  677. */
  678. uint32_t EDMA_GetRemainingMajorLoopCount(DMA_Type *base, uint32_t channel);
  679. /*!
  680. * @brief Gets the eDMA channel error status flags.
  681. *
  682. * @param base eDMA peripheral base address.
  683. * @return The mask of error status flags. Users need to use the
  684. * _edma_error_status_flags type to decode the return variables.
  685. */
  686. static inline uint32_t EDMA_GetErrorStatusFlags(DMA_Type *base)
  687. {
  688. return base->ES;
  689. }
  690. /*!
  691. * @brief Gets the eDMA channel status flags.
  692. *
  693. * @param base eDMA peripheral base address.
  694. * @param channel eDMA channel number.
  695. * @return The mask of channel status flags. Users need to use the
  696. * _edma_channel_status_flags type to decode the return variables.
  697. */
  698. uint32_t EDMA_GetChannelStatusFlags(DMA_Type *base, uint32_t channel);
  699. /*!
  700. * @brief Clears the eDMA channel status flags.
  701. *
  702. * @param base eDMA peripheral base address.
  703. * @param channel eDMA channel number.
  704. * @param mask The mask of channel status to be cleared. Users need to use
  705. * the defined _edma_channel_status_flags type.
  706. */
  707. void EDMA_ClearChannelStatusFlags(DMA_Type *base, uint32_t channel, uint32_t mask);
  708. /*! @} */
  709. /*!
  710. * @name eDMA Transactional Operation
  711. */
  712. /*!
  713. * @brief Creates the eDMA handle.
  714. *
  715. * This function is called if using the transactional API for eDMA. This function
  716. * initializes the internal state of the eDMA handle.
  717. *
  718. * @param handle eDMA handle pointer. The eDMA handle stores callback function and
  719. * parameters.
  720. * @param base eDMA peripheral base address.
  721. * @param channel eDMA channel number.
  722. */
  723. void EDMA_CreateHandle(edma_handle_t *handle, DMA_Type *base, uint32_t channel);
  724. /*!
  725. * @brief Installs the TCDs memory pool into the eDMA handle.
  726. *
  727. * This function is called after the EDMA_CreateHandle to use scatter/gather feature. This function shall only be used
  728. * while users need to use scatter gather mode. Scatter gather mode enables EDMA to load a new transfer control block
  729. * (tcd) in hardware, and automatically reconfigure that DMA channel for a new transfer.
  730. * Users need to preapre tcd memory and also configure tcds using interface EDMA_SubmitTransfer.
  731. *
  732. * @param handle eDMA handle pointer.
  733. * @param tcdPool A memory pool to store TCDs. It must be 32 bytes aligned.
  734. * @param tcdSize The number of TCD slots.
  735. */
  736. void EDMA_InstallTCDMemory(edma_handle_t *handle, edma_tcd_t *tcdPool, uint32_t tcdSize);
  737. /*!
  738. * @brief Installs a callback function for the eDMA transfer.
  739. *
  740. * This callback is called in the eDMA IRQ handler. Use the callback to do something after
  741. * the current major loop transfer completes. This function will be called every time one tcd finished transfer.
  742. *
  743. * @param handle eDMA handle pointer.
  744. * @param callback eDMA callback function pointer.
  745. * @param userData A parameter for the callback function.
  746. */
  747. void EDMA_SetCallback(edma_handle_t *handle, edma_callback callback, void *userData);
  748. /*!
  749. * @brief Prepares the eDMA transfer structure.
  750. *
  751. * This function prepares the transfer configuration structure according to the user input.
  752. *
  753. * @param config The user configuration structure of type edma_transfer_t.
  754. * @param srcAddr eDMA transfer source address.
  755. * @param srcWidth eDMA transfer source address width(bytes).
  756. * @param destAddr eDMA transfer destination address.
  757. * @param destWidth eDMA transfer destination address width(bytes).
  758. * @param bytesEachRequest eDMA transfer bytes per channel request.
  759. * @param transferBytes eDMA transfer bytes to be transferred.
  760. * @param type eDMA transfer type.
  761. * @note The data address and the data width must be consistent. For example, if the SRC
  762. * is 4 bytes, the source address must be 4 bytes aligned, or it results in
  763. * source address error (SAE).
  764. */
  765. void EDMA_PrepareTransfer(edma_transfer_config_t *config,
  766. void *srcAddr,
  767. uint32_t srcWidth,
  768. void *destAddr,
  769. uint32_t destWidth,
  770. uint32_t bytesEachRequest,
  771. uint32_t transferBytes,
  772. edma_transfer_type_t type);
  773. /*!
  774. * @brief Submits the eDMA transfer request.
  775. *
  776. * This function submits the eDMA transfer request according to the transfer configuration structure.
  777. * In scatter gather mode, call this function will add a configured tcd to the circular list of tcd pool.
  778. * The tcd pools is setup by call function EDMA_InstallTCDMemory before.
  779. *
  780. * @param handle eDMA handle pointer.
  781. * @param config Pointer to eDMA transfer configuration structure.
  782. * @retval kStatus_EDMA_Success It means submit transfer request succeed.
  783. * @retval kStatus_EDMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
  784. * @retval kStatus_EDMA_Busy It means the given channel is busy, need to submit request later.
  785. */
  786. status_t EDMA_SubmitTransfer(edma_handle_t *handle, const edma_transfer_config_t *config);
  787. /*!
  788. * @brief eDMA starts transfer.
  789. *
  790. * This function enables the channel request. Users can call this function after submitting the transfer request
  791. * or before submitting the transfer request.
  792. *
  793. * @param handle eDMA handle pointer.
  794. */
  795. void EDMA_StartTransfer(edma_handle_t *handle);
  796. /*!
  797. * @brief eDMA stops transfer.
  798. *
  799. * This function disables the channel request to pause the transfer. Users can call EDMA_StartTransfer()
  800. * again to resume the transfer.
  801. *
  802. * @param handle eDMA handle pointer.
  803. */
  804. void EDMA_StopTransfer(edma_handle_t *handle);
  805. /*!
  806. * @brief eDMA aborts transfer.
  807. *
  808. * This function disables the channel request and clear transfer status bits.
  809. * Users can submit another transfer after calling this API.
  810. *
  811. * @param handle DMA handle pointer.
  812. */
  813. void EDMA_AbortTransfer(edma_handle_t *handle);
  814. /*!
  815. * @brief Get unused TCD slot number.
  816. *
  817. * This function gets current tcd index which is run. If the TCD pool pointer is NULL, it will return 0.
  818. *
  819. * @param handle DMA handle pointer.
  820. * @return The unused tcd slot number.
  821. */
  822. static inline uint32_t EDMA_GetUnusedTCDNumber(edma_handle_t *handle)
  823. {
  824. return (handle->tcdSize - handle->tcdUsed);
  825. }
  826. /*!
  827. * @brief Get the next tcd address.
  828. *
  829. * This function gets the next tcd address. If this is last TCD, return 0.
  830. *
  831. * @param handle DMA handle pointer.
  832. * @return The next TCD address.
  833. */
  834. static inline uint32_t EDMA_GetNextTCDAddress(edma_handle_t *handle)
  835. {
  836. return (handle->base->TCD[handle->channel].DLAST_SGA);
  837. }
  838. /*!
  839. * @brief eDMA IRQ handler for the current major loop transfer completion.
  840. *
  841. * This function clears the channel major interrupt flag and calls
  842. * the callback function if it is not NULL.
  843. *
  844. * Note:
  845. * For the case using TCD queue, when the major iteration count is exhausted, additional operations are performed.
  846. * These include the final address adjustments and reloading of the BITER field into the CITER.
  847. * Assertion of an optional interrupt request also occurs at this time, as does a possible fetch of a new TCD from
  848. * memory using the scatter/gather address pointer included in the descriptor (if scatter/gather is enabled).
  849. *
  850. * For instance, when the time interrupt of TCD[0] happens, the TCD[1] has already been loaded into the eDMA engine.
  851. * As sga and sga_index are calculated based on the DLAST_SGA bitfield lies in the TCD_CSR register, the sga_index
  852. * in this case should be 2 (DLAST_SGA of TCD[1] stores the address of TCD[2]). Thus, the "tcdUsed" updated should be
  853. * (tcdUsed - 2U) which indicates the number of TCDs can be loaded in the memory pool (because TCD[0] and TCD[1] have
  854. * been loaded into the eDMA engine at this point already.).
  855. *
  856. * For the last two continuous ISRs in a scatter/gather process, they both load the last TCD (The last ISR does not
  857. * load a new TCD) from the memory pool to the eDMA engine when major loop completes.
  858. * Therefore, ensure that the header and tcdUsed updated are identical for them.
  859. * tcdUsed are both 0 in this case as no TCD to be loaded.
  860. *
  861. * See the "eDMA basic data flow" in the eDMA Functional description section of the Reference Manual for
  862. * further details.
  863. *
  864. * @param handle eDMA handle pointer.
  865. */
  866. void EDMA_HandleIRQ(edma_handle_t *handle);
  867. /* @} */
  868. #if defined(__cplusplus)
  869. }
  870. #endif /* __cplusplus */
  871. /* @} */
  872. #endif /*_FSL_EDMA_H_*/