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