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