Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Mon Feb 15 20:30:32 2016 +0000
Revision:
45:c42166b2878c
Child:
47:df7a88cd249c
More work in progress on CCD speedups;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mjr 45:c42166b2878c 1 #if defined TARGET_KL25Z || defined TARGET_KL46Z
mjr 45:c42166b2878c 2 #include "SimpleDMA.h"
mjr 45:c42166b2878c 3
mjr 45:c42166b2878c 4
mjr 45:c42166b2878c 5
mjr 45:c42166b2878c 6 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL};
mjr 45:c42166b2878c 7
mjr 45:c42166b2878c 8 SimpleDMA::SimpleDMA(int channel) {
mjr 45:c42166b2878c 9 this->channel(channel);
mjr 45:c42166b2878c 10
mjr 45:c42166b2878c 11 //Enable DMA
mjr 45:c42166b2878c 12 SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux
mjr 45:c42166b2878c 13 SIM->SCGC7 |= 1<<8; //Enable clock to DMA
mjr 45:c42166b2878c 14
mjr 45:c42166b2878c 15 trigger(Trigger_ALWAYS);
mjr 45:c42166b2878c 16
mjr 45:c42166b2878c 17 NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
mjr 45:c42166b2878c 18 NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
mjr 45:c42166b2878c 19 NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
mjr 45:c42166b2878c 20 NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
mjr 45:c42166b2878c 21 NVIC_EnableIRQ(DMA0_IRQn);
mjr 45:c42166b2878c 22 NVIC_EnableIRQ(DMA1_IRQn);
mjr 45:c42166b2878c 23 NVIC_EnableIRQ(DMA2_IRQn);
mjr 45:c42166b2878c 24 NVIC_EnableIRQ(DMA3_IRQn);
mjr 45:c42166b2878c 25
mjr 45:c42166b2878c 26 // presume cycle-steal mode
mjr 45:c42166b2878c 27 cycle_steal = true;
mjr 45:c42166b2878c 28 }
mjr 45:c42166b2878c 29
mjr 45:c42166b2878c 30 // Figure the circular buffer MOD bit pattern (SMOD or DMOD)
mjr 45:c42166b2878c 31 // for a given circular buffer size. The buffer size is
mjr 45:c42166b2878c 32 // required to be a power of 2 from 16 to 256K.
mjr 45:c42166b2878c 33 static uint32_t modsize_to_modbits(uint32_t siz)
mjr 45:c42166b2878c 34 {
mjr 45:c42166b2878c 35 // The bit pattern is such that 2^(bits+3), so we basically
mjr 45:c42166b2878c 36 // need to take the base-2 log of the size. Zero has the
mjr 45:c42166b2878c 37 // special meaning that the circular buffer is disabled.
mjr 45:c42166b2878c 38 uint32_t bits = 0;
mjr 45:c42166b2878c 39 for (bits = 0 ; siz >= 16 ; siz >>= 1, ++bits) ;
mjr 45:c42166b2878c 40
mjr 45:c42166b2878c 41 // return the result, which can't be over binary 1111
mjr 45:c42166b2878c 42 return bits & 0xF;
mjr 45:c42166b2878c 43 }
mjr 45:c42166b2878c 44
mjr 45:c42166b2878c 45 int SimpleDMA::start(uint32_t length) {
mjr 45:c42166b2878c 46 if (auto_channel)
mjr 45:c42166b2878c 47 _channel = getFreeChannel();
mjr 45:c42166b2878c 48 else
mjr 45:c42166b2878c 49 while(isBusy());
mjr 45:c42166b2878c 50
mjr 45:c42166b2878c 51 if (length > DMA_DSR_BCR_BCR_MASK)
mjr 45:c42166b2878c 52 return -1;
mjr 45:c42166b2878c 53
mjr 45:c42166b2878c 54 irq_owner[_channel] = this;
mjr 45:c42166b2878c 55
mjr 45:c42166b2878c 56 DMA0->DMA[_channel].SAR = _source;
mjr 45:c42166b2878c 57 DMA0->DMA[_channel].DAR = _destination;
mjr 45:c42166b2878c 58 DMA0->DMA[_channel].DSR_BCR = length;
mjr 45:c42166b2878c 59 DMAMUX0->CHCFG[_channel] = _trigger;
mjr 45:c42166b2878c 60
mjr 45:c42166b2878c 61 uint32_t config =
mjr 45:c42166b2878c 62 DMA_DCR_EINT_MASK
mjr 45:c42166b2878c 63 | DMA_DCR_ERQ_MASK
mjr 45:c42166b2878c 64 | (cycle_steal ? DMA_DCR_CS_MASK : 0)
mjr 45:c42166b2878c 65 | (source_inc << DMA_DCR_SINC_SHIFT)
mjr 45:c42166b2878c 66 | (modsize_to_modbits(source_mod) << DMA_DCR_SMOD_SHIFT)
mjr 45:c42166b2878c 67 | (destination_inc << DMA_DCR_DINC_SHIFT)
mjr 45:c42166b2878c 68 | (modsize_to_modbits(destination_mod) << DMA_DCR_DMOD_SHIFT);
mjr 45:c42166b2878c 69 switch (source_size) {
mjr 45:c42166b2878c 70 case 8:
mjr 45:c42166b2878c 71 config |= 1 << DMA_DCR_SSIZE_SHIFT;
mjr 45:c42166b2878c 72 break;
mjr 45:c42166b2878c 73 case 16:
mjr 45:c42166b2878c 74 config |= 2 << DMA_DCR_SSIZE_SHIFT;
mjr 45:c42166b2878c 75 break;
mjr 45:c42166b2878c 76 }
mjr 45:c42166b2878c 77 switch (destination_size) {
mjr 45:c42166b2878c 78 case 8:
mjr 45:c42166b2878c 79 config |= 1 << DMA_DCR_DSIZE_SHIFT;
mjr 45:c42166b2878c 80 break;
mjr 45:c42166b2878c 81 case 16:
mjr 45:c42166b2878c 82 config |= 2 << DMA_DCR_DSIZE_SHIFT;
mjr 45:c42166b2878c 83 break;
mjr 45:c42166b2878c 84 }
mjr 45:c42166b2878c 85
mjr 45:c42166b2878c 86 DMA0->DMA[_channel].DCR = config;
mjr 45:c42166b2878c 87
mjr 45:c42166b2878c 88 //Start
mjr 45:c42166b2878c 89 DMAMUX0->CHCFG[_channel] |= 1<<7;
mjr 45:c42166b2878c 90
mjr 45:c42166b2878c 91 return 0;
mjr 45:c42166b2878c 92 }
mjr 45:c42166b2878c 93
mjr 45:c42166b2878c 94 int SimpleDMA::restart(uint32_t length)
mjr 45:c42166b2878c 95 {
mjr 45:c42166b2878c 96 DMA0->DMA[_channel].SAR = _source;
mjr 45:c42166b2878c 97 DMA0->DMA[_channel].DAR = _destination;
mjr 45:c42166b2878c 98 DMA0->DMA[_channel].DSR_BCR = length;
mjr 45:c42166b2878c 99 DMAMUX0->CHCFG[_channel] |= 1<<7;
mjr 45:c42166b2878c 100 return 0;
mjr 45:c42166b2878c 101 }
mjr 45:c42166b2878c 102
mjr 45:c42166b2878c 103 bool SimpleDMA::isBusy( int channel ) {
mjr 45:c42166b2878c 104 //Busy bit doesn't work as I expect it to do, so just check if counter is at zero
mjr 45:c42166b2878c 105 //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
mjr 45:c42166b2878c 106 if (channel == -1)
mjr 45:c42166b2878c 107 channel = _channel;
mjr 45:c42166b2878c 108
mjr 45:c42166b2878c 109 return (DMA0->DMA[channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 110 }
mjr 45:c42166b2878c 111
mjr 45:c42166b2878c 112 /*****************************************************************/
mjr 45:c42166b2878c 113 uint32_t SimpleDMA::remaining(int channel)
mjr 45:c42166b2878c 114 {
mjr 45:c42166b2878c 115 // note that the BCR register always reads with binary 1110
mjr 45:c42166b2878c 116 // (if the configuration is correct) or 1111 (if there's an
mjr 45:c42166b2878c 117 // error in the configuration) in bits 23-20, so we need
mjr 45:c42166b2878c 118 // to mask these out - only keep bits 19-0 (low-order 20
mjr 45:c42166b2878c 119 // bits = 0xFFFFF)
mjr 45:c42166b2878c 120 return (DMA0->DMA[channel < 0 ? _channel : channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 121 }
mjr 45:c42166b2878c 122
mjr 45:c42166b2878c 123 /*****************************************************************/
mjr 45:c42166b2878c 124 void SimpleDMA::irq_handler(void) {
mjr 45:c42166b2878c 125 DMAMUX0->CHCFG[_channel] = 0;
mjr 45:c42166b2878c 126 DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ;
mjr 45:c42166b2878c 127 _callback.call();
mjr 45:c42166b2878c 128 }
mjr 45:c42166b2878c 129
mjr 45:c42166b2878c 130 void SimpleDMA::irq_handler0( void ) {
mjr 45:c42166b2878c 131 if (irq_owner[0]!=NULL)
mjr 45:c42166b2878c 132 irq_owner[0]->irq_handler();
mjr 45:c42166b2878c 133 }
mjr 45:c42166b2878c 134
mjr 45:c42166b2878c 135 void SimpleDMA::irq_handler1( void ) {
mjr 45:c42166b2878c 136 if (irq_owner[1]!=NULL)
mjr 45:c42166b2878c 137 irq_owner[1]->irq_handler();
mjr 45:c42166b2878c 138 }
mjr 45:c42166b2878c 139
mjr 45:c42166b2878c 140 void SimpleDMA::irq_handler2( void ) {
mjr 45:c42166b2878c 141 if (irq_owner[2]!=NULL)
mjr 45:c42166b2878c 142 irq_owner[2]->irq_handler();
mjr 45:c42166b2878c 143 }
mjr 45:c42166b2878c 144
mjr 45:c42166b2878c 145 void SimpleDMA::irq_handler3( void ) {
mjr 45:c42166b2878c 146 if (irq_owner[3]!=NULL)
mjr 45:c42166b2878c 147 irq_owner[3]->irq_handler();
mjr 45:c42166b2878c 148 }
mjr 45:c42166b2878c 149 #endif