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