Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Thu Feb 18 07:32:20 2016 +0000
Revision:
47:df7a88cd249c
Parent:
45:c42166b2878c
Child:
48:058ace2aed1d
3-channel linked DMA scheme for CCD image capture working

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 47:df7a88cd249c 8 SimpleDMA::SimpleDMA(int channel)
mjr 47:df7a88cd249c 9 {
mjr 45:c42166b2878c 10 this->channel(channel);
mjr 45:c42166b2878c 11
mjr 45:c42166b2878c 12 //Enable DMA
mjr 45:c42166b2878c 13 SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux
mjr 45:c42166b2878c 14 SIM->SCGC7 |= 1<<8; //Enable clock to DMA
mjr 45:c42166b2878c 15
mjr 45:c42166b2878c 16 trigger(Trigger_ALWAYS);
mjr 45:c42166b2878c 17
mjr 45:c42166b2878c 18 NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
mjr 45:c42166b2878c 19 NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
mjr 45:c42166b2878c 20 NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
mjr 45:c42166b2878c 21 NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
mjr 45:c42166b2878c 22 NVIC_EnableIRQ(DMA0_IRQn);
mjr 45:c42166b2878c 23 NVIC_EnableIRQ(DMA1_IRQn);
mjr 45:c42166b2878c 24 NVIC_EnableIRQ(DMA2_IRQn);
mjr 45:c42166b2878c 25 NVIC_EnableIRQ(DMA3_IRQn);
mjr 45:c42166b2878c 26
mjr 47:df7a88cd249c 27 // presume no link channels
mjr 47:df7a88cd249c 28 linkMode = 0;
mjr 47:df7a88cd249c 29 linkChannel1 = 0;
mjr 47:df7a88cd249c 30 linkChannel2 = 0;
mjr 47:df7a88cd249c 31
mjr 45:c42166b2878c 32 // presume cycle-steal mode
mjr 45:c42166b2878c 33 cycle_steal = true;
mjr 45:c42166b2878c 34 }
mjr 45:c42166b2878c 35
mjr 47:df7a88cd249c 36 int SimpleDMA::start(uint32_t length)
mjr 47:df7a88cd249c 37 {
mjr 45:c42166b2878c 38 if (auto_channel)
mjr 45:c42166b2878c 39 _channel = getFreeChannel();
mjr 45:c42166b2878c 40 else
mjr 45:c42166b2878c 41 while(isBusy());
mjr 45:c42166b2878c 42
mjr 45:c42166b2878c 43 if (length > DMA_DSR_BCR_BCR_MASK)
mjr 45:c42166b2878c 44 return -1;
mjr 45:c42166b2878c 45
mjr 45:c42166b2878c 46 irq_owner[_channel] = this;
mjr 45:c42166b2878c 47
mjr 45:c42166b2878c 48 DMA0->DMA[_channel].SAR = _source;
mjr 45:c42166b2878c 49 DMA0->DMA[_channel].DAR = _destination;
mjr 45:c42166b2878c 50 DMA0->DMA[_channel].DSR_BCR = length;
mjr 45:c42166b2878c 51 DMAMUX0->CHCFG[_channel] = _trigger;
mjr 45:c42166b2878c 52
mjr 45:c42166b2878c 53 uint32_t config =
mjr 45:c42166b2878c 54 DMA_DCR_EINT_MASK
mjr 45:c42166b2878c 55 | DMA_DCR_ERQ_MASK
mjr 47:df7a88cd249c 56 | DMA_DCR_EADREQ_MASK
mjr 45:c42166b2878c 57 | (cycle_steal ? DMA_DCR_CS_MASK : 0)
mjr 45:c42166b2878c 58 | (source_inc << DMA_DCR_SINC_SHIFT)
mjr 45:c42166b2878c 59 | (destination_inc << DMA_DCR_DINC_SHIFT)
mjr 47:df7a88cd249c 60 | ((linkChannel1 & 3) << DMA_DCR_LCH1_SHIFT)
mjr 47:df7a88cd249c 61 | ((linkChannel2 & 3) << DMA_DCR_LCH2_SHIFT)
mjr 47:df7a88cd249c 62 | ((linkMode & 3) << DMA_DCR_LINKCC_SHIFT);
mjr 47:df7a88cd249c 63
mjr 45:c42166b2878c 64 switch (source_size) {
mjr 45:c42166b2878c 65 case 8:
mjr 45:c42166b2878c 66 config |= 1 << DMA_DCR_SSIZE_SHIFT;
mjr 45:c42166b2878c 67 break;
mjr 45:c42166b2878c 68 case 16:
mjr 45:c42166b2878c 69 config |= 2 << DMA_DCR_SSIZE_SHIFT;
mjr 45:c42166b2878c 70 break;
mjr 45:c42166b2878c 71 }
mjr 45:c42166b2878c 72 switch (destination_size) {
mjr 45:c42166b2878c 73 case 8:
mjr 45:c42166b2878c 74 config |= 1 << DMA_DCR_DSIZE_SHIFT;
mjr 45:c42166b2878c 75 break;
mjr 45:c42166b2878c 76 case 16:
mjr 45:c42166b2878c 77 config |= 2 << DMA_DCR_DSIZE_SHIFT;
mjr 45:c42166b2878c 78 break;
mjr 45:c42166b2878c 79 }
mjr 45:c42166b2878c 80
mjr 45:c42166b2878c 81 DMA0->DMA[_channel].DCR = config;
mjr 47:df7a88cd249c 82
mjr 47:df7a88cd249c 83 //$$$
mjr 47:df7a88cd249c 84 static int iii; if (iii++ < 3)
mjr 47:df7a88cd249c 85 printf("DMA channel %d: mode %04x, source %08lx, dest %08lx, trigger %d, len %d\r\n", _channel, config, _source, _destination, _trigger, length);
mjr 45:c42166b2878c 86
mjr 47:df7a88cd249c 87 //Start - set ENBL bit in the DMAMUX channel config register
mjr 45:c42166b2878c 88 DMAMUX0->CHCFG[_channel] |= 1<<7;
mjr 45:c42166b2878c 89
mjr 45:c42166b2878c 90 return 0;
mjr 45:c42166b2878c 91 }
mjr 45:c42166b2878c 92
mjr 47:df7a88cd249c 93 void SimpleDMA::link(SimpleDMA &dest, bool all)
mjr 47:df7a88cd249c 94 {
mjr 47:df7a88cd249c 95 linkChannel1 = dest._channel;
mjr 47:df7a88cd249c 96 linkChannel2 = 0;
mjr 47:df7a88cd249c 97 linkMode = all ? 3 : 2;
mjr 47:df7a88cd249c 98 }
mjr 47:df7a88cd249c 99
mjr 47:df7a88cd249c 100 void SimpleDMA::link(SimpleDMA &dest1, SimpleDMA &dest2)
mjr 47:df7a88cd249c 101 {
mjr 47:df7a88cd249c 102 linkChannel1 = dest1._channel;
mjr 47:df7a88cd249c 103 linkChannel2 = dest2._channel;
mjr 47:df7a88cd249c 104 linkMode = 1;
mjr 47:df7a88cd249c 105 }
mjr 47:df7a88cd249c 106
mjr 47:df7a88cd249c 107
mjr 45:c42166b2878c 108 int SimpleDMA::restart(uint32_t length)
mjr 45:c42166b2878c 109 {
mjr 45:c42166b2878c 110 DMA0->DMA[_channel].SAR = _source;
mjr 45:c42166b2878c 111 DMA0->DMA[_channel].DAR = _destination;
mjr 45:c42166b2878c 112 DMA0->DMA[_channel].DSR_BCR = length;
mjr 45:c42166b2878c 113 DMAMUX0->CHCFG[_channel] |= 1<<7;
mjr 45:c42166b2878c 114 return 0;
mjr 45:c42166b2878c 115 }
mjr 45:c42166b2878c 116
mjr 47:df7a88cd249c 117 bool SimpleDMA::isBusy( int channel )
mjr 47:df7a88cd249c 118 {
mjr 45:c42166b2878c 119 //Busy bit doesn't work as I expect it to do, so just check if counter is at zero
mjr 45:c42166b2878c 120 //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
mjr 45:c42166b2878c 121 if (channel == -1)
mjr 45:c42166b2878c 122 channel = _channel;
mjr 45:c42166b2878c 123
mjr 45:c42166b2878c 124 return (DMA0->DMA[channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 125 }
mjr 45:c42166b2878c 126
mjr 45:c42166b2878c 127 /*****************************************************************/
mjr 45:c42166b2878c 128 uint32_t SimpleDMA::remaining(int channel)
mjr 45:c42166b2878c 129 {
mjr 45:c42166b2878c 130 // note that the BCR register always reads with binary 1110
mjr 45:c42166b2878c 131 // (if the configuration is correct) or 1111 (if there's an
mjr 45:c42166b2878c 132 // error in the configuration) in bits 23-20, so we need
mjr 45:c42166b2878c 133 // to mask these out - only keep bits 19-0 (low-order 20
mjr 45:c42166b2878c 134 // bits = 0xFFFFF)
mjr 45:c42166b2878c 135 return (DMA0->DMA[channel < 0 ? _channel : channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 136 }
mjr 45:c42166b2878c 137
mjr 45:c42166b2878c 138 /*****************************************************************/
mjr 47:df7a88cd249c 139 void SimpleDMA::irq_handler(void)
mjr 47:df7a88cd249c 140 {
mjr 45:c42166b2878c 141 DMAMUX0->CHCFG[_channel] = 0;
mjr 45:c42166b2878c 142 DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ;
mjr 45:c42166b2878c 143 _callback.call();
mjr 45:c42166b2878c 144 }
mjr 45:c42166b2878c 145
mjr 47:df7a88cd249c 146 void SimpleDMA::irq_handler0( void )
mjr 47:df7a88cd249c 147 {
mjr 45:c42166b2878c 148 if (irq_owner[0]!=NULL)
mjr 45:c42166b2878c 149 irq_owner[0]->irq_handler();
mjr 45:c42166b2878c 150 }
mjr 45:c42166b2878c 151
mjr 47:df7a88cd249c 152 void SimpleDMA::irq_handler1( void )
mjr 47:df7a88cd249c 153 {
mjr 45:c42166b2878c 154 if (irq_owner[1]!=NULL)
mjr 45:c42166b2878c 155 irq_owner[1]->irq_handler();
mjr 45:c42166b2878c 156 }
mjr 45:c42166b2878c 157
mjr 47:df7a88cd249c 158 void SimpleDMA::irq_handler2( void )
mjr 47:df7a88cd249c 159 {
mjr 45:c42166b2878c 160 if (irq_owner[2]!=NULL)
mjr 45:c42166b2878c 161 irq_owner[2]->irq_handler();
mjr 45:c42166b2878c 162 }
mjr 45:c42166b2878c 163
mjr 47:df7a88cd249c 164 void SimpleDMA::irq_handler3( void )
mjr 47:df7a88cd249c 165 {
mjr 45:c42166b2878c 166 if (irq_owner[3]!=NULL)
mjr 45:c42166b2878c 167 irq_owner[3]->irq_handler();
mjr 45:c42166b2878c 168 }
mjr 45:c42166b2878c 169 #endif