A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Committer:
BaderP
Date:
Tue Mar 18 12:44:46 2014 +0000
Revision:
6:e9ab0bb912c8
Parent:
5:d9f46ef80e20
patched SimpleDMA to include additional 32 kb ram

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 5:d9f46ef80e20 1 #ifdef TARGET_LPC1768
Sissors 5:d9f46ef80e20 2
Sissors 5:d9f46ef80e20 3 #include "SimpleDMA.h"
Sissors 5:d9f46ef80e20 4
Sissors 5:d9f46ef80e20 5 SimpleDMA *SimpleDMA::irq_owner[8] = {NULL};
Sissors 5:d9f46ef80e20 6 LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7};
Sissors 5:d9f46ef80e20 7 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination);
Sissors 5:d9f46ef80e20 8
Sissors 5:d9f46ef80e20 9 SimpleDMA::SimpleDMA(int channel) {
Sissors 5:d9f46ef80e20 10 this->channel(channel);
Sissors 5:d9f46ef80e20 11
Sissors 5:d9f46ef80e20 12 //Power up
Sissors 5:d9f46ef80e20 13 LPC_SC->PCONP |= 1<<29;
Sissors 5:d9f46ef80e20 14 LPC_GPDMA->DMACConfig = 1;
Sissors 5:d9f46ef80e20 15 trigger(Trigger_ALWAYS);
Sissors 5:d9f46ef80e20 16
Sissors 5:d9f46ef80e20 17 NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0);
Sissors 5:d9f46ef80e20 18 NVIC_EnableIRQ(DMA_IRQn);
Sissors 5:d9f46ef80e20 19 }
Sissors 5:d9f46ef80e20 20
Sissors 5:d9f46ef80e20 21 int SimpleDMA::start(int length) {
Sissors 5:d9f46ef80e20 22 if (auto_channel)
Sissors 5:d9f46ef80e20 23 _channel = getFreeChannel();
Sissors 5:d9f46ef80e20 24 else
Sissors 5:d9f46ef80e20 25 while(isBusy());
Sissors 5:d9f46ef80e20 26
Sissors 5:d9f46ef80e20 27 uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31);
Sissors 5:d9f46ef80e20 28 switch (source_size) {
Sissors 5:d9f46ef80e20 29 case 16:
Sissors 5:d9f46ef80e20 30 control |= (1<<18) | (length >> 1);
Sissors 5:d9f46ef80e20 31 break;
Sissors 5:d9f46ef80e20 32 case 32:
Sissors 5:d9f46ef80e20 33 control |= (2<<18) | (length >> 2);
Sissors 5:d9f46ef80e20 34 break;
Sissors 5:d9f46ef80e20 35 default:
Sissors 5:d9f46ef80e20 36 control |= length;
Sissors 5:d9f46ef80e20 37 }
Sissors 5:d9f46ef80e20 38 switch (destination_size) {
Sissors 5:d9f46ef80e20 39 case 16:
Sissors 5:d9f46ef80e20 40 control |= (1<<21);
Sissors 5:d9f46ef80e20 41 break;
Sissors 5:d9f46ef80e20 42 case 32:
Sissors 5:d9f46ef80e20 43 control |= (2<<21);
Sissors 5:d9f46ef80e20 44 break;
Sissors 5:d9f46ef80e20 45 }
Sissors 5:d9f46ef80e20 46
Sissors 5:d9f46ef80e20 47 LPC_GPDMACH[_channel]->DMACCSrcAddr = _source;
Sissors 5:d9f46ef80e20 48 LPC_GPDMACH[_channel]->DMACCDestAddr = _destination;
Sissors 5:d9f46ef80e20 49 LPC_GPDMACH[_channel]->DMACCLLI = 0;
Sissors 5:d9f46ef80e20 50 LPC_GPDMACH[_channel]->DMACCControl = control; //Enable interrupt also
Sissors 5:d9f46ef80e20 51
Sissors 5:d9f46ef80e20 52 irq_owner[_channel] = this;
Sissors 5:d9f46ef80e20 53
Sissors 5:d9f46ef80e20 54 if (_trigger != Trigger_ALWAYS) {
Sissors 5:d9f46ef80e20 55 if (_trigger & 16)
Sissors 5:d9f46ef80e20 56 LPC_SC->DMAREQSEL |= 1 << (_trigger - 24);
Sissors 5:d9f46ef80e20 57 else
Sissors 5:d9f46ef80e20 58 LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24));
Sissors 5:d9f46ef80e20 59
Sissors 5:d9f46ef80e20 60 LPC_GPDMACH[_channel]->DMACCConfig = ((_trigger & 15) << 1) + ((_trigger & 15) << 6) + (getTransferType(_trigger, _source, _destination) << 11) + (1<<15) +1; //Both parts of the transfer get triggered at same time
Sissors 5:d9f46ef80e20 61 } else
Sissors 5:d9f46ef80e20 62 LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15); //Enable channel
Sissors 5:d9f46ef80e20 63
Sissors 5:d9f46ef80e20 64 return 0;
Sissors 5:d9f46ef80e20 65 }
Sissors 5:d9f46ef80e20 66
Sissors 5:d9f46ef80e20 67 bool SimpleDMA::isBusy( int channel ) {
Sissors 5:d9f46ef80e20 68 if (channel == -1)
Sissors 5:d9f46ef80e20 69 channel = _channel;
Sissors 5:d9f46ef80e20 70 return (LPC_GPDMA->DMACEnbldChns & (1<<channel));
Sissors 5:d9f46ef80e20 71 }
Sissors 5:d9f46ef80e20 72
Sissors 5:d9f46ef80e20 73 void SimpleDMA::irq_handler0(void) {
Sissors 5:d9f46ef80e20 74 while(LPC_GPDMA->DMACIntTCStat != 0) {
Sissors 5:d9f46ef80e20 75
Sissors 5:d9f46ef80e20 76 uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF);
Sissors 5:d9f46ef80e20 77 if (irq_owner[intloc]!=NULL)
Sissors 5:d9f46ef80e20 78 irq_owner[intloc]->irq_handler();
Sissors 5:d9f46ef80e20 79 }
Sissors 5:d9f46ef80e20 80 }
Sissors 5:d9f46ef80e20 81
Sissors 5:d9f46ef80e20 82 void SimpleDMA::irq_handler(void) {
Sissors 5:d9f46ef80e20 83 LPC_GPDMA->DMACIntTCClear = 1<<_channel;
Sissors 5:d9f46ef80e20 84 _callback.call();
Sissors 5:d9f46ef80e20 85 }
Sissors 5:d9f46ef80e20 86
BaderP 6:e9ab0bb912c8 87 static inline bool isMemory(uint32_t addr)
BaderP 6:e9ab0bb912c8 88 {
BaderP 6:e9ab0bb912c8 89 return (addr >> 28) == 0 || (addr >> 28) == 1 || ((addr >= 0x2007C000) && (addr < (0x2007C000 + 0x8000)));
BaderP 6:e9ab0bb912c8 90 }
BaderP 6:e9ab0bb912c8 91
Sissors 5:d9f46ef80e20 92 uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) {
Sissors 5:d9f46ef80e20 93 //If it is always, simply put it on memory-to-memory
Sissors 5:d9f46ef80e20 94 if (trig == Trigger_ALWAYS)
Sissors 5:d9f46ef80e20 95 return 0;
BaderP 6:e9ab0bb912c8 96 else if (isMemory(source)) { //if source is RAM/Flash
BaderP 6:e9ab0bb912c8 97 if (isMemory(destination)) //if destination is RAM/flash
Sissors 5:d9f46ef80e20 98 return 3; //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do)
Sissors 5:d9f46ef80e20 99 else
Sissors 5:d9f46ef80e20 100 return 1; //Source is memory, destination is peripheral, so m2p
Sissors 5:d9f46ef80e20 101 }
Sissors 5:d9f46ef80e20 102 else {
BaderP 6:e9ab0bb912c8 103 if (isMemory(destination))
Sissors 5:d9f46ef80e20 104 return 2; //Source is peripheral, destination is memory
Sissors 5:d9f46ef80e20 105 else
Sissors 5:d9f46ef80e20 106 return 3; //Both source and destination are peripherals
Sissors 5:d9f46ef80e20 107 }
Sissors 5:d9f46ef80e20 108
Sissors 5:d9f46ef80e20 109 }
Sissors 5:d9f46ef80e20 110 #endif