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