1 /***************************************************************************//**
2 * @file
3 * @brief Direct memory access (DMA) module peripheral API
4 * @author Energy Micro AS
5 * @version 3.0.0
6 *******************************************************************************
7 * @section License
8 * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
9 *******************************************************************************
10 *
11 * Permission is granted to anyone to use this software for any purpose,
12 * including commercial applications, and to alter it and redistribute it
13 * freely, subject to the following restrictions:
14 *
15 * 1. The origin of this software must not be misrepresented; you must not
16 * claim that you wrote the original software.
17 * 2. Altered source versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 * 3. This notice may not be removed or altered from any source distribution.
20 *
21 * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
22 * obligation to support this Software. Energy Micro AS is providing the
23 * Software "AS IS", with no express or implied warranties of any kind,
24 * including, but not limited to, any implied warranties of merchantability
25 * or fitness for any particular purpose or warranties against infringement
26 * of any proprietary rights of a third party.
27 *
28 * Energy Micro AS will not be liable for any consequential, incidental, or
29 * special damages, or any other relief, or for any claim by any third party,
30 * arising from your use of this Software.
31 *
32 ******************************************************************************/
33 #include "em_dma.h"
34 #include "em_cmu.h"
35 #include "em_assert.h"
36 #include "em_bitband.h"
37
38 /***************************************************************************//**
39 * @addtogroup EM_Library
40 * @{
41 ******************************************************************************/
42
43 /***************************************************************************//**
44 * @addtogroup DMA
45 * @brief Direct Memory Access (DMA) Peripheral API
46 * @details
47 * These DMA access functions provide basic support for the following
48 * types of DMA cycles:
49 *
50 * @li @b Basic, used for transferring data between memory and peripherals.
51 * @li @b Auto-request, used for transferring data between memory locations.
52 * @li @b Ping-pong, used for for continuous transfer of data between memory
53 * and peripherals, automatically toggling between primary and alternate
54 * descriptors.
55 * @li @b Memory @b scatter-gather, used for transferring a number of buffers
56 * between memory locations.
57 * @li @b Peripheral @b scatter-gather, used for transferring a number of
58 * buffers between memory and peripherals.
59 *
60 * A basic understanding of the DMA controller is assumed. Please refer to
61 * the EFM32 reference manual for further details.
62 *
63 * The term 'descriptor' is used as a synonym to the 'channel control data
64 * structure' term.
65 *
66 * In order to use the DMA controller, the initialization function must have
67 * been executed once (normally during system init):
68 * @verbatim
69 * DMA_Init();
70 * @endverbatim
71 *
72 * Then, normally a user of a DMA channel configures the channel:
73 * @verbatim
74 * DMA_CfgChannel();
75 * @endverbatim
76 *
77 * The channel configuration only has to be done once, if reusing the channel
78 * for the same purpose later.
79 *
80 * In order to set up a DMA cycle, the primary and/or alternate descriptor
81 * has to be set up as indicated below.
82 *
83 * For basic or auto-request cycles, use once on either primary or alternate
84 * descriptor:
85 * @verbatim
86 * DMA_CfgDescr();
87 * @endverbatim
88 *
89 * For ping-pong cycles, configure both primary or alternate descriptors:
90 * @verbatim
91 * DMA_CfgDescr(); // Primary descriptor config
92 * DMA_CfgDescr(); // Alternate descriptor config
93 * @endverbatim
94 *
95 * For scatter-gather cycles, the alternate descriptor array must be programmed:
96 * @verbatim
97 * // 'n' is the number of scattered buffers
98 * // 'descr' points to the start of the alternate descriptor array
99 *
100 * // Fill in 'cfg'
101 * DMA_CfgDescrScatterGather(descr, 0, cfg);
102 * // Fill in 'cfg'
103 * DMA_CfgDescrScatterGather(descr, 1, cfg);
104 * :
105 * // Fill in 'cfg'
106 * DMA_CfgDescrScatterGather(descr, n - 1, cfg);
107 * @endverbatim
108 *
109 * In many cases, the descriptor configuration only has to be done once, if
110 * re-using the channel for the same type of DMA cycles later.
111 *
112 * In order to activate the DMA cycle, use the respective DMA_Activate...()
113 * function.
114 *
115 * For ping-pong DMA cycles, use DMA_RefreshPingPong() from the callback to
116 * prepare the completed descriptor for reuse. Notice that the refresh must
117 * be done prior to the other active descriptor completes, otherwise the
118 * ping-pong DMA cycle will halt.
119 * @{
120 ******************************************************************************/
121
122 /*******************************************************************************
123 ************************** LOCAL FUNCTIONS ********************************
124 ******************************************************************************/
125
126 /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
127
128 /***************************************************************************//**
129 * @brief
130 * Prepare descriptor for DMA cycle.
131 *
132 * @details
133 * This function prepares the last pieces of configuration required to start a
134 * DMA cycle. Since the DMA controller itself modifies some parts of the
135 * descriptor during use, those parts need to be refreshed if reusing a
136 * descriptor configuration.
137 *
138 * @note
139 * If using this function on a descriptor already activated and in use by the
140 * DMA controller, the behaviour is undefined.
141 *
142 * @param[in] channel
143 * DMA channel to prepare for DMA cycle.
144 *
145 * @param[in] cycleCtrl
146 * DMA cycle type to prepare for.
147 *
148 * @param[in] primary
149 * @li true - prepare primary descriptor
150 * @li false - prepare alternate descriptor
151 *
152 * @param[in] useBurst
153 * The burst feature is only used on peripherals supporting DMA bursts.
154 * Bursts must not be used if the total length (as given by nMinus1) is
155 * less than the arbitration rate configured for the descriptor. Please
156 * refer to the reference manual for further details on burst usage.
157 *
158 * @param[in] dst
159 * Address to start location to transfer data to. If NULL, leave setting in
160 * descriptor as is.
161 *
162 * @param[in] src
163 * Address to start location to transfer data from. If NULL, leave setting in
164 * descriptor as is.
165 *
166 * @param[in] nMinus1
167 * Number of elements (minus 1) to transfer (<= 1023).
168 ******************************************************************************/
DMA_Prepare(unsigned int channel,DMA_CycleCtrl_TypeDef cycleCtrl,bool primary,bool useBurst,void * dst,void * src,unsigned int nMinus1)169 static void DMA_Prepare(unsigned int channel,
170 DMA_CycleCtrl_TypeDef cycleCtrl,
171 bool primary,
172 bool useBurst,
173 void *dst,
174 void *src,
175 unsigned int nMinus1)
176 {
177 DMA_DESCRIPTOR_TypeDef *descr;
178 DMA_DESCRIPTOR_TypeDef *primDescr;
179 DMA_CB_TypeDef *cb;
180 uint32_t inc;
181 uint32_t chBit;
182 uint32_t tmp;
183
184 primDescr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
185
186 /* Find descriptor to configure */
187 if (primary)
188 {
189 descr = primDescr;
190 }
191 else
192 {
193 descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
194 }
195
196 /* If callback defined, update info on whether callback is issued */
197 /* for primary or alternate descriptor. Mainly needed for ping-pong */
198 /* cycles. */
199 cb = (DMA_CB_TypeDef *)(primDescr->USER);
200 if (cb)
201 {
202 cb->primary = (uint8_t)primary;
203 }
204
205 if (src)
206 {
207 inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
208 if (inc == _DMA_CTRL_SRC_INC_NONE)
209 {
210 descr->SRCEND = src;
211 }
212 else
213 {
214 descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
215 }
216 }
217
218 if (dst)
219 {
220 inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
221 if (inc == _DMA_CTRL_DST_INC_NONE)
222 {
223 descr->DSTEND = dst;
224 }
225 else
226 {
227 descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
228 }
229 }
230
231 chBit = 1 << channel;
232 if (useBurst)
233 {
234 DMA->CHUSEBURSTS = chBit;
235 }
236 else
237 {
238 DMA->CHUSEBURSTC = chBit;
239 }
240
241 if (primary)
242 {
243 DMA->CHALTC = chBit;
244 }
245 else
246 {
247 DMA->CHALTS = chBit;
248 }
249
250 /* Set cycle control */
251 tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
252 tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
253 tmp |= (uint32_t)cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
254 descr->CTRL = tmp;
255 }
256
257 /** @endcond */
258
259 /*******************************************************************************
260 ************************ INTERRUPT FUNCTIONS ******************************
261 ******************************************************************************/
262
263 /***************************************************************************//**
264 * @brief
265 * Interrupt handler for DMA cycle completion handling.
266 *
267 * @details
268 * Clears any pending flags and calls registered callback (if any).
269 *
270 * If using the default interrupt vector table setup provided, this function
271 * is automatically placed in the IRQ table due to weak linking. If taking
272 * control over the interrupt vector table in some other way, this interrupt
273 * handler must be installed in order to be able to support callback actions.
274 ******************************************************************************/
DMA_IRQHandler(void)275 void DMA_IRQHandler(void)
276 {
277 DMA_DESCRIPTOR_TypeDef *descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
278 int channel;
279 DMA_CB_TypeDef *cb;
280 uint32_t pending;
281 uint32_t pendingPrio;
282 uint32_t prio;
283 uint32_t primaryCpy;
284 int i;
285
286 /* Get all pending interrupts */
287 pending = DMA->IF;
288
289 /* Check for bus error */
290 if (pending & DMA_IF_ERR)
291 {
292 /* Loop here to enable the debugger to see what has happened */
293 while (1)
294 ;
295 }
296
297 /* Process all pending channel interrupts. First process channels */
298 /* defined with high priority, then those with default priority. */
299 prio = DMA->CHPRIS;
300 pendingPrio = pending & prio;
301 for (i = 0; i < 2; i++)
302 {
303 channel = 0;
304 /* Process pending interrupts within high/default priority group */
305 /* honouring priority within group. */
306 while (pendingPrio)
307 {
308 if (pendingPrio & 1)
309 {
310 /* Clear pending interrupt prior to invoking callback, in case it */
311 /* sets up another DMA cycle. */
312 DMA->IFC = 1 << channel;
313
314 /* Normally, no point in enabling interrupt without callback, but */
315 /* check if callback is defined anyway. Callback info is always */
316 /* located in primary descriptor. */
317 cb = (DMA_CB_TypeDef *)(descr[channel].USER);
318 if (cb)
319 {
320 /* Toggle next-descriptor indicator always prior to invoking */
321 /* callback (in case callback reconfigurs something) */
322 primaryCpy = cb->primary;
323 cb->primary ^= 1;
324 if (cb->cbFunc)
325 {
326 cb->cbFunc(channel, (bool)primaryCpy, cb->userPtr);
327 }
328 }
329 }
330
331 pendingPrio >>= 1;
332 channel++;
333 }
334
335 /* On second iteration, process default priority channels */
336 pendingPrio = pending & ~prio;
337 }
338 }
339
340
341 /*******************************************************************************
342 ************************** GLOBAL FUNCTIONS *******************************
343 ******************************************************************************/
344
345 /***************************************************************************//**
346 * @brief
347 * Activate DMA auto-request cycle (used for memory-memory transfers).
348 *
349 * @details
350 * Prior to activating the DMA cycle, the channel and descriptor to be used
351 * must have been properly configured.
352 *
353 * @note
354 * If using this function on a channel already activated and in use by the
355 * DMA controller, the behaviour is undefined.
356 *
357 * @param[in] channel
358 * DMA channel to activate DMA cycle for.
359 *
360 * @param[in] primary
361 * @li true - activate using primary descriptor
362 * @li false - activate using alternate descriptor
363 *
364 * @param[in] dst
365 * Address to start location to transfer data to. If NULL, leave setting in
366 * descriptor as is from a previous activation.
367 *
368 * @param[in] src
369 * Address to start location to transfer data from. If NULL, leave setting in
370 * descriptor as is from a previous activation.
371 *
372 * @param[in] nMinus1
373 * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The
374 * size of the DMA transfer element (1, 2 or 4 bytes) is configured with
375 * DMA_CfgDescr().
376 ******************************************************************************/
DMA_ActivateAuto(unsigned int channel,bool primary,void * dst,void * src,unsigned int nMinus1)377 void DMA_ActivateAuto(unsigned int channel,
378 bool primary,
379 void *dst,
380 void *src,
381 unsigned int nMinus1)
382 {
383 uint32_t chBit;
384
385 EFM_ASSERT(channel < DMA_CHAN_COUNT);
386 EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
387
388 DMA_Prepare(channel,
389 dmaCycleCtrlAuto,
390 primary,
391 false,
392 dst,
393 src,
394 nMinus1);
395
396 chBit = 1 << channel;
397 DMA->CHENS = chBit; /* Enable channel */
398 DMA->CHSWREQ = chBit; /* Activate with SW request */
399 }
400
401
402 /***************************************************************************//**
403 * @brief
404 * Activate DMA basic cycle (used for memory-peripheral transfers).
405 *
406 * @details
407 * Prior to activating the DMA cycle, the channel and descriptor to be used
408 * must have been properly configured.
409 *
410 * @note
411 * If using this function on a channel already activated and in use by the
412 * DMA controller, the behaviour is undefined.
413 *
414 * @param[in] channel
415 * DMA channel to activate DMA cycle for.
416 *
417 * @param[in] primary
418 * @li true - activate using primary descriptor
419 * @li false - activate using alternate descriptor
420 *
421 * @param[in] useBurst
422 * The burst feature is only used on peripherals supporting DMA bursts.
423 * Bursts must not be used if the total length (as given by nMinus1) is
424 * less than the arbitration rate configured for the descriptor. Please
425 * refer to the reference manual for further details on burst usage.
426 *
427 * @param[in] dst
428 * Address to start location to transfer data to. If NULL, leave setting in
429 * descriptor as is from a previous activation.
430 *
431 * @param[in] src
432 * Address to start location to transfer data from. If NULL, leave setting in
433 * descriptor as is from a previous activation.
434 *
435 * @param[in] nMinus1
436 * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The
437 * size of the DMA transfer element (1, 2 or 4 bytes) is configured with
438 * DMA_CfgDescr().
439 ******************************************************************************/
DMA_ActivateBasic(unsigned int channel,bool primary,bool useBurst,void * dst,void * src,unsigned int nMinus1)440 void DMA_ActivateBasic(unsigned int channel,
441 bool primary,
442 bool useBurst,
443 void *dst,
444 void *src,
445 unsigned int nMinus1)
446 {
447 EFM_ASSERT(channel < DMA_CHAN_COUNT);
448 EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
449
450 DMA_Prepare(channel,
451 dmaCycleCtrlBasic,
452 primary,
453 useBurst,
454 dst,
455 src,
456 nMinus1);
457
458 /* Enable channel, request signal is provided by peripheral device */
459 DMA->CHENS = 1 << channel;
460 }
461
462
463 /***************************************************************************//**
464 * @brief
465 * Activate DMA ping-pong cycle (used for memory-peripheral transfers).
466 *
467 * @details
468 * Prior to activating the DMA cycle, the channel and both descriptors must
469 * have been properly configured. The primary descriptor is always the first
470 * descriptor to be used by the DMA controller.
471 *
472 * @note
473 * If using this function on a channel already activated and in use by the
474 * DMA controller, the behaviour is undefined.
475 *
476 * @param[in] channel
477 * DMA channel to activate DMA cycle for.
478 *
479 * @param[in] useBurst
480 * The burst feature is only used on peripherals supporting DMA bursts.
481 * Bursts must not be used if the total length (as given by nMinus1) is
482 * less than the arbitration rate configured for the descriptors. Please
483 * refer to the reference manual for further details on burst usage. Notice
484 * that this setting is used for both the primary and alternate descriptors.
485 *
486 * @param[in] primDst
487 * Address to start location to transfer data to, for primary descriptor.
488 * If NULL, leave setting in descriptor as is from a previous activation.
489 *
490 * @param[in] primSrc
491 * Address to start location to transfer data from, for primary descriptor.
492 * If NULL, leave setting in descriptor as is from a previous activation.
493 *
494 * @param[in] primNMinus1
495 * Number of DMA transfer elements (minus 1) to transfer (<= 1023), for
496 * primary descriptor. The size of the DMA transfer element (1, 2 or 4 bytes)
497 * is configured with DMA_CfgDescr().
498 *
499 * @param[in] altDst
500 * Address to start location to transfer data to, for alternate descriptor.
501 * If NULL, leave setting in descriptor as is from a previous activation.
502 *
503 * @param[in] altSrc
504 * Address to start location to transfer data from, for alternate descriptor.
505 * If NULL, leave setting in descriptor as is from a previous activation.
506 *
507 * @param[in] altNMinus1
508 * Number of DMA transfer elements (minus 1) to transfer (<= 1023), for
509 * alternate descriptor. The size of the DMA transfer element (1, 2 or 4 bytes)
510 * is configured with DMA_CfgDescr().
511 ******************************************************************************/
DMA_ActivatePingPong(unsigned int channel,bool useBurst,void * primDst,void * primSrc,unsigned int primNMinus1,void * altDst,void * altSrc,unsigned int altNMinus1)512 void DMA_ActivatePingPong(unsigned int channel,
513 bool useBurst,
514 void *primDst,
515 void *primSrc,
516 unsigned int primNMinus1,
517 void *altDst,
518 void *altSrc,
519 unsigned int altNMinus1)
520 {
521 EFM_ASSERT(channel < DMA_CHAN_COUNT);
522 EFM_ASSERT(primNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
523 EFM_ASSERT(altNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
524
525 /* Prepare alternate descriptor first */
526 DMA_Prepare(channel,
527 dmaCycleCtrlPingPong,
528 false,
529 useBurst,
530 altDst,
531 altSrc,
532 altNMinus1);
533
534 /* Prepare primary descriptor last in order to start cycle using it */
535 DMA_Prepare(channel,
536 dmaCycleCtrlPingPong,
537 true,
538 useBurst,
539 primDst,
540 primSrc,
541 primNMinus1);
542
543 /* Enable channel, request signal is provided by peripheral device */
544 DMA->CHENS = 1 << channel;
545 }
546
547
548 /***************************************************************************//**
549 * @brief
550 * Activate DMA scatter-gather cycle (used for either memory-peripheral
551 * or memory-memory transfers).
552 *
553 * @details
554 * Prior to activating the DMA cycle, the array with alternate descriptors
555 * must have been properly configured. This function can be reused without
556 * reconfiguring the alternate descriptors, as long as @p count is the same.
557 *
558 * @note
559 * If using this function on a channel already activated and in use by the
560 * DMA controller, the behaviour is undefined.
561 *
562 * @param[in] channel
563 * DMA channel to activate DMA cycle for.
564 *
565 * @param[in] useBurst
566 * The burst feature is only used on peripherals supporting DMA bursts
567 * (and thus this parameter is ignored for memory scatter-gather cycles).
568 * This parameter determines if bursts should be enabled during DMA transfers
569 * using the alternate descriptors. Bursts must not be used if the total
570 * length (as given by nMinus1 for the alternate descriptor) is
571 * less than the arbitration rate configured for the descriptor. Please
572 * refer to the reference manual for further details on burst usage.
573 *
574 * @param[in,out] altDescr
575 * Pointer to start of array with prepared alternate descriptors. The last
576 * descriptor will have its cycle control type reprogrammed to basic type.
577 *
578 * @param[in] count
579 * Number of alternate descriptors in @p altDescr array. Maximum number of
580 * alternate descriptors is 256.
581 ******************************************************************************/
DMA_ActivateScatterGather(unsigned int channel,bool useBurst,DMA_DESCRIPTOR_TypeDef * altDescr,unsigned int count)582 void DMA_ActivateScatterGather(unsigned int channel,
583 bool useBurst,
584 DMA_DESCRIPTOR_TypeDef *altDescr,
585 unsigned int count)
586 {
587 DMA_DESCRIPTOR_TypeDef *descr;
588 DMA_CB_TypeDef *cb;
589 uint32_t cycleCtrl;
590 uint32_t chBit;
591
592 EFM_ASSERT(channel < DMA_CHAN_COUNT);
593 EFM_ASSERT(altDescr);
594 EFM_ASSERT(count && (count <= 256));
595
596 /* We have to configure the primary descriptor properly in order to */
597 /* transfer one complete alternate descriptor from the alternate */
598 /* descriptor table into the actual alternate descriptor. */
599 descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE) + channel;
600
601 /* Set source end address to point to alternate descriptor array */
602 descr->SRCEND = (uint32_t *)altDescr + (count * 4) - 1;
603
604 /* The destination end address in the primary descriptor MUST point */
605 /* to the corresponding alternate descriptor in scatter-gather mode. */
606 descr->DSTEND = (uint32_t *)((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE) +
607 channel + 1) - 1;
608
609 /* The user field of the descriptor is used for callback configuration, */
610 /* and already configured when channel is configured. Do not modify it. */
611
612 /* Determine from alternate configuration whether this is a memory or */
613 /* peripheral scatter-gather, by looking at the first alternate descriptor. */
614 cycleCtrl = altDescr->CTRL & _DMA_CTRL_CYCLE_CTRL_MASK;
615 cycleCtrl &= ~(1 << _DMA_CTRL_CYCLE_CTRL_SHIFT);
616
617 EFM_ASSERT((cycleCtrl == dmaCycleCtrlMemScatterGather) ||
618 (cycleCtrl == dmaCycleCtrlPerScatterGather));
619
620 /* Set last alternate descriptor to basic or auto-request cycle type in */
621 /* order to have dma_done signal asserted when complete. Otherwise interrupt */
622 /* will not be triggered when done. */
623 altDescr[count - 1].CTRL &= ~_DMA_CTRL_CYCLE_CTRL_MASK;
624 if (cycleCtrl == dmaCycleCtrlMemScatterGather)
625 {
626 altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlAuto << _DMA_CTRL_CYCLE_CTRL_SHIFT;
627 }
628 else
629 {
630 altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlBasic << _DMA_CTRL_CYCLE_CTRL_SHIFT;
631 }
632
633 /* If callback defined, update info on whether callback is issued for */
634 /* primary or alternate descriptor. Not really useful for scatter-gather, */
635 /* but do for consistency. Always set to alternate, since that is the last */
636 /* descriptor actually used. */
637 cb = (DMA_CB_TypeDef *)(descr->USER);
638 if (cb)
639 {
640 cb->primary = false;
641 }
642
643 /* Configure primary descriptor control word */
644 descr->CTRL =
645 ((uint32_t)dmaDataInc4 << _DMA_CTRL_DST_INC_SHIFT) |
646 ((uint32_t)dmaDataSize4 << _DMA_CTRL_DST_SIZE_SHIFT) |
647 ((uint32_t)dmaDataInc4 << _DMA_CTRL_SRC_INC_SHIFT) |
648 ((uint32_t)dmaDataSize4 << _DMA_CTRL_SRC_SIZE_SHIFT) |
649 /* Use same protection scheme as for alternate descriptors */
650 (altDescr->CTRL & _DMA_CTRL_SRC_PROT_CTRL_MASK) |
651 ((uint32_t)dmaArbitrate4 << _DMA_CTRL_R_POWER_SHIFT) |
652 (((count * 4) - 1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
653 (((uint32_t)useBurst & 1) << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
654 cycleCtrl;
655
656 chBit = 1 << channel;
657
658 /* Start with primary descriptor */
659 DMA->CHALTC = chBit;
660
661 /* Enable channel */
662 DMA->CHENS = chBit;
663
664 /* Send request if memory scatter-gather, otherwise request signal is */
665 /* provided by peripheral. */
666 if (cycleCtrl == dmaCycleCtrlMemScatterGather)
667 {
668 DMA->CHSWREQ = chBit;
669 }
670 }
671
672
673 /***************************************************************************//**
674 * @brief
675 * Configure a DMA channel.
676 *
677 * @details
678 * Configure miscellaneous issues for a DMA channel. This function is typically
679 * used once to setup a channel for a certain type of use.
680 *
681 * @note
682 * If using this function on a channel already in use by the DMA controller,
683 * the behaviour is undefined.
684 *
685 * @param[in] channel
686 * DMA channel to configure.
687 *
688 * @param[in] cfg
689 * Configuration to use.
690 ******************************************************************************/
DMA_CfgChannel(unsigned int channel,DMA_CfgChannel_TypeDef * cfg)691 void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg)
692 {
693 DMA_DESCRIPTOR_TypeDef *descr;
694
695 EFM_ASSERT(channel < DMA_CHAN_COUNT);
696 EFM_ASSERT(cfg);
697
698 /* Always keep callback configuration reference in primary descriptor */
699 descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
700 descr[channel].USER = (uint32_t)(cfg->cb);
701
702 /* Set to specified priority for channel */
703 if (cfg->highPri)
704 {
705 DMA->CHPRIS = 1 << channel;
706 }
707 else
708 {
709 DMA->CHPRIC = 1 << channel;
710 }
711
712 /* Set DMA signal source select */
713 DMA->CH[channel].CTRL = cfg->select;
714
715 /* Enable/disable interrupt as specified */
716 if (cfg->enableInt)
717 {
718 DMA->IFC = (1 << channel);
719 BITBAND_Peripheral(&(DMA->IEN), channel, 1);
720 }
721 else
722 {
723 BITBAND_Peripheral(&(DMA->IEN), channel, 0);
724 }
725 }
726
727
728 /***************************************************************************//**
729 * @brief
730 * Configure DMA descriptor for auto-request, basic or ping-pong DMA cycles.
731 *
732 * @details
733 * This function is used for configuration of a descriptor for the following
734 * DMA cycle types:
735 *
736 * @li auto-request - used for memory/memory transfer
737 * @li basic - used for a peripheral/memory transfer
738 * @li ping-pong - used for a ping-pong based peripheral/memory transfer
739 * style providing time to refresh one descriptor while the other is
740 * in use.
741 *
742 * The DMA cycle is not activated, please see DMA_ActivateAuto(),
743 * DMA_ActivateBasic() or DMA_ActivatePingPong() to activate the DMA cycle.
744 * In many cases, the configuration only has to be done once, and all
745 * subsequent cycles may be activated with the activate function.
746 *
747 * For ping-pong DMA cycles, this function must be used both on the primary
748 * and the alternate descriptor prior to activating the DMA cycle.
749 *
750 * Notice that the DMA channel must also be configured, see DMA_CfgChannel().
751 *
752 * @note
753 * If using this function on a descriptor already activated and in use by
754 * the DMA controller, the behaviour is undefined.
755 *
756 * @param[in] channel
757 * DMA channel to configure for.
758 *
759 * @param[in] primary
760 * @li true - configure primary descriptor
761 * @li false - configure alternate descriptor
762 *
763 * @param[in] cfg
764 * Configuration to use.
765 ******************************************************************************/
DMA_CfgDescr(unsigned int channel,bool primary,DMA_CfgDescr_TypeDef * cfg)766 void DMA_CfgDescr(unsigned int channel,
767 bool primary,
768 DMA_CfgDescr_TypeDef *cfg)
769 {
770 DMA_DESCRIPTOR_TypeDef *descr;
771
772 EFM_ASSERT(channel < DMA_CHAN_COUNT);
773 EFM_ASSERT(cfg);
774
775 /* Find descriptor to configure */
776 if (primary)
777 {
778 descr = (DMA_DESCRIPTOR_TypeDef *)DMA->CTRLBASE;
779 }
780 else
781 {
782 descr = (DMA_DESCRIPTOR_TypeDef *)DMA->ALTCTRLBASE;
783 }
784 descr += channel;
785
786 /* Prepare the descriptor */
787 /* Source/destination end addresses set when started */
788 descr->CTRL =
789 (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
790 (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
791 (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
792 (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
793 ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
794 (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
795 (0 << _DMA_CTRL_N_MINUS_1_SHIFT) | /* Set when activated */
796 (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) | /* Set when activated */
797 DMA_CTRL_CYCLE_CTRL_INVALID; /* Set when activated */
798 }
799
800
801 #if defined(_EFM32_GIANT_FAMILY)
802 /***************************************************************************//**
803 * @brief Configure DMA channel for Loop mode or 2D transfer.
804 *
805 * @details
806 * For 2D transfer, set cfg->enable to "false", and only configure nMinus1
807 * to same width as channel descriptor.
808 *
809 * @param[in] channel
810 * DMA channel to configure for.
811 *
812 * @param[in] cfg
813 * Configuration to use.
814 ******************************************************************************/
DMA_CfgLoop(unsigned int channel,DMA_CfgLoop_TypeDef * cfg)815 void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg)
816 {
817 EFM_ASSERT(channel <= 1);
818 EFM_ASSERT(cfg->nMinus1 <= 1023);
819
820 /* Configure LOOP setting */
821 switch( channel )
822 {
823 case 0:
824 DMA->LOOP0 = (cfg->enable << _DMA_LOOP0_EN_SHIFT|
825 cfg->nMinus1 << _DMA_LOOP0_WIDTH_SHIFT);
826 break;
827 case 1:
828 DMA->LOOP1 = (cfg->enable << _DMA_LOOP1_EN_SHIFT|
829 cfg->nMinus1 << _DMA_LOOP1_WIDTH_SHIFT);
830 break;
831 }
832 }
833
834
835 /***************************************************************************//**
836 * @brief Configure DMA channel 2D transfer properties.
837 *
838 * @param[in] channel
839 * DMA channel to configure for.
840 *
841 * @param[in] cfg
842 * Configuration to use.
843 ******************************************************************************/
DMA_CfgRect(unsigned int channel,DMA_CfgRect_TypeDef * cfg)844 void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg)
845 {
846 EFM_ASSERT(channel == 0);
847 EFM_ASSERT(cfg->dstStride <= 2047);
848 EFM_ASSERT(cfg->srcStride <= 2047);
849 EFM_ASSERT(cfg->height <= 1023);
850
851 /* Configure rectangular/2D copy */
852 DMA->RECT0 = (cfg->dstStride << _DMA_RECT0_DSTSTRIDE_SHIFT|
853 cfg->srcStride << _DMA_RECT0_SRCSTRIDE_SHIFT|
854 cfg->height << _DMA_RECT0_HEIGHT_SHIFT);
855 }
856 #endif
857
858
859 /***************************************************************************//**
860 * @brief
861 * Configure an alternate DMA descriptor for use with scatter-gather DMA
862 * cycles.
863 *
864 * @details
865 * In scatter-gather mode, the alternate descriptors are located in one
866 * contiguous memory area. Each of the alternate descriptor must be fully
867 * configured prior to starting the scatter-gather DMA cycle.
868 *
869 * The DMA cycle is not activated by this function, please see
870 * DMA_ActivateScatterGather() to activate the DMA cycle. In some cases, the
871 * alternate configuration only has to be done once, and all subsequent
872 * transfers may be activated with the activate function.
873 *
874 * Notice that the DMA channel must also be configured, see DMA_CfgChannel().
875 *
876 * @param[in] descr
877 * Points to start of memory area holding the alternate descriptors.
878 *
879 * @param[in] indx
880 * Alternate descriptor index number to configure (numbered from 0).
881 *
882 * @param[in] cfg
883 * Configuration to use.
884 ******************************************************************************/
DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef * descr,unsigned int indx,DMA_CfgDescrSGAlt_TypeDef * cfg)885 void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr,
886 unsigned int indx,
887 DMA_CfgDescrSGAlt_TypeDef *cfg)
888 {
889 uint32_t cycleCtrl;
890
891 EFM_ASSERT(descr);
892 EFM_ASSERT(cfg);
893
894 /* Point to selected entry in alternate descriptor table */
895 descr += indx;
896
897 if (cfg->srcInc == dmaDataIncNone)
898 {
899 descr->SRCEND = cfg->src;
900 }
901 else
902 {
903 descr->SRCEND = (void *)((uint32_t)(cfg->src) + ((uint32_t)(cfg->nMinus1) << cfg->srcInc));
904 }
905
906 if (cfg->dstInc == dmaDataIncNone)
907 {
908 descr->DSTEND = cfg->dst;
909 }
910 else
911 {
912 descr->DSTEND = (void *)((uint32_t)(cfg->dst) + ((uint32_t)(cfg->nMinus1) << cfg->dstInc));
913 }
914
915 /* User definable part not used */
916 descr->USER = 0;
917
918 if (cfg->peripheral)
919 {
920 cycleCtrl = (uint32_t)dmaCycleCtrlPerScatterGather + 1;
921 }
922 else
923 {
924 cycleCtrl = (uint32_t)dmaCycleCtrlMemScatterGather + 1;
925 }
926
927 descr->CTRL =
928 (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
929 (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
930 (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
931 (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
932 ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
933 (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
934 ((uint32_t)(cfg->nMinus1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
935 /* Never set next useburst bit, since the descriptor used after the */
936 /* alternate descriptor is the primary descriptor which operates on */
937 /* memory. If the alternate descriptors need to have useBurst set, this */
938 /* done when setting up the primary descriptor, ie when activating. */
939 (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
940 (cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT);
941 }
942
943
944 /***************************************************************************//**
945 * @brief
946 * Check if DMA channel is enabled.
947 *
948 * @details
949 * The DMA channel is disabled when the DMA controller has finished a DMA
950 * cycle.
951 *
952 * @param[in] channel
953 * DMA channel to check.
954 *
955 * @return
956 * true if channel is enabled, false if not.
957 ******************************************************************************/
DMA_ChannelEnabled(unsigned int channel)958 bool DMA_ChannelEnabled(unsigned int channel)
959 {
960 EFM_ASSERT(channel < DMA_CHAN_COUNT);
961
962 return (bool)((DMA->CHENS >> channel) & 1);
963 }
964
965
966 /***************************************************************************//**
967 * @brief
968 * Initializes DMA controller.
969 *
970 * @details
971 * This function will reset and prepare the DMA controller for use. Although
972 * it may be used several times, it is normally only used during system
973 * init. If reused during normal operation, notice that any ongoing DMA
974 * transfers will be aborted. When completed, the DMA controller is in
975 * an enabled state.
976 *
977 * @note
978 * Must be invoked before using the DMA controller.
979 *
980 * @param[in] init
981 * Pointer to a structure containing DMA init information.
982 ******************************************************************************/
DMA_Init(DMA_Init_TypeDef * init)983 void DMA_Init(DMA_Init_TypeDef *init)
984 {
985 EFM_ASSERT(init);
986
987 /* Make sure control block is properly aligned */
988 EFM_ASSERT(!((uint32_t)(init->controlBlock) & (256 - 1)));
989
990 /* Make sure DMA clock is enabled prior to accessing DMA module */
991 CMU_ClockEnable(cmuClock_DMA, true);
992
993 /* Make sure DMA controller is set to a known reset state */
994 DMA_Reset();
995
996 /* Clear/enable DMA interrupts */
997 NVIC_ClearPendingIRQ(DMA_IRQn);
998 NVIC_EnableIRQ(DMA_IRQn);
999
1000 /* Enable bus error interrupt */
1001 DMA->IEN = DMA_IEN_ERR;
1002
1003 /* Set pointer to control block, notice that this ptr must have been */
1004 /* properly aligned, according to requirements defined in the reference */
1005 /* manual. */
1006 DMA->CTRLBASE = (uint32_t)(init->controlBlock);
1007
1008 /* Configure and enable the DMA controller */
1009 DMA->CONFIG = ((uint32_t)(init->hprot) << _DMA_CONFIG_CHPROT_SHIFT) | DMA_CONFIG_EN;
1010 }
1011
1012
1013 /***************************************************************************//**
1014 * @brief
1015 * Refresh a descriptor used in a DMA ping-pong cycle.
1016 *
1017 * @details
1018 * During a ping-pong DMA cycle, the DMA controller automatically alternates
1019 * between primary and alternate descriptors, when completing use of a
1020 * descriptor. While the other descriptor is in use by the DMA controller,
1021 * the SW should refresh the completed descriptor. This is typically done from
1022 * the callback defined for the ping-pong cycle.
1023 *
1024 * @param[in] channel
1025 * DMA channel to refresh ping-pong descriptor for.
1026 *
1027 * @param[in] primary
1028 * @li true - refresh primary descriptor
1029 * @li false - refresh alternate descriptor
1030 *
1031 * @param[in] useBurst
1032 * The burst feature is only used on peripherals supporting DMA bursts.
1033 * Bursts must not be used if the total length (as given by nMinus1) is
1034 * less than the arbitration rate configured for the descriptor. Please
1035 * refer to the reference manual for further details on burst usage.
1036 *
1037 * @param[in] dst
1038 * Address to start location to transfer data to. If NULL, leave setting in
1039 * descriptor as is.
1040 *
1041 * @param[in] src
1042 * Address to start location to transfer data from. If NULL, leave setting in
1043 * descriptor as is.
1044 *
1045 * @param[in] nMinus1
1046 * Number of DMA transfer elements (minus 1) to transfer (<= 1023). The
1047 * size of the DMA transfer element (1, 2 or 4 bytes) is configured with
1048 * DMA_CfgDescr().
1049 *
1050 * @param[in] stop
1051 * Indicate that the DMA ping-pong cycle shall stop @b after completing use
1052 * of this descriptor.
1053 ******************************************************************************/
DMA_RefreshPingPong(unsigned int channel,bool primary,bool useBurst,void * dst,void * src,unsigned int nMinus1,bool stop)1054 void DMA_RefreshPingPong(unsigned int channel,
1055 bool primary,
1056 bool useBurst,
1057 void *dst,
1058 void *src,
1059 unsigned int nMinus1,
1060 bool stop)
1061 {
1062 DMA_CycleCtrl_TypeDef cycleCtrl;
1063 DMA_DESCRIPTOR_TypeDef *descr;
1064 uint32_t inc;
1065 uint32_t chBit;
1066 uint32_t tmp;
1067
1068 EFM_ASSERT(channel < DMA_CHAN_COUNT);
1069 EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
1070
1071 /* The ping-pong DMA cycle may be stopped by issuing a basic cycle type */
1072 if (stop)
1073 {
1074 cycleCtrl = dmaCycleCtrlBasic;
1075 }
1076 else
1077 {
1078 cycleCtrl = dmaCycleCtrlPingPong;
1079 }
1080
1081 /* Find descriptor to configure */
1082 if (primary)
1083 {
1084 descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
1085 }
1086 else
1087 {
1088 descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
1089 }
1090
1091 if (src)
1092 {
1093 inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
1094 if (inc == _DMA_CTRL_SRC_INC_NONE)
1095 {
1096 descr->SRCEND = src;
1097 }
1098 else
1099 {
1100 descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
1101 }
1102 }
1103
1104 if (dst)
1105 {
1106 inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
1107 if (inc == _DMA_CTRL_DST_INC_NONE)
1108 {
1109 descr->DSTEND = dst;
1110 }
1111 else
1112 {
1113 descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
1114 }
1115 }
1116
1117 chBit = 1 << channel;
1118 if (useBurst)
1119 {
1120 DMA->CHUSEBURSTS = chBit;
1121 }
1122 else
1123 {
1124 DMA->CHUSEBURSTC = chBit;
1125 }
1126
1127 /* Set cycle control */
1128 tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
1129 tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
1130 tmp |= cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
1131 descr->CTRL = tmp;
1132 }
1133
1134
1135 /***************************************************************************//**
1136 * @brief
1137 * Reset the DMA controller.
1138 *
1139 * @details
1140 * This functions will disable the DMA controller and set it to a reset
1141 * state.
1142 *
1143 * @note
1144 * Notice that any ongoing transfers will be aborted.
1145 ******************************************************************************/
DMA_Reset(void)1146 void DMA_Reset(void)
1147 {
1148 int i;
1149
1150 /* Disable DMA interrupts */
1151 NVIC_DisableIRQ(DMA_IRQn);
1152
1153 /* Put the DMA controller into a known state, first disabling it. */
1154 DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
1155 DMA->CHUSEBURSTC = _DMA_CHUSEBURSTC_MASK;
1156 DMA->CHREQMASKC = _DMA_CHREQMASKC_MASK;
1157 DMA->CHENC = _DMA_CHENC_MASK;
1158 DMA->CHALTC = _DMA_CHALTC_MASK;
1159 DMA->CHPRIC = _DMA_CHPRIC_MASK;
1160 DMA->ERRORC = DMA_ERRORC_ERRORC;
1161 DMA->IEN = _DMA_IEN_RESETVALUE;
1162 DMA->IFC = _DMA_IFC_MASK;
1163
1164 /* Clear channel control flags */
1165 for (i = 0; i < DMA_CHAN_COUNT; i++)
1166 {
1167 DMA->CH[i].CTRL = _DMA_CH_CTRL_RESETVALUE;
1168 }
1169 }
1170
1171
1172 /** @} (end addtogroup DMA) */
1173 /** @} (end addtogroup EM_Library) */
1174