A simple library to access the DMA functionality.
Fork of SimpleDMA by
SimpleDMA_LPC1768.cpp@6:e9ab0bb912c8, 2014-03-18 (annotated)
- 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?
User | Revision | Line number | New 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 |