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