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, 3)) /*!< Version 2.5.3. */
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 assert(((uint32_t)bytes / (uint32_t)width) <= DMA_MAX_TRANSFER_COUNT);
490 return (DMA_CHANNEL_XFERCFG_CFGVALID_MASK | DMA_CHANNEL_XFERCFG_RELOAD(reload) |
491 DMA_CHANNEL_XFERCFG_CLRTRIG(clrTrig) | DMA_CHANNEL_XFERCFG_SETINTA(intA) |
492 DMA_CHANNEL_XFERCFG_SETINTB(intB) |
493 DMA_CHANNEL_XFERCFG_WIDTH((uint32_t)width == 4UL ? 2UL : ((uint32_t)width - 1UL)) |
494 DMA_CHANNEL_XFERCFG_SRCINC((uint32_t)srcInc == 4UL ? ((uint32_t)srcInc - 1UL) : (uint32_t)srcInc) |
495 DMA_CHANNEL_XFERCFG_DSTINC((uint32_t)dstInc == 4UL ? ((uint32_t)dstInc - 1UL) : (uint32_t)dstInc) |
496 DMA_CHANNEL_XFERCFG_XFERCOUNT((uint32_t)bytes / (uint32_t)width - 1UL));
497 }
498
499 /*!
500 * @brief Gets the remaining bytes of the current DMA descriptor transfer.
501 *
502 * @param base DMA peripheral base address.
503 * @param channel DMA channel number.
504 * @return The number of bytes which have not been transferred yet.
505 */
506 uint32_t DMA_GetRemainingBytes(DMA_Type *base, uint32_t channel);
507
508 /*!
509 * @brief Set priority of channel configuration register.
510 *
511 * @param base DMA peripheral base address.
512 * @param channel DMA channel number.
513 * @param priority Channel priority value.
514 */
DMA_SetChannelPriority(DMA_Type * base,uint32_t channel,dma_priority_t priority)515 static inline void DMA_SetChannelPriority(DMA_Type *base, uint32_t channel, dma_priority_t priority)
516 {
517 assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
518 (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
519 base->CHANNEL[channel].CFG =
520 (base->CHANNEL[channel].CFG & (~(DMA_CHANNEL_CFG_CHPRIORITY_MASK))) | DMA_CHANNEL_CFG_CHPRIORITY(priority);
521 }
522
523 /*!
524 * @brief Get priority of channel configuration register.
525 *
526 * @param base DMA peripheral base address.
527 * @param channel DMA channel number.
528 * @return Channel priority value.
529 */
DMA_GetChannelPriority(DMA_Type * base,uint32_t channel)530 static inline dma_priority_t DMA_GetChannelPriority(DMA_Type *base, uint32_t channel)
531 {
532 assert((FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base) != -1) &&
533 (channel < (uint32_t)FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(base)));
534 return (dma_priority_t)(uint8_t)((base->CHANNEL[channel].CFG & DMA_CHANNEL_CFG_CHPRIORITY_MASK) >>
535 DMA_CHANNEL_CFG_CHPRIORITY_SHIFT);
536 }
537
538 /*!
539 * @brief Set channel configuration valid.
540 *
541 * @param base DMA peripheral base address.
542 * @param channel DMA channel number.
543 */
DMA_SetChannelConfigValid(DMA_Type * base,uint32_t channel)544 static inline void DMA_SetChannelConfigValid(DMA_Type *base, uint32_t channel)
545 {
546 base->CHANNEL[channel].XFERCFG |= DMA_CHANNEL_XFERCFG_CFGVALID_MASK;
547 }
548
549 /*!
550 * @brief Do software trigger for the channel.
551 *
552 * @param base DMA peripheral base address.
553 * @param channel DMA channel number.
554 */
DMA_DoChannelSoftwareTrigger(DMA_Type * base,uint32_t channel)555 static inline void DMA_DoChannelSoftwareTrigger(DMA_Type *base, uint32_t channel)
556 {
557 base->CHANNEL[channel].XFERCFG |= DMA_CHANNEL_XFERCFG_SWTRIG_MASK;
558 }
559
560 /*!
561 * @brief Load channel transfer configurations.
562 *
563 * @param base DMA peripheral base address.
564 * @param channel DMA channel number.
565 * @param xfer transfer configurations.
566 */
DMA_LoadChannelTransferConfig(DMA_Type * base,uint32_t channel,uint32_t xfer)567 static inline void DMA_LoadChannelTransferConfig(DMA_Type *base, uint32_t channel, uint32_t xfer)
568 {
569 base->CHANNEL[channel].XFERCFG = xfer;
570 }
571
572 /*!
573 * @brief Create application specific DMA descriptor
574 * to be used in a chain in transfer
575 * @deprecated Do not use this function. It has been superceded by @ref DMA_SetupDescriptor.
576 * @param desc DMA descriptor address.
577 * @param xfercfg Transfer configuration for DMA descriptor.
578 * @param srcAddr Address of last item to transmit
579 * @param dstAddr Address of last item to receive.
580 * @param nextDesc Address of next descriptor in chain.
581 */
582 void DMA_CreateDescriptor(dma_descriptor_t *desc, dma_xfercfg_t *xfercfg, void *srcAddr, void *dstAddr, void *nextDesc);
583
584 /*!
585 * @brief setup dma descriptor
586 *
587 * Note: This function do not support configure wrap descriptor.
588 *
589 * @param desc DMA descriptor address.
590 * @param xfercfg Transfer configuration for DMA descriptor.
591 * @param srcStartAddr Start address of source address.
592 * @param dstStartAddr Start address of destination address.
593 * @param nextDesc Address of next descriptor in chain.
594 */
595 void DMA_SetupDescriptor(
596 dma_descriptor_t *desc, uint32_t xfercfg, void *srcStartAddr, void *dstStartAddr, void *nextDesc);
597
598 /*!
599 * @brief setup dma channel descriptor
600 *
601 * Note: This function support configure wrap descriptor.
602 *
603 * @param desc DMA descriptor address.
604 * @param xfercfg Transfer configuration for DMA descriptor.
605 * @param srcStartAddr Start address of source address.
606 * @param dstStartAddr Start address of destination address.
607 * @param nextDesc Address of next descriptor in chain.
608 * @param wrapType burst wrap type.
609 * @param burstSize burst size, reference _dma_burst_size.
610 */
611 void DMA_SetupChannelDescriptor(dma_descriptor_t *desc,
612 uint32_t xfercfg,
613 void *srcStartAddr,
614 void *dstStartAddr,
615 void *nextDesc,
616 dma_burst_wrap_t wrapType,
617 uint32_t burstSize);
618
619 /*!
620 * @brief load channel transfer decriptor.
621 *
622 * This function can be used to load desscriptor to driver internal channel descriptor that is used to start DMA
623 * transfer, the head descriptor table is defined in DMA driver, it is useful for the case:
624 * 1. for the polling transfer, application can allocate a local descriptor memory table to prepare a descriptor firstly
625 * and then call this api to load the configured descriptor to driver descriptor table.
626 * @code
627 * DMA_Init(DMA0);
628 * DMA_EnableChannel(DMA0, DEMO_DMA_CHANNEL);
629 * DMA_SetupDescriptor(desc, xferCfg, s_srcBuffer, &s_destBuffer[0], NULL);
630 * DMA_LoadChannelDescriptor(DMA0, DEMO_DMA_CHANNEL, (dma_descriptor_t *)desc);
631 * DMA_DoChannelSoftwareTrigger(DMA0, DEMO_DMA_CHANNEL);
632 * while(DMA_ChannelIsBusy(DMA0, DEMO_DMA_CHANNEL))
633 * {}
634 * @endcode
635 *
636 * @param base DMA base address.
637 * @param channel DMA channel.
638 * @param descriptor configured DMA descriptor.
639 */
640 void DMA_LoadChannelDescriptor(DMA_Type *base, uint32_t channel, dma_descriptor_t *descriptor);
641
642 /*! @} */
643
644 /*!
645 * @name DMA Transactional Operation
646 * @{
647 */
648
649 /*!
650 * @brief Abort running transfer by handle.
651 *
652 * This function aborts DMA transfer specified by handle.
653 *
654 * @param handle DMA handle pointer.
655 */
656 void DMA_AbortTransfer(dma_handle_t *handle);
657
658 /*!
659 * @brief Creates the DMA handle.
660 *
661 * This function is called if using transaction API for DMA. This function
662 * initializes the internal state of DMA handle.
663 *
664 * @param handle DMA handle pointer. The DMA handle stores callback function and
665 * parameters.
666 * @param base DMA peripheral base address.
667 * @param channel DMA channel number.
668 */
669 void DMA_CreateHandle(dma_handle_t *handle, DMA_Type *base, uint32_t channel);
670
671 /*!
672 * @brief Installs a callback function for the DMA transfer.
673 *
674 * This callback is called in DMA IRQ handler. Use the callback to do something after
675 * the current major loop transfer completes.
676 *
677 * @param handle DMA handle pointer.
678 * @param callback DMA callback function pointer.
679 * @param userData Parameter for callback function.
680 */
681 void DMA_SetCallback(dma_handle_t *handle, dma_callback callback, void *userData);
682
683 /*!
684 * @brief Prepares the DMA transfer structure.
685 * @deprecated Do not use this function. It has been superceded by @ref DMA_PrepareChannelTransfer.
686 * This function prepares the transfer configuration structure according to the user input.
687 *
688 * @param config The user configuration structure of type dma_transfer_t.
689 * @param srcAddr DMA transfer source address.
690 * @param dstAddr DMA transfer destination address.
691 * @param byteWidth DMA transfer destination address width(bytes).
692 * @param transferBytes DMA transfer bytes to be transferred.
693 * @param type DMA transfer type.
694 * @param nextDesc Chain custom descriptor to transfer.
695 * @note The data address and the data width must be consistent. For example, if the SRC
696 * is 4 bytes, so the source address must be 4 bytes aligned, or it shall result in
697 * source address error(SAE).
698 */
699 void DMA_PrepareTransfer(dma_transfer_config_t *config,
700 void *srcAddr,
701 void *dstAddr,
702 uint32_t byteWidth,
703 uint32_t transferBytes,
704 dma_transfer_type_t type,
705 void *nextDesc);
706
707 /*!
708 * @brief Prepare channel transfer configurations.
709 *
710 * This function used to prepare channel transfer configurations.
711 *
712 * @param config Pointer to DMA channel transfer configuration structure.
713 * @param srcStartAddr source start address.
714 * @param dstStartAddr destination start address.
715 * @param xferCfg xfer configuration, user can reference DMA_CHANNEL_XFER about to how to get xferCfg value.
716 * @param type transfer type.
717 * @param trigger DMA channel trigger configurations.
718 * @param nextDesc address of next descriptor.
719 */
720 void DMA_PrepareChannelTransfer(dma_channel_config_t *config,
721 void *srcStartAddr,
722 void *dstStartAddr,
723 uint32_t xferCfg,
724 dma_transfer_type_t type,
725 dma_channel_trigger_t *trigger,
726 void *nextDesc);
727
728 /*!
729 * @brief Submits the DMA transfer request.
730 * @deprecated Do not use this function. It has been superceded by @ref DMA_SubmitChannelTransfer.
731 *
732 * This function submits the DMA transfer request according to the transfer configuration structure.
733 * If the user submits the transfer request repeatedly, this function packs an unprocessed request as
734 * a TCD and enables scatter/gather feature to process it in the next time.
735 *
736 * @param handle DMA handle pointer.
737 * @param config Pointer to DMA transfer configuration structure.
738 * @retval kStatus_DMA_Success It means submit transfer request succeed.
739 * @retval kStatus_DMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
740 * @retval kStatus_DMA_Busy It means the given channel is busy, need to submit request later.
741 */
742 status_t DMA_SubmitTransfer(dma_handle_t *handle, dma_transfer_config_t *config);
743
744 /*!
745 * @brief Submit channel transfer paramter directly.
746 *
747 * This function used to configue channel head descriptor that is used to start DMA transfer, the head descriptor table
748 * is defined in DMA driver, it is useful for the case:
749 * 1. for the single transfer, application doesn't need to allocate descriptor table, the head descriptor can be used
750 for it.
751 * @code
752 DMA_SetChannelConfig(base, channel, trigger, isPeriph);
753 DMA_CreateHandle(handle, base, channel)
754 DMA_SubmitChannelTransferParameter(handle, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc,
755 bytes), srcStartAddr, dstStartAddr, NULL);
756 DMA_StartTransfer(handle)
757 * @endcode
758 *
759 * 2. for the linked transfer, application should responsible for link descriptor, for example, if 4 transfer is
760 required, then application should prepare
761 * three descriptor table with macro , the head descriptor in driver can be used for the first transfer descriptor.
762 * @code
763 define link descriptor table in application with macro
764 DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc[3]);
765
766 DMA_SetupDescriptor(nextDesc0, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
767 srcStartAddr, dstStartAddr, nextDesc1);
768 DMA_SetupDescriptor(nextDesc1, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
769 srcStartAddr, dstStartAddr, nextDesc2);
770 DMA_SetupDescriptor(nextDesc2, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
771 srcStartAddr, dstStartAddr, NULL);
772 DMA_SetChannelConfig(base, channel, trigger, isPeriph);
773 DMA_CreateHandle(handle, base, channel)
774 DMA_SubmitChannelTransferParameter(handle, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc,
775 bytes), srcStartAddr, dstStartAddr, nextDesc0);
776 DMA_StartTransfer(handle);
777 * @endcode
778 *
779 * @param handle Pointer to DMA handle.
780 * @param xferCfg xfer configuration, user can reference DMA_CHANNEL_XFER about to how to get xferCfg value.
781 * @param srcStartAddr source start address.
782 * @param dstStartAddr destination start address.
783 * @param nextDesc address of next descriptor.
784 */
785 void DMA_SubmitChannelTransferParameter(
786 dma_handle_t *handle, uint32_t xferCfg, void *srcStartAddr, void *dstStartAddr, void *nextDesc);
787
788 /*!
789 * @brief Submit channel descriptor.
790 *
791 * This function used to configue channel head descriptor that is used to start DMA transfer, the head descriptor table
792 is defined in
793 * DMA driver, this functiono is typical for the ping pong case:
794 *
795 * 1. for the ping pong case, application should responsible for the descriptor, for example, application should
796 * prepare two descriptor table with macro.
797 * @code
798 define link descriptor table in application with macro
799 DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc[2]);
800
801 DMA_SetupDescriptor(nextDesc0, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
802 srcStartAddr, dstStartAddr, nextDesc1);
803 DMA_SetupDescriptor(nextDesc1, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
804 srcStartAddr, dstStartAddr, nextDesc0);
805 DMA_SetChannelConfig(base, channel, trigger, isPeriph);
806 DMA_CreateHandle(handle, base, channel)
807 DMA_SubmitChannelDescriptor(handle, nextDesc0);
808 DMA_StartTransfer(handle);
809 * @endcode
810 *
811 * @param handle Pointer to DMA handle.
812 * @param descriptor descriptor to submit.
813 */
814 void DMA_SubmitChannelDescriptor(dma_handle_t *handle, dma_descriptor_t *descriptor);
815
816 /*!
817 * @brief Submits the DMA channel transfer request.
818 *
819 * This function submits the DMA transfer request according to the transfer configuration structure.
820 * If the user submits the transfer request repeatedly, this function packs an unprocessed request as
821 * a TCD and enables scatter/gather feature to process it in the next time.
822 * It is used for the case:
823 * 1. for the single transfer, application doesn't need to allocate descriptor table, the head descriptor can be used
824 for it.
825 * @code
826 DMA_CreateHandle(handle, base, channel)
827 DMA_PrepareChannelTransfer(config,srcStartAddr,dstStartAddr,xferCfg,type,trigger,NULL);
828 DMA_SubmitChannelTransfer(handle, config)
829 DMA_StartTransfer(handle)
830 * @endcode
831 *
832 * 2. for the linked transfer, application should responsible for link descriptor, for example, if 4 transfer is
833 required, then application should prepare
834 * three descriptor table with macro , the head descriptor in driver can be used for the first transfer descriptor.
835 * @code
836 define link descriptor table in application with macro
837 DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc);
838 DMA_SetupDescriptor(nextDesc0, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
839 srcStartAddr, dstStartAddr, nextDesc1);
840 DMA_SetupDescriptor(nextDesc1, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
841 srcStartAddr, dstStartAddr, nextDesc2);
842 DMA_SetupDescriptor(nextDesc2, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
843 srcStartAddr, dstStartAddr, NULL);
844 DMA_CreateHandle(handle, base, channel)
845 DMA_PrepareChannelTransfer(config,srcStartAddr,dstStartAddr,xferCfg,type,trigger,nextDesc0);
846 DMA_SubmitChannelTransfer(handle, config)
847 DMA_StartTransfer(handle)
848 * @endcode
849 *
850 * 3. for the ping pong case, application should responsible for link descriptor, for example, application should
851 prepare
852 * two descriptor table with macro , the head descriptor in driver can be used for the first transfer descriptor.
853 * @code
854 define link descriptor table in application with macro
855 DMA_ALLOCATE_LINK_DESCRIPTOR(nextDesc);
856
857 DMA_SetupDescriptor(nextDesc0, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
858 srcStartAddr, dstStartAddr, nextDesc1);
859 DMA_SetupDescriptor(nextDesc1, DMA_CHANNEL_XFER(reload, clrTrig, intA, intB, width, srcInc, dstInc, bytes),
860 srcStartAddr, dstStartAddr, nextDesc0);
861 DMA_CreateHandle(handle, base, channel)
862 DMA_PrepareChannelTransfer(config,srcStartAddr,dstStartAddr,xferCfg,type,trigger,nextDesc0);
863 DMA_SubmitChannelTransfer(handle, config)
864 DMA_StartTransfer(handle)
865 * @endcode
866 * @param handle DMA handle pointer.
867 * @param config Pointer to DMA transfer configuration structure.
868 * @retval kStatus_DMA_Success It means submit transfer request succeed.
869 * @retval kStatus_DMA_QueueFull It means TCD queue is full. Submit transfer request is not allowed.
870 * @retval kStatus_DMA_Busy It means the given channel is busy, need to submit request later.
871 */
872 status_t DMA_SubmitChannelTransfer(dma_handle_t *handle, dma_channel_config_t *config);
873
874 /*!
875 * @brief DMA start transfer.
876 *
877 * This function enables the channel request. User can call this function after submitting the transfer request
878 * It will trigger transfer start with software trigger only when hardware trigger is not used.
879 *
880 * @param handle DMA handle pointer.
881 */
882 void DMA_StartTransfer(dma_handle_t *handle);
883
884 /*!
885 * @brief DMA IRQ handler for descriptor transfer complete.
886 *
887 * This function clears the channel major interrupt flag and call
888 * the callback function if it is not NULL.
889 *
890 * @param base DMA base address.
891 */
892 void DMA_IRQHandle(DMA_Type *base);
893
894 /*! @} */
895
896 #if defined(__cplusplus)
897 }
898 #endif /* __cplusplus */
899
900 /*! @} */
901
902 #endif /*FSL_DMA_H_*/
903