A simple library to access the DMA functionality.

Fork of SimpleDMA by Erik -

Committer:
Sissors
Date:
Sun Dec 22 21:42:49 2013 +0000
Revision:
2:fe2fcaa72434
Parent:
1:0b73b00bcee8
Child:
3:34f5bf8adfa0
v1.0 KL25Z

Who changed what in which revision?

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