A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Committer:
Sissors
Date:
Thu Dec 26 16:31:54 2013 +0000
Revision:
4:c3a84c6c432c
Parent:
3:34f5bf8adfa0
Child:
5:d9f46ef80e20
Always enable IRQ to finish the DMA transfer
; (Shouldn't be needed, but works for now)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sissors 0:d77ea45fa625 1 #include "SimpleDMA.h"
Sissors 0:d77ea45fa625 2
Sissors 3:34f5bf8adfa0 3
Sissors 0:d77ea45fa625 4
Sissors 1:0b73b00bcee8 5 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL};
Sissors 1:0b73b00bcee8 6
Sissors 0:d77ea45fa625 7 SimpleDMA::SimpleDMA(int channel) {
Sissors 0:d77ea45fa625 8 this->channel(channel);
Sissors 1:0b73b00bcee8 9
Sissors 0:d77ea45fa625 10 //Enable DMA
Sissors 0:d77ea45fa625 11 SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux
Sissors 0:d77ea45fa625 12 SIM->SCGC7 |= 1<<8; //Enable clock to DMA
Sissors 0:d77ea45fa625 13
Sissors 1:0b73b00bcee8 14 trigger(Trigger_ALWAYS);
Sissors 1:0b73b00bcee8 15
Sissors 2:fe2fcaa72434 16 DCR = (1<<29) + (1<<30); //Set to always use DMAMUX (If no trigger is needed we route via alwayson)
Sissors 3:34f5bf8adfa0 17
Sissors 3:34f5bf8adfa0 18 NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
Sissors 3:34f5bf8adfa0 19 NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
Sissors 3:34f5bf8adfa0 20 NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
Sissors 3:34f5bf8adfa0 21 NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
Sissors 3:34f5bf8adfa0 22 NVIC_EnableIRQ(DMA0_IRQn);
Sissors 3:34f5bf8adfa0 23 NVIC_EnableIRQ(DMA1_IRQn);
Sissors 3:34f5bf8adfa0 24 NVIC_EnableIRQ(DMA2_IRQn);
Sissors 3:34f5bf8adfa0 25 NVIC_EnableIRQ(DMA3_IRQn);
Sissors 0:d77ea45fa625 26 }
Sissors 0:d77ea45fa625 27
Sissors 2:fe2fcaa72434 28 int SimpleDMA::setAddress(uint32_t address, int wordsize, bool source, bool autoinc) {
Sissors 0:d77ea45fa625 29 //Check if it is an allowed address
Sissors 0:d77ea45fa625 30 switch ((uint32_t) address >> 20) {
Sissors 0:d77ea45fa625 31 case 0x000:
Sissors 0:d77ea45fa625 32 case 0x1FF:
Sissors 0:d77ea45fa625 33 case 0x200:
Sissors 0:d77ea45fa625 34 case 0x400:
Sissors 0:d77ea45fa625 35 break;
Sissors 0:d77ea45fa625 36 default:
Sissors 0:d77ea45fa625 37 return -1;
Sissors 0:d77ea45fa625 38 }
Sissors 0:d77ea45fa625 39
Sissors 0:d77ea45fa625 40 char _size;
Sissors 3:34f5bf8adfa0 41
Sissors 0:d77ea45fa625 42 switch (wordsize) {
Sissors 0:d77ea45fa625 43 case 8:
Sissors 0:d77ea45fa625 44 _size = 1;
Sissors 0:d77ea45fa625 45 break;
Sissors 0:d77ea45fa625 46 case 16:
Sissors 0:d77ea45fa625 47 _size = 2;
Sissors 0:d77ea45fa625 48 break;
Sissors 0:d77ea45fa625 49 case 32:
Sissors 0:d77ea45fa625 50 _size = 0;
Sissors 0:d77ea45fa625 51 break;
Sissors 0:d77ea45fa625 52 default:
Sissors 0:d77ea45fa625 53 _size = 1;
Sissors 0:d77ea45fa625 54 }
Sissors 0:d77ea45fa625 55
Sissors 0:d77ea45fa625 56 //Check if source or destination
Sissors 0:d77ea45fa625 57 if (source) {
Sissors 2:fe2fcaa72434 58 SAR = address;
Sissors 2:fe2fcaa72434 59 DCR &= ~(7<<20);
Sissors 2:fe2fcaa72434 60 DCR |= autoinc << 22;
Sissors 2:fe2fcaa72434 61 DCR |= _size << 20;
Sissors 0:d77ea45fa625 62 } else {
Sissors 2:fe2fcaa72434 63 DAR = address;
Sissors 2:fe2fcaa72434 64 DCR &= ~(7<<17);
Sissors 2:fe2fcaa72434 65 DCR |= autoinc << 19;
Sissors 2:fe2fcaa72434 66 DCR |= _size << 17;
Sissors 0:d77ea45fa625 67 }
Sissors 3:34f5bf8adfa0 68
Sissors 0:d77ea45fa625 69 return 0;
Sissors 0:d77ea45fa625 70 };
Sissors 0:d77ea45fa625 71
Sissors 0:d77ea45fa625 72 int SimpleDMA::trigger(SimpleDMA_Trigger trig){
Sissors 1:0b73b00bcee8 73
Sissors 2:fe2fcaa72434 74 CHCFG = trig;
Sissors 0:d77ea45fa625 75 return 0;
Sissors 0:d77ea45fa625 76 }
Sissors 0:d77ea45fa625 77
Sissors 3:34f5bf8adfa0 78
Sissors 4:c3a84c6c432c 79 int SimpleDMA::start(int length) {
Sissors 3:34f5bf8adfa0 80 if (auto_channel)
Sissors 3:34f5bf8adfa0 81 _channel = getFreeChannel();
Sissors 3:34f5bf8adfa0 82 else
Sissors 3:34f5bf8adfa0 83 while(isBusy());
Sissors 2:fe2fcaa72434 84
Sissors 0:d77ea45fa625 85 if (length > 0xFFFFF)
Sissors 0:d77ea45fa625 86 return -1;
Sissors 4:c3a84c6c432c 87
Sissors 4:c3a84c6c432c 88 DCR |= (1UL<<31);
Sissors 3:34f5bf8adfa0 89 irq_owner[_channel] = this;
Sissors 0:d77ea45fa625 90
Sissors 2:fe2fcaa72434 91 //Set registers:
Sissors 2:fe2fcaa72434 92 DMA0->DMA[_channel].SAR = SAR;
Sissors 2:fe2fcaa72434 93 DMA0->DMA[_channel].DAR = DAR;
Sissors 2:fe2fcaa72434 94 DMA0->DMA[_channel].DCR = DCR;
Sissors 2:fe2fcaa72434 95
Sissors 2:fe2fcaa72434 96 //Set trigger
Sissors 2:fe2fcaa72434 97 DMAMUX0->CHCFG[_channel] = CHCFG;
Sissors 2:fe2fcaa72434 98
Sissors 2:fe2fcaa72434 99 //Set length
Sissors 2:fe2fcaa72434 100 DMA0->DMA[_channel].DSR_BCR = length;
Sissors 1:0b73b00bcee8 101
Sissors 0:d77ea45fa625 102 //Start
Sissors 0:d77ea45fa625 103 DMAMUX0->CHCFG[_channel] |= 1<<7;
Sissors 0:d77ea45fa625 104
Sissors 0:d77ea45fa625 105 return 0;
Sissors 0:d77ea45fa625 106 }
Sissors 0:d77ea45fa625 107
Sissors 0:d77ea45fa625 108 void SimpleDMA::channel(int chan) {
Sissors 3:34f5bf8adfa0 109 if (chan == -1) {
Sissors 3:34f5bf8adfa0 110 auto_channel = true;
Sissors 3:34f5bf8adfa0 111 _channel = 0;
Sissors 3:34f5bf8adfa0 112 } else {
Sissors 3:34f5bf8adfa0 113 auto_channel = false;
Sissors 3:34f5bf8adfa0 114 if (chan >= 0 && chan < DMA_CHANNELS)
Sissors 3:34f5bf8adfa0 115 _channel = chan;
Sissors 3:34f5bf8adfa0 116 else
Sissors 3:34f5bf8adfa0 117 _channel = 3;
Sissors 3:34f5bf8adfa0 118 }
Sissors 0:d77ea45fa625 119 }
Sissors 0:d77ea45fa625 120
Sissors 3:34f5bf8adfa0 121 bool SimpleDMA::isBusy( int channel ) {
Sissors 2:fe2fcaa72434 122 //Busy bit doesn't work as I expect it to do, so just check if counter is at zero
Sissors 2:fe2fcaa72434 123 //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
Sissors 3:34f5bf8adfa0 124 if (channel == -1)
Sissors 3:34f5bf8adfa0 125 channel = _channel;
Sissors 3:34f5bf8adfa0 126
Sissors 3:34f5bf8adfa0 127 return (DMA0->DMA[channel].DSR_BCR & 0xFFFFFF);
Sissors 1:0b73b00bcee8 128 }
Sissors 1:0b73b00bcee8 129
Sissors 1:0b73b00bcee8 130 void SimpleDMA::irq_handler(void) {
Sissors 1:0b73b00bcee8 131 DMAMUX0->CHCFG[_channel] = 0;
Sissors 2:fe2fcaa72434 132 DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ;
Sissors 1:0b73b00bcee8 133 _callback.call();
Sissors 1:0b73b00bcee8 134 }