em_dma.c

Go to the documentation of this file.
00001 /***************************************************************************/
00034 #include "em_dma.h"
00035 #if defined( DMA_PRESENT )
00036 
00037 #include "em_cmu.h"
00038 #include "em_assert.h"
00039 #include "em_bitband.h"
00040 
00041 /***************************************************************************/
00046 /***************************************************************************/
00125 /*******************************************************************************
00126  **************************   LOCAL FUNCTIONS   ********************************
00127  ******************************************************************************/
00128 
00131 /***************************************************************************/
00172 static void DMA_Prepare(unsigned int channel,
00173                         DMA_CycleCtrl_TypeDef cycleCtrl,
00174                         bool primary,
00175                         bool useBurst,
00176                         void *dst,
00177                         void *src,
00178                         unsigned int nMinus1)
00179 {
00180   DMA_DESCRIPTOR_TypeDef *descr;
00181   DMA_DESCRIPTOR_TypeDef *primDescr;
00182   DMA_CB_TypeDef         *cb;
00183   uint32_t               inc;
00184   uint32_t               chBit;
00185   uint32_t               tmp;
00186 
00187   primDescr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
00188 
00189   /* Find descriptor to configure */
00190   if (primary)
00191   {
00192     descr = primDescr;
00193   }
00194   else
00195   {
00196     descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
00197   }
00198 
00199   /* If callback defined, update info on whether callback is issued */
00200   /* for primary or alternate descriptor. Mainly needed for ping-pong */
00201   /* cycles. */
00202   cb = (DMA_CB_TypeDef *)(primDescr->USER);
00203   if (cb)
00204   {
00205     cb->primary = (uint8_t)primary;
00206   }
00207 
00208   if (src)
00209   {
00210     inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
00211     if (inc == _DMA_CTRL_SRC_INC_NONE)
00212     {
00213       descr->SRCEND = src;
00214     }
00215     else
00216     {
00217       descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
00218     }
00219   }
00220 
00221   if (dst)
00222   {
00223     inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
00224     if (inc == _DMA_CTRL_DST_INC_NONE)
00225     {
00226       descr->DSTEND = dst;
00227     }
00228     else
00229     {
00230       descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
00231     }
00232   }
00233 
00234   chBit = 1 << channel;
00235   if (useBurst)
00236   {
00237     DMA->CHUSEBURSTS = chBit;
00238   }
00239   else
00240   {
00241     DMA->CHUSEBURSTC = chBit;
00242   }
00243 
00244   if (primary)
00245   {
00246     DMA->CHALTC = chBit;
00247   }
00248   else
00249   {
00250     DMA->CHALTS = chBit;
00251   }
00252 
00253   /* Set cycle control */
00254   tmp         = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
00255   tmp        |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
00256   tmp        |= (uint32_t)cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
00257   descr->CTRL = tmp;
00258 }
00259 
00262 /*******************************************************************************
00263  ************************   INTERRUPT FUNCTIONS   ******************************
00264  ******************************************************************************/
00265 
00266 #ifndef EXCLUDE_DEFAULT_DMA_IRQ_HANDLER
00267 
00268 /***************************************************************************/
00285 void DMA_IRQHandler(void)
00286 {
00287   int                    channel;
00288   DMA_CB_TypeDef         *cb;
00289   uint32_t               pending;
00290   uint32_t               pendingPrio;
00291   uint32_t               prio;
00292   uint32_t               primaryCpy;
00293   int                    i;
00294 
00295   /* Get all pending and enabled interrupts */
00296   pending  = DMA->IF;
00297   pending &= DMA->IEN;
00298 
00299   /* Check for bus error */
00300   if (pending & DMA_IF_ERR)
00301   {
00302     /* Loop here to enable the debugger to see what has happened */
00303     while (1)
00304       ;
00305   }
00306 
00307   /* Process all pending channel interrupts. First process channels */
00308   /* defined with high priority, then those with default priority. */
00309   prio        = DMA->CHPRIS;
00310   pendingPrio = pending & prio;
00311   for (i = 0; i < 2; i++)
00312   {
00313     channel = 0;
00314     /* Process pending interrupts within high/default priority group */
00315     /* honouring priority within group. */
00316     while (pendingPrio)
00317     {
00318       if (pendingPrio & 1)
00319       {
00320         DMA_DESCRIPTOR_TypeDef *descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
00321         uint32_t chmask = 1 << channel;
00322 
00323         /* Clear pending interrupt prior to invoking callback, in case it */
00324         /* sets up another DMA cycle. */
00325         DMA->IFC = chmask;
00326 
00327         /* Normally, no point in enabling interrupt without callback, but */
00328         /* check if callback is defined anyway. Callback info is always */
00329         /* located in primary descriptor. */
00330         cb = (DMA_CB_TypeDef *)(descr[channel].USER);
00331         if (cb)
00332         {
00333           /* Toggle next-descriptor indicator always prior to invoking */
00334           /* callback (in case callback reconfigurs something) */
00335           primaryCpy   = cb->primary;
00336           cb->primary ^= 1;
00337           if (cb->cbFunc)
00338           {
00339             cb->cbFunc(channel, (bool)primaryCpy, cb->userPtr);
00340           }
00341         }
00342       }
00343 
00344       pendingPrio >>= 1;
00345       channel++;
00346     }
00347 
00348     /* On second iteration, process default priority channels */
00349     pendingPrio = pending & ~prio;
00350   }
00351 }
00352 
00353 #endif /* EXCLUDE_DEFAULT_DMA_IRQ_HANDLER */
00354 
00355 
00356 /*******************************************************************************
00357  **************************   GLOBAL FUNCTIONS   *******************************
00358  ******************************************************************************/
00359 
00360 /***************************************************************************/
00392 void DMA_ActivateAuto(unsigned int channel,
00393                       bool primary,
00394                       void *dst,
00395                       void *src,
00396                       unsigned int nMinus1)
00397 {
00398   uint32_t chBit;
00399 
00400   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00401   EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
00402 
00403   DMA_Prepare(channel,
00404               dmaCycleCtrlAuto,
00405               primary,
00406               false,
00407               dst,
00408               src,
00409               nMinus1);
00410 
00411   chBit        = 1 << channel;
00412   DMA->CHENS   = chBit; /* Enable channel */
00413   DMA->CHSWREQ = chBit; /* Activate with SW request */
00414 }
00415 
00416 
00417 /***************************************************************************/
00455 void DMA_ActivateBasic(unsigned int channel,
00456                        bool primary,
00457                        bool useBurst,
00458                        void *dst,
00459                        void *src,
00460                        unsigned int nMinus1)
00461 {
00462   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00463   EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
00464 
00465   DMA_Prepare(channel,
00466               dmaCycleCtrlBasic,
00467               primary,
00468               useBurst,
00469               dst,
00470               src,
00471               nMinus1);
00472 
00473   /* Enable channel, request signal is provided by peripheral device */
00474   DMA->CHENS = 1 << channel;
00475 }
00476 
00477 
00478 /***************************************************************************/
00527 void DMA_ActivatePingPong(unsigned int channel,
00528                           bool useBurst,
00529                           void *primDst,
00530                           void *primSrc,
00531                           unsigned int primNMinus1,
00532                           void *altDst,
00533                           void *altSrc,
00534                           unsigned int altNMinus1)
00535 {
00536   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00537   EFM_ASSERT(primNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
00538   EFM_ASSERT(altNMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
00539 
00540   /* Prepare alternate descriptor first */
00541   DMA_Prepare(channel,
00542               dmaCycleCtrlPingPong,
00543               false,
00544               useBurst,
00545               altDst,
00546               altSrc,
00547               altNMinus1);
00548 
00549   /* Prepare primary descriptor last in order to start cycle using it */
00550   DMA_Prepare(channel,
00551               dmaCycleCtrlPingPong,
00552               true,
00553               useBurst,
00554               primDst,
00555               primSrc,
00556               primNMinus1);
00557 
00558   /* Enable channel, request signal is provided by peripheral device */
00559   DMA->CHENS = 1 << channel;
00560 }
00561 
00562 
00563 /***************************************************************************/
00597 void DMA_ActivateScatterGather(unsigned int channel,
00598                                bool useBurst,
00599                                DMA_DESCRIPTOR_TypeDef *altDescr,
00600                                unsigned int count)
00601 {
00602   DMA_DESCRIPTOR_TypeDef *descr;
00603   DMA_CB_TypeDef         *cb;
00604   uint32_t               cycleCtrl;
00605   uint32_t               chBit;
00606 
00607   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00608   EFM_ASSERT(altDescr);
00609   EFM_ASSERT(count && (count <= 256));
00610 
00611   /* We have to configure the primary descriptor properly in order to */
00612   /* transfer one complete alternate descriptor from the alternate */
00613   /* descriptor table into the actual alternate descriptor. */
00614   descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE) + channel;
00615 
00616   /* Set source end address to point to alternate descriptor array */
00617   descr->SRCEND = (uint32_t *)altDescr + (count * 4) - 1;
00618 
00619   /* The destination end address in the primary descriptor MUST point */
00620   /* to the corresponding alternate descriptor in scatter-gather mode. */
00621   descr->DSTEND = (uint32_t *)((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE) +
00622                                channel + 1) - 1;
00623 
00624   /* The user field of the descriptor is used for callback configuration, */
00625   /* and already configured when channel is configured. Do not modify it. */
00626 
00627   /* Determine from alternate configuration whether this is a memory or */
00628   /* peripheral scatter-gather, by looking at the first alternate descriptor. */
00629   cycleCtrl  = altDescr->CTRL & _DMA_CTRL_CYCLE_CTRL_MASK;
00630   cycleCtrl &= ~(1 << _DMA_CTRL_CYCLE_CTRL_SHIFT);
00631 
00632   EFM_ASSERT((cycleCtrl == dmaCycleCtrlMemScatterGather) ||
00633              (cycleCtrl == dmaCycleCtrlPerScatterGather));
00634 
00635   /* Set last alternate descriptor to basic or auto-request cycle type in */
00636   /* order to have dma_done signal asserted when complete. Otherwise interrupt */
00637   /* will not be triggered when done. */
00638   altDescr[count - 1].CTRL &= ~_DMA_CTRL_CYCLE_CTRL_MASK;
00639   if (cycleCtrl == dmaCycleCtrlMemScatterGather)
00640   {
00641     altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlAuto << _DMA_CTRL_CYCLE_CTRL_SHIFT;
00642   }
00643   else
00644   {
00645     altDescr[count - 1].CTRL |= (uint32_t)dmaCycleCtrlBasic << _DMA_CTRL_CYCLE_CTRL_SHIFT;
00646   }
00647 
00648   /* If callback defined, update info on whether callback is issued for */
00649   /* primary or alternate descriptor. Not really useful for scatter-gather, */
00650   /* but do for consistency. Always set to alternate, since that is the last */
00651   /* descriptor actually used. */
00652   cb = (DMA_CB_TypeDef *)(descr->USER);
00653   if (cb)
00654   {
00655     cb->primary = false;
00656   }
00657 
00658   /* Configure primary descriptor control word */
00659   descr->CTRL =
00660     ((uint32_t)dmaDataInc4 << _DMA_CTRL_DST_INC_SHIFT) |
00661     ((uint32_t)dmaDataSize4 << _DMA_CTRL_DST_SIZE_SHIFT) |
00662     ((uint32_t)dmaDataInc4 << _DMA_CTRL_SRC_INC_SHIFT) |
00663     ((uint32_t)dmaDataSize4 << _DMA_CTRL_SRC_SIZE_SHIFT) |
00664     /* Use same protection scheme as for alternate descriptors */
00665     (altDescr->CTRL & _DMA_CTRL_SRC_PROT_CTRL_MASK) |
00666     ((uint32_t)dmaArbitrate4 << _DMA_CTRL_R_POWER_SHIFT) |
00667     (((count * 4) - 1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
00668     (((uint32_t)useBurst & 1) << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
00669     cycleCtrl;
00670 
00671   chBit = 1 << channel;
00672 
00673   /* Start with primary descriptor */
00674   DMA->CHALTC = chBit;
00675 
00676   /* Enable channel */
00677   DMA->CHENS = chBit;
00678 
00679   /* Send request if memory scatter-gather, otherwise request signal is */
00680   /* provided by peripheral. */
00681   if (cycleCtrl == dmaCycleCtrlMemScatterGather)
00682   {
00683     DMA->CHSWREQ = chBit;
00684   }
00685 }
00686 
00687 
00688 /***************************************************************************/
00706 void DMA_CfgChannel(unsigned int channel, DMA_CfgChannel_TypeDef *cfg)
00707 {
00708   DMA_DESCRIPTOR_TypeDef *descr;
00709 
00710   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00711   EFM_ASSERT(cfg);
00712 
00713   /* Always keep callback configuration reference in primary descriptor */
00714   descr               = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
00715   descr[channel].USER = (uint32_t)(cfg->cb);
00716 
00717   /* Set to specified priority for channel */
00718   if (cfg->highPri)
00719   {
00720     DMA->CHPRIS = 1 << channel;
00721   }
00722   else
00723   {
00724     DMA->CHPRIC = 1 << channel;
00725   }
00726 
00727   /* Set DMA signal source select */
00728   DMA->CH[channel].CTRL = cfg->select;
00729 
00730   /* Enable/disable interrupt as specified */
00731   if (cfg->enableInt)
00732   {
00733     DMA->IFC = (1 << channel);
00734     BITBAND_Peripheral(&(DMA->IEN), channel, 1);
00735   }
00736   else
00737   {
00738     BITBAND_Peripheral(&(DMA->IEN), channel, 0);
00739   }
00740 }
00741 
00742 
00743 /***************************************************************************/
00781 void DMA_CfgDescr(unsigned int channel,
00782                   bool primary,
00783                   DMA_CfgDescr_TypeDef *cfg)
00784 {
00785   DMA_DESCRIPTOR_TypeDef *descr;
00786 
00787   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00788   EFM_ASSERT(cfg);
00789 
00790   /* Find descriptor to configure */
00791   if (primary)
00792   {
00793     descr = (DMA_DESCRIPTOR_TypeDef *)DMA->CTRLBASE;
00794   }
00795   else
00796   {
00797     descr = (DMA_DESCRIPTOR_TypeDef *)DMA->ALTCTRLBASE;
00798   }
00799   descr += channel;
00800 
00801   /* Prepare the descriptor */
00802   /* Source/destination end addresses set when started */
00803   descr->CTRL =
00804     (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
00805     (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
00806     (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
00807     (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
00808     ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
00809     (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
00810     (0 << _DMA_CTRL_N_MINUS_1_SHIFT) |         /* Set when activated */
00811     (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) |     /* Set when activated */
00812     DMA_CTRL_CYCLE_CTRL_INVALID;               /* Set when activated */
00813 }
00814 
00815 
00816 #if defined( _DMA_LOOP0_MASK ) && defined( _DMA_LOOP1_MASK )
00817 /***************************************************************************/
00830 void DMA_CfgLoop(unsigned int channel, DMA_CfgLoop_TypeDef *cfg)
00831 {
00832   EFM_ASSERT(channel <= 1);
00833   EFM_ASSERT(cfg->nMinus1 <= 1023);
00834 
00835   /* Configure LOOP setting */
00836   switch( channel )
00837   {
00838   case 0:
00839     DMA->LOOP0 = (cfg->enable << _DMA_LOOP0_EN_SHIFT|
00840                   cfg->nMinus1 << _DMA_LOOP0_WIDTH_SHIFT);
00841     break;
00842   case 1:
00843     DMA->LOOP1 = (cfg->enable << _DMA_LOOP1_EN_SHIFT|
00844                   cfg->nMinus1 << _DMA_LOOP1_WIDTH_SHIFT);
00845     break;
00846   }
00847 }
00848 #endif
00849 
00850 
00851 #if defined( _DMA_RECT0_MASK )
00852 /***************************************************************************/
00861 void DMA_CfgRect(unsigned int channel, DMA_CfgRect_TypeDef *cfg)
00862 {
00863   (void)channel;                            /* Unused parameter */
00864 
00865   EFM_ASSERT(channel == 0);
00866   EFM_ASSERT(cfg->dstStride <= 2047);
00867   EFM_ASSERT(cfg->srcStride <= 2047);
00868   EFM_ASSERT(cfg->height <= 1023);
00869 
00870   /* Configure rectangular/2D copy */
00871   DMA->RECT0 = (cfg->dstStride << _DMA_RECT0_DSTSTRIDE_SHIFT|
00872                 cfg->srcStride << _DMA_RECT0_SRCSTRIDE_SHIFT|
00873                 cfg->height << _DMA_RECT0_HEIGHT_SHIFT);
00874 }
00875 #endif
00876 
00877 
00878 /***************************************************************************/
00904 void DMA_CfgDescrScatterGather(DMA_DESCRIPTOR_TypeDef *descr,
00905                                unsigned int indx,
00906                                DMA_CfgDescrSGAlt_TypeDef *cfg)
00907 {
00908   uint32_t cycleCtrl;
00909 
00910   EFM_ASSERT(descr);
00911   EFM_ASSERT(cfg);
00912 
00913   /* Point to selected entry in alternate descriptor table */
00914   descr += indx;
00915 
00916   if (cfg->srcInc == dmaDataIncNone)
00917   {
00918     descr->SRCEND = cfg->src;
00919   }
00920   else
00921   {
00922     descr->SRCEND = (void *)((uint32_t)(cfg->src) + ((uint32_t)(cfg->nMinus1) << cfg->srcInc));
00923   }
00924 
00925   if (cfg->dstInc == dmaDataIncNone)
00926   {
00927     descr->DSTEND = cfg->dst;
00928   }
00929   else
00930   {
00931     descr->DSTEND = (void *)((uint32_t)(cfg->dst) + ((uint32_t)(cfg->nMinus1) << cfg->dstInc));
00932   }
00933 
00934   /* User definable part not used */
00935   descr->USER = 0;
00936 
00937   if (cfg->peripheral)
00938   {
00939     cycleCtrl = (uint32_t)dmaCycleCtrlPerScatterGather + 1;
00940   }
00941   else
00942   {
00943     cycleCtrl = (uint32_t)dmaCycleCtrlMemScatterGather + 1;
00944   }
00945 
00946   descr->CTRL =
00947     (cfg->dstInc << _DMA_CTRL_DST_INC_SHIFT) |
00948     (cfg->size << _DMA_CTRL_DST_SIZE_SHIFT) |
00949     (cfg->srcInc << _DMA_CTRL_SRC_INC_SHIFT) |
00950     (cfg->size << _DMA_CTRL_SRC_SIZE_SHIFT) |
00951     ((uint32_t)(cfg->hprot) << _DMA_CTRL_SRC_PROT_CTRL_SHIFT) |
00952     (cfg->arbRate << _DMA_CTRL_R_POWER_SHIFT) |
00953     ((uint32_t)(cfg->nMinus1) << _DMA_CTRL_N_MINUS_1_SHIFT) |
00954     /* Never set next useburst bit, since the descriptor used after the */
00955     /* alternate descriptor is the primary descriptor which operates on */
00956     /* memory. If the alternate descriptors need to have useBurst set, this */
00957     /* done when setting up the primary descriptor, ie when activating. */
00958     (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
00959     (cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT);
00960 }
00961 
00962 
00963 /***************************************************************************/
00979 void DMA_ChannelEnable(unsigned int channel, bool enable)
00980 {
00981   EFM_ASSERT(channel < DMA_CHAN_COUNT);
00982 
00983   if (enable)
00984   {
00985     DMA->CHENS = 1<<channel;
00986   }
00987   else
00988   {
00989     DMA->CHENC = 1<<channel;
00990   }
00991 }
00992 
00993 
00994 /***************************************************************************/
01008 bool DMA_ChannelEnabled(unsigned int channel)
01009 {
01010   EFM_ASSERT(channel < DMA_CHAN_COUNT);
01011 
01012   return (bool)((DMA->CHENS >> channel) & 1);
01013 }
01014 
01015 
01016 /***************************************************************************/
01033 void DMA_Init(DMA_Init_TypeDef *init)
01034 {
01035   EFM_ASSERT(init);
01036 
01037   /* Make sure control block is properly aligned */
01038 #if (DMA_CHAN_COUNT <= 4)
01039   EFM_ASSERT(!((uint32_t)(init->controlBlock) & (128 - 1)));
01040 #elif (DMA_CHAN_COUNT <= 8) || (DMA_CHAN_COUNT <= 12)
01041   EFM_ASSERT(!((uint32_t)(init->controlBlock) & (256 - 1)));
01042 #else
01043 #error "Unsupported DMA channel count (em_dma.c)."
01044 #endif
01045 
01046   /* Make sure DMA clock is enabled prior to accessing DMA module */
01047   CMU_ClockEnable(cmuClock_DMA, true);
01048 
01049   /* Make sure DMA controller is set to a known reset state */
01050   DMA_Reset();
01051 
01052   /* Clear/enable DMA interrupts */
01053   NVIC_ClearPendingIRQ(DMA_IRQn);
01054   NVIC_EnableIRQ(DMA_IRQn);
01055 
01056   /* Enable bus error interrupt */
01057   DMA->IEN = DMA_IEN_ERR;
01058 
01059   /* Set pointer to control block, notice that this ptr must have been */
01060   /* properly aligned, according to requirements defined in the reference */
01061   /* manual. */
01062   DMA->CTRLBASE = (uint32_t)(init->controlBlock);
01063 
01064   /* Configure and enable the DMA controller */
01065   DMA->CONFIG = ((uint32_t)(init->hprot) << _DMA_CONFIG_CHPROT_SHIFT) | DMA_CONFIG_EN;
01066 }
01067 
01068 
01069 /***************************************************************************/
01110 void DMA_RefreshPingPong(unsigned int channel,
01111                          bool primary,
01112                          bool useBurst,
01113                          void *dst,
01114                          void *src,
01115                          unsigned int nMinus1,
01116                          bool stop)
01117 {
01118   DMA_CycleCtrl_TypeDef  cycleCtrl;
01119   DMA_DESCRIPTOR_TypeDef *descr;
01120   uint32_t               inc;
01121   uint32_t               chBit;
01122   uint32_t               tmp;
01123 
01124   EFM_ASSERT(channel < DMA_CHAN_COUNT);
01125   EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
01126 
01127   /* The ping-pong DMA cycle may be stopped by issuing a basic cycle type */
01128   if (stop)
01129   {
01130     cycleCtrl = dmaCycleCtrlBasic;
01131   }
01132   else
01133   {
01134     cycleCtrl = dmaCycleCtrlPingPong;
01135   }
01136 
01137   /* Find descriptor to configure */
01138   if (primary)
01139   {
01140     descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
01141   }
01142   else
01143   {
01144     descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
01145   }
01146 
01147   if (src)
01148   {
01149     inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
01150     if (inc == _DMA_CTRL_SRC_INC_NONE)
01151     {
01152       descr->SRCEND = src;
01153     }
01154     else
01155     {
01156       descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
01157     }
01158   }
01159 
01160   if (dst)
01161   {
01162     inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
01163     if (inc == _DMA_CTRL_DST_INC_NONE)
01164     {
01165       descr->DSTEND = dst;
01166     }
01167     else
01168     {
01169       descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
01170     }
01171   }
01172 
01173   chBit = 1 << channel;
01174   if (useBurst)
01175   {
01176     DMA->CHUSEBURSTS = chBit;
01177   }
01178   else
01179   {
01180     DMA->CHUSEBURSTC = chBit;
01181   }
01182 
01183   /* Set cycle control */
01184   tmp         = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
01185   tmp        |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
01186   tmp        |= cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
01187   descr->CTRL = tmp;
01188 }
01189 
01190 
01191 /***************************************************************************/
01202 void DMA_Reset(void)
01203 {
01204   int i;
01205 
01206   /* Disable DMA interrupts */
01207   NVIC_DisableIRQ(DMA_IRQn);
01208 
01209   /* Put the DMA controller into a known state, first disabling it. */
01210   DMA->CONFIG      = _DMA_CONFIG_RESETVALUE;
01211   DMA->CHUSEBURSTC = _DMA_CHUSEBURSTC_MASK;
01212   DMA->CHREQMASKC  = _DMA_CHREQMASKC_MASK;
01213   DMA->CHENC       = _DMA_CHENC_MASK;
01214   DMA->CHALTC      = _DMA_CHALTC_MASK;
01215   DMA->CHPRIC      = _DMA_CHPRIC_MASK;
01216   DMA->ERRORC      = DMA_ERRORC_ERRORC;
01217   DMA->IEN         = _DMA_IEN_RESETVALUE;
01218   DMA->IFC         = _DMA_IFC_MASK;
01219 
01220   /* Clear channel control flags */
01221   for (i = 0; i < DMA_CHAN_COUNT; i++)
01222   {
01223     DMA->CH[i].CTRL = _DMA_CH_CTRL_RESETVALUE;
01224   }
01225 }
01226 
01227 
01230 #endif /* defined( DMA_PRESENT ) */