Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

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