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
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
00190 if (primary)
00191 {
00192 descr = primDescr;
00193 }
00194 else
00195 {
00196 descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
00197 }
00198
00199
00200
00201
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
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
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
00296 pending = DMA->IF;
00297 pending &= DMA->IEN;
00298
00299
00300 if (pending & DMA_IF_ERR)
00301 {
00302
00303 while (1)
00304 ;
00305 }
00306
00307
00308
00309 prio = DMA->CHPRIS;
00310 pendingPrio = pending & prio;
00311 for (i = 0; i < 2; i++)
00312 {
00313 channel = 0;
00314
00315
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
00324
00325 DMA->IFC = chmask;
00326
00327
00328
00329
00330 cb = (DMA_CB_TypeDef *)(descr[channel].USER);
00331 if (cb)
00332 {
00333
00334
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
00349 pendingPrio = pending & ~prio;
00350 }
00351 }
00352
00353 #endif
00354
00355
00356
00357
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;
00413 DMA->CHSWREQ = chBit;
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
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
00541 DMA_Prepare(channel,
00542 dmaCycleCtrlPingPong,
00543 false,
00544 useBurst,
00545 altDst,
00546 altSrc,
00547 altNMinus1);
00548
00549
00550 DMA_Prepare(channel,
00551 dmaCycleCtrlPingPong,
00552 true,
00553 useBurst,
00554 primDst,
00555 primSrc,
00556 primNMinus1);
00557
00558
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
00612
00613
00614 descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE) + channel;
00615
00616
00617 descr->SRCEND = (uint32_t *)altDescr + (count * 4) - 1;
00618
00619
00620
00621 descr->DSTEND = (uint32_t *)((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE) +
00622 channel + 1) - 1;
00623
00624
00625
00626
00627
00628
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
00636
00637
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
00649
00650
00651
00652 cb = (DMA_CB_TypeDef *)(descr->USER);
00653 if (cb)
00654 {
00655 cb->primary = false;
00656 }
00657
00658
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
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
00674 DMA->CHALTC = chBit;
00675
00676
00677 DMA->CHENS = chBit;
00678
00679
00680
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
00714 descr = (DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE);
00715 descr[channel].USER = (uint32_t)(cfg->cb);
00716
00717
00718 if (cfg->highPri)
00719 {
00720 DMA->CHPRIS = 1 << channel;
00721 }
00722 else
00723 {
00724 DMA->CHPRIC = 1 << channel;
00725 }
00726
00727
00728 DMA->CH[channel].CTRL = cfg->select;
00729
00730
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
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
00802
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) |
00811 (0 << _DMA_CTRL_NEXT_USEBURST_SHIFT) |
00812 DMA_CTRL_CYCLE_CTRL_INVALID;
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
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;
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
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
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
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
00955
00956
00957
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
01038 EFM_ASSERT(!((uint32_t)(init->controlBlock) & (256 - 1)));
01039
01040
01041 CMU_ClockEnable(cmuClock_DMA, true);
01042
01043
01044 DMA_Reset();
01045
01046
01047 NVIC_ClearPendingIRQ(DMA_IRQn);
01048 NVIC_EnableIRQ(DMA_IRQn);
01049
01050
01051 DMA->IEN = DMA_IEN_ERR;
01052
01053
01054
01055
01056 DMA->CTRLBASE = (uint32_t)(init->controlBlock);
01057
01058
01059 DMA->CONFIG = ((uint32_t)(init->hprot) << _DMA_CONFIG_CHPROT_SHIFT) | DMA_CONFIG_EN;
01060 }
01061
01062
01063
01104 void DMA_RefreshPingPong(unsigned int channel,
01105 bool primary,
01106 bool useBurst,
01107 void *dst,
01108 void *src,
01109 unsigned int nMinus1,
01110 bool stop)
01111 {
01112 DMA_CycleCtrl_TypeDef cycleCtrl;
01113 DMA_DESCRIPTOR_TypeDef *descr;
01114 uint32_t inc;
01115 uint32_t chBit;
01116 uint32_t tmp;
01117
01118 EFM_ASSERT(channel < DMA_CHAN_COUNT);
01119 EFM_ASSERT(nMinus1 <= (_DMA_CTRL_N_MINUS_1_MASK >> _DMA_CTRL_N_MINUS_1_SHIFT));
01120
01121
01122 if (stop)
01123 {
01124 cycleCtrl = dmaCycleCtrlBasic;
01125 }
01126 else
01127 {
01128 cycleCtrl = dmaCycleCtrlPingPong;
01129 }
01130
01131
01132 if (primary)
01133 {
01134 descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->CTRLBASE)) + channel;
01135 }
01136 else
01137 {
01138 descr = ((DMA_DESCRIPTOR_TypeDef *)(DMA->ALTCTRLBASE)) + channel;
01139 }
01140
01141 if (src)
01142 {
01143 inc = (descr->CTRL & _DMA_CTRL_SRC_INC_MASK) >> _DMA_CTRL_SRC_INC_SHIFT;
01144 if (inc == _DMA_CTRL_SRC_INC_NONE)
01145 {
01146 descr->SRCEND = src;
01147 }
01148 else
01149 {
01150 descr->SRCEND = (void *)((uint32_t)src + (nMinus1 << inc));
01151 }
01152 }
01153
01154 if (dst)
01155 {
01156 inc = (descr->CTRL & _DMA_CTRL_DST_INC_MASK) >> _DMA_CTRL_DST_INC_SHIFT;
01157 if (inc == _DMA_CTRL_DST_INC_NONE)
01158 {
01159 descr->DSTEND = dst;
01160 }
01161 else
01162 {
01163 descr->DSTEND = (void *)((uint32_t)dst + (nMinus1 << inc));
01164 }
01165 }
01166
01167 chBit = 1 << channel;
01168 if (useBurst)
01169 {
01170 DMA->CHUSEBURSTS = chBit;
01171 }
01172 else
01173 {
01174 DMA->CHUSEBURSTC = chBit;
01175 }
01176
01177
01178 tmp = descr->CTRL & ~(_DMA_CTRL_CYCLE_CTRL_MASK | _DMA_CTRL_N_MINUS_1_MASK);
01179 tmp |= nMinus1 << _DMA_CTRL_N_MINUS_1_SHIFT;
01180 tmp |= cycleCtrl << _DMA_CTRL_CYCLE_CTRL_SHIFT;
01181 descr->CTRL = tmp;
01182 }
01183
01184
01185
01196 void DMA_Reset(void)
01197 {
01198 int i;
01199
01200
01201 NVIC_DisableIRQ(DMA_IRQn);
01202
01203
01204 DMA->CONFIG = _DMA_CONFIG_RESETVALUE;
01205 DMA->CHUSEBURSTC = _DMA_CHUSEBURSTC_MASK;
01206 DMA->CHREQMASKC = _DMA_CHREQMASKC_MASK;
01207 DMA->CHENC = _DMA_CHENC_MASK;
01208 DMA->CHALTC = _DMA_CHALTC_MASK;
01209 DMA->CHPRIC = _DMA_CHPRIC_MASK;
01210 DMA->ERRORC = DMA_ERRORC_ERRORC;
01211 DMA->IEN = _DMA_IEN_RESETVALUE;
01212 DMA->IFC = _DMA_IFC_MASK;
01213
01214
01215 for (i = 0; i < DMA_CHAN_COUNT; i++)
01216 {
01217 DMA->CH[i].CTRL = _DMA_CH_CTRL_RESETVALUE;
01218 }
01219 }
01220
01221
01224 #endif