A simple library to access the DMA functionality.
Fork of SimpleDMA by
SimpleDMA_LPC1768.cpp
- Committer:
- Sissors
- Date:
- 2014-01-04
- Revision:
- 5:d9f46ef80e20
- Child:
- 6:e9ab0bb912c8
File content as of revision 5:d9f46ef80e20:
#ifdef TARGET_LPC1768 #include "SimpleDMA.h" SimpleDMA *SimpleDMA::irq_owner[8] = {NULL}; LPC_GPDMACH_TypeDef *LPC_GPDMACH[8] = {LPC_GPDMACH0, LPC_GPDMACH1, LPC_GPDMACH2, LPC_GPDMACH3, LPC_GPDMACH4, LPC_GPDMACH5, LPC_GPDMACH6, LPC_GPDMACH7}; uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination); SimpleDMA::SimpleDMA(int channel) { this->channel(channel); //Power up LPC_SC->PCONP |= 1<<29; LPC_GPDMA->DMACConfig = 1; trigger(Trigger_ALWAYS); NVIC_SetVector(DMA_IRQn, (uint32_t)&irq_handler0); NVIC_EnableIRQ(DMA_IRQn); } int SimpleDMA::start(int length) { if (auto_channel) _channel = getFreeChannel(); else while(isBusy()); uint32_t control = (source_inc << 26) | (destination_inc << 27) | (1UL << 31); switch (source_size) { case 16: control |= (1<<18) | (length >> 1); break; case 32: control |= (2<<18) | (length >> 2); break; default: control |= length; } switch (destination_size) { case 16: control |= (1<<21); break; case 32: control |= (2<<21); break; } LPC_GPDMACH[_channel]->DMACCSrcAddr = _source; LPC_GPDMACH[_channel]->DMACCDestAddr = _destination; LPC_GPDMACH[_channel]->DMACCLLI = 0; LPC_GPDMACH[_channel]->DMACCControl = control; //Enable interrupt also irq_owner[_channel] = this; if (_trigger != Trigger_ALWAYS) { if (_trigger & 16) LPC_SC->DMAREQSEL |= 1 << (_trigger - 24); else LPC_SC->DMAREQSEL &= ~(1 << (_trigger - 24)); 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 } else LPC_GPDMACH[_channel]->DMACCConfig = (getTransferType(_trigger, _source, _destination) << 11) + 1 + (1<<15); //Enable channel return 0; } bool SimpleDMA::isBusy( int channel ) { if (channel == -1) channel = _channel; return (LPC_GPDMA->DMACEnbldChns & (1<<channel)); } void SimpleDMA::irq_handler0(void) { while(LPC_GPDMA->DMACIntTCStat != 0) { uint32_t intloc = 31 - __CLZ(LPC_GPDMA->DMACIntTCStat & 0xFF); if (irq_owner[intloc]!=NULL) irq_owner[intloc]->irq_handler(); } } void SimpleDMA::irq_handler(void) { LPC_GPDMA->DMACIntTCClear = 1<<_channel; _callback.call(); } uint32_t getTransferType(SimpleDMA_Trigger trig, uint32_t source, uint32_t destination) { //If it is always, simply put it on memory-to-memory if (trig == Trigger_ALWAYS) return 0; else if ((source >> 28) == 0 || (source >> 28) == 1) { //if source is RAM/Flash if ((destination >> 28) == 0 || (destination >> 28) == 1) //if destination is RAM/flash return 3; //Return p2p for m2m with a trigger (since I have no idea wtf you are trying to do) else return 1; //Source is memory, destination is peripheral, so m2p } else { if ((destination >> 28) == 0 || (destination >> 28)) return 2; //Source is peripheral, destination is memory else return 3; //Both source and destination are peripherals } } #endif