1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2022 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #ifndef _FSL_DMA_H_
10 #define _FSL_DMA_H_
11 
12 #include "fsl_common.h"
13 
14 /*!
15  * @addtogroup dma
16  * @{
17  */
18 
19 /*! @file */
20 /*******************************************************************************
21  * Definitions
22  ******************************************************************************/
23 
24 /*! @name Driver version */
25 /*@{*/
26 /*! @brief DMA driver version */
27 #define FSL_DMA_DRIVER_VERSION (MAKE_VERSION(2, 5, 0)) /*!< Version 2.5.0. */
28 /*@}*/
29 
30 /*! @brief DMA max transfer size */
31 #define DMA_MAX_TRANSFER_COUNT 0x400U
32 /*! @brief DMA channel numbers */
33 #if defined FSL_FEATURE_DMA_NUMBER_OF_CHANNELS
34 #define FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(x) FSL_FEATURE_DMA_NUMBER_OF_CHANNELS
35 #define FSL_FEATURE_DMA_MAX_CHANNELS           FSL_FEATURE_DMA_NUMBER_OF_CHANNELS
36 #define FSL_FEATURE_DMA_ALL_CHANNELS           (FSL_FEATURE_DMA_NUMBER_OF_CHANNELS * FSL_FEATURE_SOC_DMA_COUNT)
37 #endif
38 /*! @brief DMA head link descriptor table align size */
39 #define FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE (16U)
40 /*! @brief DMA head descriptor table allocate macro
41  * To simplify user interface, this macro will help allocate descriptor memory,
42  * user just need to provide the name and the number for the allocate descriptor.
43  *
44  * @param name Allocate decriptor name.
45  * @param number Number of descriptor to be allocated.
46  */
47 #define DMA_ALLOCATE_HEAD_DESCRIPTORS(name, number) \
48     SDK_ALIGN(dma_descriptor_t name[number], FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE)
49 /*! @brief DMA head descriptor table allocate macro at noncacheable section
50  * To simplify user interface, this macro will help allocate descriptor memory at noncacheable section,
51  * user just need to provide the name and the number for the allocate descriptor.
52  *
53  * @param name Allocate decriptor name.
54  * @param number Number of descriptor to be allocated.
55  */
56 #define DMA_ALLOCATE_HEAD_DESCRIPTORS_AT_NONCACHEABLE(name, number) \
57     AT_NONCACHEABLE_SECTION_ALIGN(dma_descriptor_t name[number], FSL_FEATURE_DMA_DESCRIPTOR_ALIGN_SIZE)
58 /*! @brief DMA link descriptor table allocate macro
59  * To simplify user interface, this macro will help allocate descriptor memory,
60  * user just need to provide the name and the number for the allocate descriptor.
61  *
62  * @param name Allocate decriptor name.
63  * @param number Number of descriptor to be allocated.
64  */
65 #define DMA_ALLOCATE_LINK_DESCRIPTORS(name, number) \
66     SDK_ALIGN(dma_descriptor_t name[number], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE)
67 /*! @brief DMA link descriptor table allocate macro at noncacheable section
68  * To simplify user interface, this macro will help allocate descriptor memory at noncacheable section,
69  * user just need to provide the name and the number for the allocate descriptor.
70  *
71  * @param name Allocate decriptor name.
72  * @param number Number of descriptor to be allocated.
73  */
74 #define DMA_ALLOCATE_LINK_DESCRIPTORS_AT_NONCACHEABLE(name, number) \
75     AT_NONCACHEABLE_SECTION_ALIGN(dma_descriptor_t name[number], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE)
76 /*! @brief DMA transfer buffer address need to align with the transfer width */
77 #define DMA_ALLOCATE_DATA_TRANSFER_BUFFER(name, width) SDK_ALIGN(name, width)
78 /* Channel group consists of 32 channels. channel_group = 0 */
79 #define DMA_CHANNEL_GROUP(channel) (((uint8_t)(channel)) >> 5U)
80 /* Channel index in channel group. channel_index = (channel % (channel number per instance)) */
81 #define DMA_CHANNEL_INDEX(base, channel) (((uint8_t)(channel)) & 0x1FU)
82 /*! @brief DMA linked descriptor address algin size */
83 #define DMA_COMMON_REG_GET(base, channel, reg) \
84     (((volatile uint32_t *)(&((base)->COMMON[0].reg)))[DMA_CHANNEL_GROUP(channel)])
85 #define DMA_COMMON_CONST_REG_GET(base, channel, reg) \
86     (((volatile const uint32_t *)(&((base)->COMMON[0].reg)))[DMA_CHANNEL_GROUP(channel)])
87 #define DMA_COMMON_REG_SET(base, channel, reg, value) \
88     (((volatile uint32_t *)(&((base)->COMMON[0].reg)))[DMA_CHANNEL_GROUP(channel)] = (value))
89 
90 /*! @brief DMA descriptor end address calculate
91  * @param start start address
92  * @param inc address interleave size
93  * @param bytes transfer bytes
94  * @param width transfer width
95  */
96 #define DMA_DESCRIPTOR_END_ADDRESS(start, inc, bytes, width) \
97     ((uint32_t *)((uint32_t)(start) + (inc) * (bytes) - (inc) * (width)))
98 
99 #define DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes) \
100     (DMA_SetChannelXferConfig(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes))
101 
102 /*! @brief _dma_transfer_status DMA transfer status */
103 enum
104 {
105     kStatus_DMA_Busy = MAKE_STATUS(kStatusGroup_DMA, 0), /*!< Channel is busy and can't handle the
106                                                                 transfer request. */
107 };
108 
109 /*! @brief _dma_addr_interleave_size dma address interleave size */
110 enum
111 {
112     kDMA_AddressInterleave0xWidth = 0U, /*!< dma source/destination address no interleave */
113     kDMA_AddressInterleave1xWidth = 1U, /*!< dma source/destination address interleave 1xwidth */
114     kDMA_AddressInterleave2xWidth = 2U, /*!< dma source/destination address interleave 2xwidth */
115     kDMA_AddressInterleave4xWidth = 4U, /*!< dma source/destination address interleave 3xwidth */
116 };
117 
118 /*! @brief _dma_transfer_width dma transfer width */
119 enum
120 {
121     kDMA_Transfer8BitWidth  = 1U, /*!< dma channel transfer bit width is 8 bit */
122     kDMA_Transfer16BitWidth = 2U, /*!< dma channel transfer bit width is 16 bit */
123     kDMA_Transfer32BitWidth = 4U, /*!< dma channel transfer bit width is 32 bit */
124 };
125 
126 /*! @brief DMA descriptor structure */
127 typedef struct _dma_descriptor
128 {
129     volatile uint32_t xfercfg; /*!< Transfer configuration */
130     void *srcEndAddr;          /*!< Last source address of DMA transfer */
131     void *dstEndAddr;          /*!< Last destination address of DMA transfer */
132     void *linkToNextDesc;      /*!< Address of next DMA descriptor in chain */
133 } dma_descriptor_t;
134 
135 /*! @brief DMA transfer configuration */
136 typedef struct _dma_xfercfg
137 {
138     bool valid;             /*!< Descriptor is ready to transfer */
139     bool reload;            /*!< Reload channel configuration register after
140                                  current descriptor is exhausted */
141     bool swtrig;            /*!< Perform software trigger. Transfer if fired
142                                  when 'valid' is set */
143     bool clrtrig;           /*!< Clear trigger */
144     bool intA;              /*!< Raises IRQ when transfer is done and set IRQA status register flag */
145     bool intB;              /*!< Raises IRQ when transfer is done and set IRQB status register flag */
146     uint8_t byteWidth;      /*!< Byte width of data to transfer */
147     uint8_t srcInc;         /*!< Increment source address by 'srcInc' x 'byteWidth' */
148     uint8_t dstInc;         /*!< Increment destination address by 'dstInc' x 'byteWidth' */
149     uint16_t transferCount; /*!< Number of transfers */
150 } dma_xfercfg_t;
151 
152 /*! @brief DMA channel priority */
153 typedef enum _dma_priority
154 {
155     kDMA_ChannelPriority0 = 0, /*!< Highest channel priority - priority 0 */
156     kDMA_ChannelPriority1,     /*!< Channel priority 1 */
157     kDMA_ChannelPriority2,     /*!< Channel priority 2 */
158     kDMA_ChannelPriority3,     /*!< Channel priority 3 */
159     kDMA_ChannelPriority4,     /*!< Channel priority 4 */
160     kDMA_ChannelPriority5,     /*!< Channel priority 5 */
161     kDMA_ChannelPriority6,     /*!< Channel priority 6 */
162     kDMA_ChannelPriority7,     /*!< Lowest channel priority - priority 7 */
163 } dma_priority_t;
164 
165 /*! @brief DMA interrupt flags */
166 typedef enum _dma_int
167 {
168     kDMA_IntA,     /*!< DMA interrupt flag A */
169     kDMA_IntB,     /*!< DMA interrupt flag B */
170     kDMA_IntError, /*!< DMA interrupt flag error */
171 } dma_irq_t;
172 
173 /*! @brief DMA trigger type*/
174 typedef enum _dma_trigger_type
175 {
176     kDMA_NoTrigger        = 0,                                                         /*!< Trigger is disabled */
177     kDMA_LowLevelTrigger  = DMA_CHANNEL_CFG_HWTRIGEN(1) | DMA_CHANNEL_CFG_TRIGTYPE(1), /*!< Low level active trigger */
178     kDMA_HighLevelTrigger = DMA_CHANNEL_CFG_HWTRIGEN(1) | DMA_CHANNEL_CFG_TRIGTYPE(1) |
179                             DMA_CHANNEL_CFG_TRIGPOL(1),    /*!< High level active trigger */
180     kDMA_FallingEdgeTrigger = DMA_CHANNEL_CFG_HWTRIGEN(1), /*!< Falling edge active trigger */
181     kDMA_RisingEdgeTrigger =
182         DMA_CHANNEL_CFG_HWTRIGEN(1) | DMA_CHANNEL_CFG_TRIGPOL(1), /*!< Rising edge active trigger */
183 } dma_trigger_type_t;
184 
185 /*! @brief _dma_burst_size DMA burst size*/
186 enum
187 {
188     kDMA_BurstSize1    = 0U,  /*!< burst size 1 transfer */
189     kDMA_BurstSize2    = 1U,  /*!< burst size 2 transfer */
190     kDMA_BurstSize4    = 2U,  /*!< burst size 4 transfer */
191     kDMA_BurstSize8    = 3U,  /*!< burst size 8 transfer */
192     kDMA_BurstSize16   = 4U,  /*!< burst size 16 transfer */
193     kDMA_BurstSize32   = 5U,  /*!< burst size 32 transfer */
194     kDMA_BurstSize64   = 6U,  /*!< burst size 64 transfer */
195     kDMA_BurstSize128  = 7U,  /*!< burst size 128 transfer */
196     kDMA_BurstSize256  = 8U,  /*!< burst size 256 transfer */
197     kDMA_BurstSize512  = 9U,  /*!< burst size 512 transfer */
198     kDMA_BurstSize1024 = 10U, /*!< burst size 1024 transfer */
199 };
200 
201 /*! @brief DMA trigger burst */
202 typedef enum _dma_trigger_burst
203 {
204     kDMA_SingleTransfer     = 0,                            /*!< Single transfer */
205     kDMA_LevelBurstTransfer = DMA_CHANNEL_CFG_TRIGBURST(1), /*!< Burst transfer driven by level trigger */
206     kDMA_EdgeBurstTransfer1 = DMA_CHANNEL_CFG_TRIGBURST(1), /*!< Perform 1 transfer by edge trigger */
207     kDMA_EdgeBurstTransfer2 =
208         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(1), /*!< Perform 2 transfers by edge trigger */
209     kDMA_EdgeBurstTransfer4 =
210         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(2), /*!< Perform 4 transfers by edge trigger */
211     kDMA_EdgeBurstTransfer8 =
212         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(3), /*!< Perform 8 transfers by edge trigger */
213     kDMA_EdgeBurstTransfer16 =
214         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(4), /*!< Perform 16 transfers by edge trigger */
215     kDMA_EdgeBurstTransfer32 =
216         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(5), /*!< Perform 32 transfers by edge trigger */
217     kDMA_EdgeBurstTransfer64 =
218         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(6), /*!< Perform 64 transfers by edge trigger */
219     kDMA_EdgeBurstTransfer128 =
220         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(7), /*!< Perform 128 transfers by edge trigger */
221     kDMA_EdgeBurstTransfer256 =
222         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(8), /*!< Perform 256 transfers by edge trigger */
223     kDMA_EdgeBurstTransfer512 =
224         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(9), /*!< Perform 512 transfers by edge trigger */
225     kDMA_EdgeBurstTransfer1024 =
226         DMA_CHANNEL_CFG_TRIGBURST(1) | DMA_CHANNEL_CFG_BURSTPOWER(10), /*!< Perform 1024 transfers by edge trigger */
227 } dma_trigger_burst_t;
228 
229 /*! @brief DMA burst wrapping */
230 typedef enum _dma_burst_wrap
231 {
232     kDMA_NoWrap        = 0,                               /*!< Wrapping is disabled */
233     kDMA_SrcWrap       = DMA_CHANNEL_CFG_SRCBURSTWRAP(1), /*!< Wrapping is enabled for source */
234     kDMA_DstWrap       = DMA_CHANNEL_CFG_DSTBURSTWRAP(1), /*!< Wrapping is enabled for destination */
235     kDMA_SrcAndDstWrap = DMA_CHANNEL_CFG_SRCBURSTWRAP(1) |
236                          DMA_CHANNEL_CFG_DSTBURSTWRAP(1), /*!< Wrapping is enabled for source and destination */
237 } dma_burst_wrap_t;
238 
239 /*! @brief DMA transfer type */
240 typedef enum _dma_transfer_type
241 {
242     kDMA_MemoryToMemory = 0x0U, /*!< Transfer from memory to memory (increment source and destination) */
243     kDMA_PeripheralToMemory,    /*!< Transfer from peripheral to memory (increment only destination) */
244     kDMA_MemoryToPeripheral,    /*!< Transfer from memory to peripheral (increment only source)*/
245     kDMA_StaticToStatic,        /*!< Peripheral to static memory (do not increment source or destination) */
246 } dma_transfer_type_t;
247 
248 /*! @brief DMA channel trigger */
249 typedef struct _dma_channel_trigger
250 {
251     dma_trigger_type_t type;   /*!< Select hardware trigger as edge triggered or level triggered. */
252     dma_trigger_burst_t burst; /*!< Select whether hardware triggers cause a single or burst transfer. */
253     dma_burst_wrap_t wrap;     /*!< Select wrap type, source wrap or dest wrap, or both. */
254 } dma_channel_trigger_t;
255 
256 /*! @brief DMA channel trigger */
257 typedef struct _dma_channel_config
258 {
259     void *srcStartAddr;             /*!< Source data address */
260     void *dstStartAddr;             /*!< Destination data address */
261     void *nextDesc;                 /*!< Chain custom descriptor */
262     uint32_t xferCfg;               /*!< channel transfer configurations */
263     dma_channel_trigger_t *trigger; /*!< DMA trigger type */
264     bool isPeriph;                  /*!< select the request type */
265 } dma_channel_config_t;
266 
267 /*! @brief DMA transfer configuration */
268 typedef struct _dma_transfer_config
269 {
270     uint8_t *srcAddr;      /*!< Source data address */
271     uint8_t *dstAddr;      /*!< Destination data address */
272     uint8_t *nextDesc;     /*!< Chain custom descriptor */
273     dma_xfercfg_t xfercfg; /*!< Transfer options */
274     bool isPeriph;         /*!< DMA transfer is driven by peripheral */
275 } dma_transfer_config_t;
276 
277 /*! @brief Callback for DMA */
278 struct _dma_handle;
279 
280 /*! @brief Define Callback function for DMA. */
281 typedef void (*dma_callback)(struct _dma_handle *handle, void *userData, bool transferDone, uint32_t intmode);
282 
283 /*! @brief DMA transfer handle structure */
284 typedef struct _dma_handle
285 {
286     dma_callback callback; /*!< Callback function. Invoked when transfer
287                                of descriptor with interrupt flag finishes */
288     void *userData;        /*!< Callback function parameter */
289     DMA_Type *base;        /*!< DMA peripheral base address */
290     uint8_t channel;       /*!< DMA channel number */
291 } dma_handle_t;
292 
293 /*******************************************************************************
294  * APIs
295  ******************************************************************************/
296 #if defined(__cplusplus)
297 extern "C" {
298 #endif /* __cplusplus */
299 
300 /*!
301  * @name DMA initialization and De-initialization
302  * @{
303  */
304 
305 /*!
306  * @brief Initializes DMA peripheral.
307  *
308  * This function enable the DMA clock, set descriptor table and
309  * enable DMA peripheral.
310  *
311  * @param base DMA peripheral base address.
312  */
313 void DMA_Init(DMA_Type *base);
314 
315 /*!
316  * @brief Deinitializes DMA peripheral.
317  *
318  * This function gates the DMA clock.
319  *
320  * @param base DMA peripheral base address.
321  */
322 void DMA_Deinit(DMA_Type *base);
323 
324 /*!
325  * @brief Install DMA descriptor memory.
326  *
327  * This function used to register DMA descriptor memory for linked transfer, a typical case is ping pong
328  * transfer which will request more than one DMA descriptor memory space, althrough current DMA driver has
329  * a default DMA descriptor buffer, but it support one DMA descriptor for one channel only.
330  *
331  * @param base DMA base address.
332  * @param addr DMA descriptor address
333  */
334 void DMA_InstallDescriptorMemory(DMA_Type *base, void *addr);
335 
336 /* @} */
337 
338 /*!
339  * @name DMA Channel Operation
340  * @{
341  */
342 
343 /*!
344  * @brief Return whether DMA channel is processing transfer
345  *
346  * @param base DMA peripheral base address.
347  * @param channel DMA channel number.
348  * @return True for active state, false otherwise.
349  */
DMA_ChannelIsActive(DMA_Type * base,uint32_t channel)350 static inline bool DMA_ChannelIsActive(DMA_Type *base, uint32_t channel)
351 {
352     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
353            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
354 
355     return (DMA_COMMON_CONST_REG_GET(base, channel, ACTIVE) & (1UL << DMA_CHANNEL_INDEX(base, channel))) != 0UL;
356 }
357 
358 /*!
359  * @brief Return whether DMA channel is busy
360  *
361  * @param base DMA peripheral base address.
362  * @param channel DMA channel number.
363  * @return True for busy state, false otherwise.
364  */
DMA_ChannelIsBusy(DMA_Type * base,uint32_t channel)365 static inline bool DMA_ChannelIsBusy(DMA_Type *base, uint32_t channel)
366 {
367     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
368            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
369 
370     return (DMA_COMMON_CONST_REG_GET(base, channel, BUSY) & (1UL << DMA_CHANNEL_INDEX(base, channel))) != 0UL;
371 }
372 
373 /*!
374  * @brief Enables the interrupt source for the DMA transfer.
375  *
376  * @param base DMA peripheral base address.
377  * @param channel DMA channel number.
378  */
DMA_EnableChannelInterrupts(DMA_Type * base,uint32_t channel)379 static inline void DMA_EnableChannelInterrupts(DMA_Type *base, uint32_t channel)
380 {
381     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
382            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
383     DMA_COMMON_REG_GET(base, channel, INTENSET) |= 1UL << DMA_CHANNEL_INDEX(base, channel);
384 }
385 
386 /*!
387  * @brief Disables the interrupt source for the DMA transfer.
388  *
389  * @param base DMA peripheral base address.
390  * @param channel DMA channel number.
391  */
DMA_DisableChannelInterrupts(DMA_Type * base,uint32_t channel)392 static inline void DMA_DisableChannelInterrupts(DMA_Type *base, uint32_t channel)
393 {
394     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
395            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
396     DMA_COMMON_REG_GET(base, channel, INTENCLR) |= 1UL << DMA_CHANNEL_INDEX(base, channel);
397 }
398 
399 /*!
400  * @brief Enable DMA channel.
401  *
402  * @param base DMA peripheral base address.
403  * @param channel DMA channel number.
404  */
DMA_EnableChannel(DMA_Type * base,uint32_t channel)405 static inline void DMA_EnableChannel(DMA_Type *base, uint32_t channel)
406 {
407     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
408            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
409     DMA_COMMON_REG_GET(base, channel, ENABLESET) |= 1UL << DMA_CHANNEL_INDEX(base, channel);
410 }
411 
412 /*!
413  * @brief Disable DMA channel.
414  *
415  * @param base DMA peripheral base address.
416  * @param channel DMA channel number.
417  */
DMA_DisableChannel(DMA_Type * base,uint32_t channel)418 static inline void DMA_DisableChannel(DMA_Type *base, uint32_t channel)
419 {
420     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
421            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
422     DMA_COMMON_REG_GET(base, channel, ENABLECLR) |= 1UL << DMA_CHANNEL_INDEX(base, channel);
423 }
424 
425 /*!
426  * @brief Set PERIPHREQEN of channel configuration register.
427  *
428  * @param base DMA peripheral base address.
429  * @param channel DMA channel number.
430  */
DMA_EnableChannelPeriphRq(DMA_Type * base,uint32_t channel)431 static inline void DMA_EnableChannelPeriphRq(DMA_Type *base, uint32_t channel)
432 {
433     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
434            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
435     base->CHANNEL[channel].CFG |= DMA_CHANNEL_CFG_PERIPHREQEN_MASK;
436 }
437 
438 /*!
439  * @brief Get PERIPHREQEN value of channel configuration register.
440  *
441  * @param base DMA peripheral base address.
442  * @param channel DMA channel number.
443  * @return True for enabled PeriphRq, false for disabled.
444  */
DMA_DisableChannelPeriphRq(DMA_Type * base,uint32_t channel)445 static inline void DMA_DisableChannelPeriphRq(DMA_Type *base, uint32_t channel)
446 {
447     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
448            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
449     base->CHANNEL[channel].CFG &= ~DMA_CHANNEL_CFG_PERIPHREQEN_MASK;
450 }
451 
452 /*!
453  * @brief Set trigger settings of DMA channel.
454  * @deprecated Do not use this function.  It has been superceded by @ref DMA_SetChannelConfig.
455  *
456  * @param base DMA peripheral base address.
457  * @param channel DMA channel number.
458  * @param trigger trigger configuration.
459  */
460 void DMA_ConfigureChannelTrigger(DMA_Type *base, uint32_t channel, dma_channel_trigger_t *trigger);
461 
462 /*!
463  * @brief set channel config.
464  *
465  * This function provide a interface to configure channel configuration reisters.
466  *
467  * @param base DMA base address.
468  * @param channel DMA channel number.
469  * @param trigger channel configurations structure.
470  * @param isPeriph true is periph request, false is not.
471  */
472 void DMA_SetChannelConfig(DMA_Type *base, uint32_t channel, dma_channel_trigger_t *trigger, bool isPeriph);
473 
474 /*! @brief DMA channel xfer transfer configurations
475  *
476  * @param reload true is reload link descriptor after current exhaust, false is not
477  * @param clrTrig true is clear trigger status, wait software trigger, false is not
478  * @param intA enable interruptA
479  * @param intB enable interruptB
480  * @param width transfer width
481  * @param srcInc source address interleave size
482  * @param dstInc destination address interleave size
483  * @param bytes transfer bytes
484  * @return The vaule of xfer config
485  */
DMA_SetChannelXferConfig(bool reload,bool clrTrig,bool intA,bool intB,uint8_t width,uint8_t srcInc,uint8_t dstInc,uint32_t bytes)486 static inline uint32_t DMA_SetChannelXferConfig(
487     bool reload, bool clrTrig, bool intA, bool intB, uint8_t width, uint8_t srcInc, uint8_t dstInc, uint32_t bytes)
488 {
489     return (DMA_CHANNEL_XFERCFG_CFGVALID_MASK | DMA_CHANNEL_XFERCFG_RELOAD(reload) |
490             DMA_CHANNEL_XFERCFG_CLRTRIG(clrTrig) | DMA_CHANNEL_XFERCFG_SETINTA(intA) |
491             DMA_CHANNEL_XFERCFG_SETINTB(intB) |
492             DMA_CHANNEL_XFERCFG_WIDTH((uint32_t)width == 4UL ? 2UL : ((uint32_t)width - 1UL)) |
493             DMA_CHANNEL_XFERCFG_SRCINC((uint32_t)srcInc == 4UL ? ((uint32_t)srcInc - 1UL) : (uint32_t)srcInc) |
494             DMA_CHANNEL_XFERCFG_DSTINC((uint32_t)dstInc == 4UL ? ((uint32_t)dstInc - 1UL) : (uint32_t)dstInc) |
495             DMA_CHANNEL_XFERCFG_XFERCOUNT((uint32_t)bytes / (uint32_t)width - 1UL));
496 }
497 
498 /*!
499  * @brief Gets the remaining bytes of the current DMA descriptor transfer.
500  *
501  * @param base DMA peripheral base address.
502  * @param channel DMA channel number.
503  * @return The number of bytes which have not been transferred yet.
504  */
505 uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel);
506 
507 /*!
508  * @brief Set priority of channel configuration register.
509  *
510  * @param base DMA peripheral base address.
511  * @param channel DMA channel number.
512  * @param priority Channel priority value.
513  */
DMA_SetChannelPriority(DMA_Type * base,uint32_t channel,dma_priority_t priority)514 static inline void DMA_SetChannelPriority(DMA_Type *base, uint32_t channel, dma_priority_t priority)
515 {
516     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
517            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
518     base->CHANNEL[channel].CFG =
519         (base->CHANNEL[channel].CFG & (~(DMA_CHANNEL_CFG_CHPRIORITY_MASK))) | DMA_CHANNEL_CFG_CHPRIORITY(priority);
520 }
521 
522 /*!
523  * @brief Get priority of channel configuration register.
524  *
525  * @param base DMA peripheral base address.
526  * @param channel DMA channel number.
527  * @return Channel priority value.
528  */
DMA_GetChannelPriority(DMA_Type * base,uint32_t channel)529 static inline dma_priority_t DMA_GetChannelPriority(DMA_Type *base, uint32_t channel)
530 {
531     assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
532            (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
533     return (dma_priority_t)(uint8_t)((base->CHANNEL[channel].CFG & DMA_CHANNEL_CFG_CHPRIORITY_MASK) >>
534                                      DMA_CHANNEL_CFG_CHPRIORITY_SHIFT);
535 }
536 
537 /*!
538  * @brief Set channel configuration valid.
539  *
540  * @param base DMA peripheral base address.
541  * @param channel DMA channel number.
542  */
DMA_SetChannelConfigValid(DMA_Type * base,uint32_t channel)543 static inline void DMA_SetChannelConfigValid(DMA_Type *base, uint32_t channel)
544 {
545     base->CHANNEL[channel].XFERCFG |= DMA_CHANNEL_XFERCFG_CFGVALID_MASK;
546 }
547 
548 /*!
549  * @brief Do software trigger for the channel.
550  *
551  * @param base DMA peripheral base address.
552  * @param channel DMA channel number.
553  */
DMA_DoChannelSoftwareTrigger(DMA_Type * base,uint32_t channel)554 static inline void DMA_DoChannelSoftwareTrigger(DMA_Type *base, uint32_t channel)
555 {
556     base->CHANNEL[channel].XFERCFG |= DMA_CHANNEL_XFERCFG_SWTRIG_MASK;
557 }
558 
559 /*!
560  * @brief Load channel transfer configurations.
561  *
562  * @param base DMA peripheral base address.
563  * @param channel DMA channel number.
564  * @param xfer transfer configurations.
565  */
DMA_LoadChannelTransferConfig(DMA_Type * base,uint32_t channel,uint32_t xfer)566 static inline void DMA_LoadChannelTransferConfig(DMA_Type *base, uint32_t channel, uint32_t xfer)
567 {
568     base->CHANNEL[channel].XFERCFG = xfer;
569 }
570 
571 /*!
572  * @brief Create application specific DMA descriptor
573  *        to be used in a chain in transfer
574  * @deprecated Do not use this function.  It has been superceded by @ref DMA_SetupDescriptor.
575  * @param desc DMA descriptor address.
576  * @param xfercfg Transfer configuration for DMA descriptor.
577  * @param srcAddr Address of last item to transmit
578  * @param dstAddr Address of last item to receive.
579  * @param nextDesc Address of next descriptor in chain.
580  */
581 void DMA_CreateDescriptor(dma_descriptor_t *desc, dma_xfercfg_t *xfercfg, void *srcAddr, void *dstAddr, void *nextDesc);
582 
583 /*!
584  * @brief setup dma descriptor
585  *
586  * Note: This function do not support configure wrap descriptor.
587  *
588  * @param desc DMA descriptor address.
589  * @param xfercfg Transfer configuration for DMA descriptor.
590  * @param srcStartAddr Start address of source address.
591  * @param dstStartAddr Start address of destination address.
592  * @param nextDesc Address of next descriptor in chain.
593  */
594 void DMA_SetupDescriptor(
595     dma_descriptor_t *desc, uint32_t xfercfg, void *srcStartAddr, void *dstStartAddr, void *nextDesc);
596 
597 /*!
598  * @brief setup dma channel descriptor
599  *
600  * Note: This function support configure wrap descriptor.
601  *
602  * @param desc DMA descriptor address.
603  * @param xfercfg Transfer configuration for DMA descriptor.
604  * @param srcStartAddr Start address of source address.
605  * @param dstStartAddr Start address of destination address.
606  * @param nextDesc Address of next descriptor in chain.
607  * @param wrapType burst wrap type.
608  * @param burstSize burst size, reference _dma_burst_size.
609  */
610 void DMA_SetupChannelDescriptor(dma_descriptor_t *desc,
611                                 uint32_t xfercfg,
612                                 void *srcStartAddr,
613                                 void *dstStartAddr,
614                                 void *nextDesc,
615                                 dma_burst_wrap_t wrapType,
616                                 uint32_t burstSize);
617 
618 /*!
619  * @brief load channel transfer decriptor.
620  *
621  * This function can be used to load desscriptor to driver internal channel descriptor that is used to start DMA
622  * transfer, the head descriptor table is defined in DMA driver, it is useful for the case:
623  * 1. for the polling transfer, application can allocate a local descriptor memory table to prepare a descriptor firstly
624  * and then call this api to load the configured descriptor to driver descriptor table.
625  * @code
626  *   DMA_Init(DMA0);
627  *   DMA_EnableChannel(DMA0, DEMO_DMA_CHANNEL);
628  *   DMA_SetupDescriptor(desc, xferCfg, s_srcBuffer, &s_destBuffer[0], NULL);
629  *   DMA_LoadChannelDescriptor(DMA0, DEMO_DMA_CHANNEL, (dma_descriptor_t *)desc);
630  *   DMA_DoChannelSoftwareTrigger(DMA0, DEMO_DMA_CHANNEL);
631  *   while(DMA_ChannelIsBusy(DMA0, DEMO_DMA_CHANNEL))
632  *   {}
633  * @endcode
634  *
635  * @param base DMA base address.
636  * @param channel DMA channel.
637  * @param descriptor configured DMA descriptor.
638  */
639 void DMA_LoadChannelDescriptor(DMA_Type *base, uint32_t channel, dma_descriptor_t *descriptor);
640 
641 /* @} */
642 
643 /*!
644  * @name DMA Transactional Operation
645  * @{
646  */
647 
648 /*!
649  * @brief Abort running transfer by handle.
650  *
651  * This function aborts DMA transfer specified by handle.
652  *
653  * @param handle DMA handle pointer.
654  */
655 void DMA_AbortTransfer(dma_handle_t *handle);
656 
657 /*!
658  * @brief Creates the DMA handle.
659  *
660  * This function is called if using transaction API for DMA. This function
661  * initializes the internal state of DMA handle.
662  *
663  * @param handle DMA handle pointer. The DMA handle stores callback function and
664  *               parameters.
665  * @param base DMA peripheral base address.
666  * @param channel DMA channel number.
667  */
668 void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel);
669 
670 /*!
671  * @brief Installs a callback function for the DMA transfer.
672  *
673  * This callback is called in DMA IRQ handler. Use the callback to do something after
674  * the current major loop transfer completes.
675  *
676  * @param handle DMA handle pointer.
677  * @param callback DMA callback function pointer.
678  * @param userData Parameter for callback function.
679  */
680 void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData);
681 
682 /*!
683  * @brief Prepares the DMA transfer structure.
684  * @deprecated Do not use this function.  It has been superceded by @ref DMA_PrepareChannelTransfer.
685  * This function prepares the transfer configuration structure according to the user input.
686  *
687  * @param config The user configuration structure of type dma_transfer_t.
688  * @param srcAddr DMA transfer source address.
689  * @param dstAddr DMA transfer destination address.
690  * @param byteWidth DMA transfer destination address width(bytes).
691  * @param transferBytes DMA transfer bytes to be transferred.
692  * @param type DMA transfer type.
693  * @param nextDesc Chain custom descriptor to transfer.
694  * @note The data address and the data width must be consistent. For example, if the SRC
695  *       is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in
696  *       source address error(SAE).
697  */
698 void DMA_PrepareTransfer(dma_transfer_config_t *config,
699                          void *srcAddr,
700                          void *dstAddr,
701                          uint32_t byteWidth,
702                          uint32_t transferBytes,
703                          dma_transfer_type_t type,
704                          void *nextDesc);
705 
706 /*!
707  * @brief Prepare channel transfer configurations.
708  *
709  * This function used to prepare channel transfer configurations.
710  *
711  * @param config Pointer to DMA channel transfer configuration structure.
712  * @param srcStartAddr source start address.
713  * @param dstStartAddr destination start address.
714  * @param xferCfg xfer configuration, user can reference DMA_CHANNEL_XFER about to how to get xferCfg value.
715  * @param type transfer type.
716  * @param trigger DMA channel trigger configurations.
717  * @param nextDesc address of next descriptor.
718  */
719 void DMA_PrepareChannelTransfer(dma_channel_config_t *config,
720                                 void *srcStartAddr,
721                                 void *dstStartAddr,
722                                 uint32_t xferCfg,
723                                 dma_transfer_type_t type,
724                                 dma_channel_trigger_t *trigger,
725                                 void *nextDesc);
726 
727 /*!
728  * @brief Submits the DMA transfer request.
729  * @deprecated Do not use this function.  It has been superceded by @ref DMA_SubmitChannelTransfer.
730  *
731  * This function submits the DMA transfer request according to the transfer configuration structure.
732  * If the user submits the transfer request repeatedly, this function packs an unprocessed request as
733  * a TCD and enables scatter/gather feature to process it in the next time.
734  *
735  * @param handle DMA handle pointer.
736  * @param config Pointer to DMA transfer configuration structure.
737  * @retval kStatus_DMA_Success It means submit transfer request succeed.
738  * @retval kStatus_DMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
739  * @retval kStatus_DMA_Busy It means the given channel is busy, need to submit request later.
740  */
741 status_t DMA_SubmitTransfer(dma_handle_t *handle, dma_transfer_config_t *config);
742 
743 /*!
744  * @brief Submit channel transfer paramter directly.
745  *
746  * This function used to configue channel head descriptor that is used to start DMA transfer, the head descriptor table
747  * is defined in DMA driver, it is useful for the case:
748  * 1. for the single transfer, application doesn't need to allocate descriptor table, the head descriptor can be used
749  for it.
750  * @code
751     DMA_SetChannelConfig(base, channel, trigger, isPeriph);
752     DMA_CreateHandle(handle, base, channel)
753     DMA_SubmitChannelTransferParameter(handle, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc,
754  bytes), srcStartAddr, dstStartAddr, NULL);
755     DMA_StartTransfer(handle)
756  * @endcode
757  *
758  * 2. for the linked transfer, application should responsible for link descriptor, for example, if 4 transfer is
759  required, then application should prepare
760  *  three descriptor table with macro , the head descriptor in driver can be used for the first transfer descriptor.
761  * @code
762     define link descriptor table in application with macro
763     DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc[3]);
764 
765     DMA_SetupDescriptor(nextDesc0,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
766  srcStartAddr, dstStartAddr, nextDesc1);
767     DMA_SetupDescriptor(nextDesc1,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
768  srcStartAddr, dstStartAddr, nextDesc2);
769     DMA_SetupDescriptor(nextDesc2,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
770  srcStartAddr, dstStartAddr, NULL);
771     DMA_SetChannelConfig(base, channel, trigger, isPeriph);
772     DMA_CreateHandle(handle, base, channel)
773     DMA_SubmitChannelTransferParameter(handle, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc,
774  bytes), srcStartAddr, dstStartAddr, nextDesc0);
775     DMA_StartTransfer(handle);
776  * @endcode
777  *
778  * @param handle Pointer to DMA handle.
779  * @param xferCfg xfer configuration, user can reference DMA_CHANNEL_XFER about to how to get xferCfg value.
780  * @param srcStartAddr source start address.
781  * @param dstStartAddr destination start address.
782  * @param nextDesc address of next descriptor.
783  */
784 void DMA_SubmitChannelTransferParameter(
785     dma_handle_t *handle, uint32_t xferCfg, void *srcStartAddr, void *dstStartAddr, void *nextDesc);
786 
787 /*!
788  * @brief Submit channel descriptor.
789  *
790  * This function used to configue channel head descriptor that is used to start DMA transfer, the head descriptor table
791  is defined in
792  * DMA driver, this functiono is typical for the ping pong case:
793  *
794  * 1. for the ping pong case, application should responsible for the descriptor, for example, application should
795  * prepare two descriptor table with macro.
796  * @code
797     define link descriptor table in application with macro
798     DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc[2]);
799 
800     DMA_SetupDescriptor(nextDesc0,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
801  srcStartAddr, dstStartAddr, nextDesc1);
802     DMA_SetupDescriptor(nextDesc1,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
803  srcStartAddr, dstStartAddr, nextDesc0);
804     DMA_SetChannelConfig(base, channel, trigger, isPeriph);
805     DMA_CreateHandle(handle, base, channel)
806     DMA_SubmitChannelDescriptor(handle,  nextDesc0);
807     DMA_StartTransfer(handle);
808  * @endcode
809  *
810  * @param handle Pointer to DMA handle.
811  * @param descriptor descriptor to submit.
812  */
813 void DMA_SubmitChannelDescriptor(dma_handle_t *handle, dma_descriptor_t *descriptor);
814 
815 /*!
816  * @brief Submits the DMA channel transfer request.
817  *
818  * This function submits the DMA transfer request according to the transfer configuration structure.
819  * If the user submits the transfer request repeatedly, this function packs an unprocessed request as
820  * a TCD and enables scatter/gather feature to process it in the next time.
821  * It is used for the case:
822  * 1. for the single transfer, application doesn't need to allocate descriptor table, the head descriptor can be used
823  for it.
824  * @code
825     DMA_CreateHandle(handle, base, channel)
826     DMA_PrepareChannelTransfer(config,srcStartAddr,dstStartAddr,xferCfg,type,trigger,NULL);
827     DMA_SubmitChannelTransfer(handle, config)
828     DMA_StartTransfer(handle)
829  * @endcode
830  *
831  * 2. for the linked transfer, application should responsible for link descriptor, for example, if 4 transfer is
832  required, then application should prepare
833  *  three descriptor table with macro , the head descriptor in driver can be used for the first transfer descriptor.
834  * @code
835     define link descriptor table in application with macro
836     DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc);
837     DMA_SetupDescriptor(nextDesc0,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
838  srcStartAddr, dstStartAddr, nextDesc1);
839     DMA_SetupDescriptor(nextDesc1,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
840  srcStartAddr, dstStartAddr, nextDesc2);
841     DMA_SetupDescriptor(nextDesc2,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
842  srcStartAddr, dstStartAddr, NULL);
843     DMA_CreateHandle(handle, base, channel)
844     DMA_PrepareChannelTransfer(config,srcStartAddr,dstStartAddr,xferCfg,type,trigger,nextDesc0);
845     DMA_SubmitChannelTransfer(handle, config)
846     DMA_StartTransfer(handle)
847  * @endcode
848  *
849  * 3. for the ping pong case, application should responsible for link descriptor, for example, application should
850  prepare
851  *  two descriptor table with macro , the head descriptor in driver can be used for the first transfer descriptor.
852  * @code
853     define link descriptor table in application with macro
854     DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc);
855 
856     DMA_SetupDescriptor(nextDesc0,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
857  srcStartAddr, dstStartAddr, nextDesc1);
858     DMA_SetupDescriptor(nextDesc1,  DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
859  srcStartAddr, dstStartAddr, nextDesc0);
860     DMA_CreateHandle(handle, base, channel)
861     DMA_PrepareChannelTransfer(config,srcStartAddr,dstStartAddr,xferCfg,type,trigger,nextDesc0);
862     DMA_SubmitChannelTransfer(handle, config)
863     DMA_StartTransfer(handle)
864  * @endcode
865  * @param handle DMA handle pointer.
866  * @param config Pointer to DMA transfer configuration structure.
867  * @retval kStatus_DMA_Success It means submit transfer request succeed.
868  * @retval kStatus_DMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
869  * @retval kStatus_DMA_Busy It means the given channel is busy, need to submit request later.
870  */
871 status_t DMA_SubmitChannelTransfer(dma_handle_t *handle, dma_channel_config_t *config);
872 
873 /*!
874  * @brief DMA start transfer.
875  *
876  * This function enables the channel request. User can call this function after submitting the transfer request
877  * It will trigger transfer start with software trigger only when hardware trigger is not used.
878  *
879  * @param handle DMA handle pointer.
880  */
881 void DMA_StartTransfer(dma_handle_t *handle);
882 
883 /*!
884  * @brief DMA IRQ handler for descriptor transfer complete.
885  *
886  * This function clears the channel major interrupt flag and call
887  * the callback function if it is not NULL.
888  *
889  * @param base DMA base address.
890  */
891 void DMA_IRQHandle(DMA_Type *base);
892 
893 /* @} */
894 
895 #if defined(__cplusplus)
896 }
897 #endif /* __cplusplus */
898 
899 /* @} */
900 
901 #endif /*_FSL_DMA_H_*/
902