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, 1)) /*!< Version 2.5.1. */
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_SET(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_SET(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_SET(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_SET(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