Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
mjr
Date:
Fri Feb 03 20:50:02 2017 +0000
Revision:
76:7f5912b6340e
Parent:
54:fd77a6b2f76c
Child:
100:1ff35c07217c
Rework flash driver to make it truly stable (hopefully to 100% reliability); host-loaded configuration; performance improvements; more performance diagnostics.

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 76:7f5912b6340e 4 // DMA - Register Layout Typedef (from mbed MKL25Z4.h)
mjr 76:7f5912b6340e 5 // Break out the DMA[n] register array as a named struct,
mjr 76:7f5912b6340e 6 // so that we can create pointers to it.
mjr 76:7f5912b6340e 7 typedef struct {
mjr 76:7f5912b6340e 8 __IO uint32_t SAR; /**< Source Address Register, array offset: 0x100, array step: 0x10 */
mjr 76:7f5912b6340e 9 __IO uint32_t DAR; /**< Destination Address Register, array offset: 0x104, array step: 0x10 */
mjr 76:7f5912b6340e 10 union { /* offset: 0x108, array step: 0x10 */
mjr 76:7f5912b6340e 11 __IO uint32_t DSR_BCR; /**< DMA Status Register / Byte Count Register, array offset: 0x108, array step: 0x10 */
mjr 76:7f5912b6340e 12 struct { /* offset: 0x108, array step: 0x10 */
mjr 76:7f5912b6340e 13 uint8_t RESERVED_0[3];
mjr 76:7f5912b6340e 14 __IO uint8_t DSR; /**< DMA_DSR0 register...DMA_DSR3 register., array offset: 0x10B, array step: 0x10 */
mjr 76:7f5912b6340e 15 } DMA_DSR_ACCESS8BIT;
mjr 76:7f5912b6340e 16 };
mjr 76:7f5912b6340e 17 __IO uint32_t DCR; /**< DMA Control Register, array offset: 0x10C, array step: 0x10 */
mjr 76:7f5912b6340e 18 } DMA_Reg_Type;
mjr 76:7f5912b6340e 19 typedef struct {
mjr 76:7f5912b6340e 20 union { /* offset: 0x0 */
mjr 76:7f5912b6340e 21 __IO uint8_t REQC_ARR[4]; /**< DMA_REQC0 register...DMA_REQC3 register., array offset: 0x0, array step: 0x1 */
mjr 76:7f5912b6340e 22 };
mjr 76:7f5912b6340e 23 uint8_t RESERVED_0[252];
mjr 76:7f5912b6340e 24 DMA_Reg_Type DMA[4];
mjr 76:7f5912b6340e 25 } MyDMA_Type;
mjr 45:c42166b2878c 26
mjr 45:c42166b2878c 27
mjr 45:c42166b2878c 28 SimpleDMA *SimpleDMA::irq_owner[4] = {NULL};
mjr 45:c42166b2878c 29
mjr 48:058ace2aed1d 30 void SimpleDMA::class_init()
mjr 48:058ace2aed1d 31 {
mjr 48:058ace2aed1d 32 static bool inited = false;
mjr 48:058ace2aed1d 33 if (!inited)
mjr 48:058ace2aed1d 34 {
mjr 48:058ace2aed1d 35 NVIC_SetVector(DMA0_IRQn, (uint32_t)&irq_handler0);
mjr 48:058ace2aed1d 36 NVIC_SetVector(DMA1_IRQn, (uint32_t)&irq_handler1);
mjr 48:058ace2aed1d 37 NVIC_SetVector(DMA2_IRQn, (uint32_t)&irq_handler2);
mjr 48:058ace2aed1d 38 NVIC_SetVector(DMA3_IRQn, (uint32_t)&irq_handler3);
mjr 48:058ace2aed1d 39 NVIC_EnableIRQ(DMA0_IRQn);
mjr 48:058ace2aed1d 40 NVIC_EnableIRQ(DMA1_IRQn);
mjr 48:058ace2aed1d 41 NVIC_EnableIRQ(DMA2_IRQn);
mjr 48:058ace2aed1d 42 NVIC_EnableIRQ(DMA3_IRQn);
mjr 48:058ace2aed1d 43 inited = true;
mjr 48:058ace2aed1d 44 }
mjr 48:058ace2aed1d 45 }
mjr 48:058ace2aed1d 46
mjr 47:df7a88cd249c 47 SimpleDMA::SimpleDMA(int channel)
mjr 47:df7a88cd249c 48 {
mjr 48:058ace2aed1d 49 class_init();
mjr 54:fd77a6b2f76c 50
mjr 54:fd77a6b2f76c 51 // remember the channel (-1 means we automatically select on start())
mjr 45:c42166b2878c 52 this->channel(channel);
mjr 45:c42166b2878c 53
mjr 54:fd77a6b2f76c 54 // Enable DMA
mjr 54:fd77a6b2f76c 55 SIM->SCGC6 |= 1<<1; // Enable clock to DMA mux
mjr 54:fd77a6b2f76c 56 SIM->SCGC7 |= 1<<8; // Enable clock to DMA
mjr 45:c42166b2878c 57
mjr 54:fd77a6b2f76c 58 // use the "always" software trigger by default
mjr 45:c42166b2878c 59 trigger(Trigger_ALWAYS);
mjr 45:c42166b2878c 60
mjr 47:df7a88cd249c 61 // presume no link channels
mjr 47:df7a88cd249c 62 linkMode = 0;
mjr 47:df7a88cd249c 63 linkChannel1 = 0;
mjr 47:df7a88cd249c 64 linkChannel2 = 0;
mjr 45:c42166b2878c 65 }
mjr 45:c42166b2878c 66
mjr 54:fd77a6b2f76c 67 int SimpleDMA::start(uint32_t length, bool wait)
mjr 48:058ace2aed1d 68 {
mjr 45:c42166b2878c 69 if (auto_channel)
mjr 45:c42166b2878c 70 _channel = getFreeChannel();
mjr 54:fd77a6b2f76c 71 else if (!wait && isBusy())
mjr 54:fd77a6b2f76c 72 return -1;
mjr 54:fd77a6b2f76c 73 else {
mjr 54:fd77a6b2f76c 74 while (isBusy());
mjr 54:fd77a6b2f76c 75 }
mjr 45:c42166b2878c 76
mjr 45:c42166b2878c 77 if (length > DMA_DSR_BCR_BCR_MASK)
mjr 45:c42166b2878c 78 return -1;
mjr 45:c42166b2878c 79
mjr 45:c42166b2878c 80 irq_owner[_channel] = this;
mjr 76:7f5912b6340e 81
mjr 76:7f5912b6340e 82 // get pointers to the register locations
mjr 76:7f5912b6340e 83 volatile uint8_t *chcfg = &DMAMUX0->CHCFG[_channel];
mjr 76:7f5912b6340e 84 volatile DMA_Reg_Type *dmareg = (volatile DMA_Reg_Type *)&DMA0->DMA[_channel];
mjr 48:058ace2aed1d 85
mjr 48:058ace2aed1d 86 // disable the channel while we're setting it up
mjr 76:7f5912b6340e 87 *chcfg = 0;
mjr 54:fd77a6b2f76c 88
mjr 54:fd77a6b2f76c 89 // set the DONE flag on the channel
mjr 76:7f5912b6340e 90 dmareg->DSR_BCR = DMA_DSR_BCR_DONE_MASK;
mjr 48:058ace2aed1d 91
mjr 45:c42166b2878c 92 uint32_t config =
mjr 45:c42166b2878c 93 DMA_DCR_EINT_MASK
mjr 45:c42166b2878c 94 | DMA_DCR_ERQ_MASK
mjr 48:058ace2aed1d 95 | DMA_DCR_CS_MASK
mjr 54:fd77a6b2f76c 96 | ((source_inc & 0x01) << DMA_DCR_SINC_SHIFT)
mjr 54:fd77a6b2f76c 97 | ((destination_inc & 0x01) << DMA_DCR_DINC_SHIFT)
mjr 54:fd77a6b2f76c 98 | ((linkChannel1 & 0x03) << DMA_DCR_LCH1_SHIFT)
mjr 54:fd77a6b2f76c 99 | ((linkChannel2 & 0x03) << DMA_DCR_LCH2_SHIFT)
mjr 54:fd77a6b2f76c 100 | ((linkMode & 0x03) << DMA_DCR_LINKCC_SHIFT);
mjr 47:df7a88cd249c 101
mjr 54:fd77a6b2f76c 102 switch (source_size)
mjr 54:fd77a6b2f76c 103 {
mjr 54:fd77a6b2f76c 104 case 8:
mjr 54:fd77a6b2f76c 105 config |= 1 << DMA_DCR_SSIZE_SHIFT;
mjr 54:fd77a6b2f76c 106 break;
mjr 54:fd77a6b2f76c 107
mjr 54:fd77a6b2f76c 108 case 16:
mjr 54:fd77a6b2f76c 109 config |= 2 << DMA_DCR_SSIZE_SHIFT;
mjr 54:fd77a6b2f76c 110 break;
mjr 45:c42166b2878c 111 }
mjr 54:fd77a6b2f76c 112
mjr 54:fd77a6b2f76c 113 switch (destination_size)
mjr 54:fd77a6b2f76c 114 {
mjr 54:fd77a6b2f76c 115 case 8:
mjr 54:fd77a6b2f76c 116 config |= 1 << DMA_DCR_DSIZE_SHIFT;
mjr 54:fd77a6b2f76c 117 break;
mjr 54:fd77a6b2f76c 118
mjr 54:fd77a6b2f76c 119 case 16:
mjr 54:fd77a6b2f76c 120 config |= 2 << DMA_DCR_DSIZE_SHIFT;
mjr 54:fd77a6b2f76c 121 break;
mjr 45:c42166b2878c 122 }
mjr 45:c42166b2878c 123
mjr 76:7f5912b6340e 124 dmareg->SAR = _source;
mjr 76:7f5912b6340e 125 dmareg->DAR = _destination;
mjr 76:7f5912b6340e 126 *chcfg = _trigger;
mjr 76:7f5912b6340e 127 dmareg->DCR = config;
mjr 76:7f5912b6340e 128 dmareg->DSR_BCR = length;
mjr 47:df7a88cd249c 129
mjr 54:fd77a6b2f76c 130 // Start - set the ENBL bit in the DMAMUX channel config register
mjr 76:7f5912b6340e 131 *chcfg |= DMAMUX_CHCFG_ENBL_MASK;
mjr 54:fd77a6b2f76c 132
mjr 45:c42166b2878c 133 return 0;
mjr 45:c42166b2878c 134 }
mjr 45:c42166b2878c 135
mjr 47:df7a88cd249c 136 void SimpleDMA::link(SimpleDMA &dest, bool all)
mjr 47:df7a88cd249c 137 {
mjr 47:df7a88cd249c 138 linkChannel1 = dest._channel;
mjr 47:df7a88cd249c 139 linkChannel2 = 0;
mjr 47:df7a88cd249c 140 linkMode = all ? 3 : 2;
mjr 47:df7a88cd249c 141 }
mjr 47:df7a88cd249c 142
mjr 47:df7a88cd249c 143 void SimpleDMA::link(SimpleDMA &dest1, SimpleDMA &dest2)
mjr 47:df7a88cd249c 144 {
mjr 47:df7a88cd249c 145 linkChannel1 = dest1._channel;
mjr 47:df7a88cd249c 146 linkChannel2 = dest2._channel;
mjr 47:df7a88cd249c 147 linkMode = 1;
mjr 47:df7a88cd249c 148 }
mjr 47:df7a88cd249c 149
mjr 47:df7a88cd249c 150
mjr 47:df7a88cd249c 151 bool SimpleDMA::isBusy( int channel )
mjr 47:df7a88cd249c 152 {
mjr 45:c42166b2878c 153 if (channel == -1)
mjr 45:c42166b2878c 154 channel = _channel;
mjr 54:fd77a6b2f76c 155
mjr 54:fd77a6b2f76c 156 // The busy bit doesn't seem to work as expected. Just check if
mjr 54:fd77a6b2f76c 157 // counter is at zero - if not, treat it as busy.
mjr 54:fd77a6b2f76c 158 //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
mjr 45:c42166b2878c 159 return (DMA0->DMA[channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 160 }
mjr 45:c42166b2878c 161
mjr 45:c42166b2878c 162 /*****************************************************************/
mjr 45:c42166b2878c 163 uint32_t SimpleDMA::remaining(int channel)
mjr 45:c42166b2878c 164 {
mjr 45:c42166b2878c 165 // note that the BCR register always reads with binary 1110
mjr 45:c42166b2878c 166 // (if the configuration is correct) or 1111 (if there's an
mjr 45:c42166b2878c 167 // error in the configuration) in bits 23-20, so we need
mjr 45:c42166b2878c 168 // to mask these out - only keep bits 19-0 (low-order 20
mjr 45:c42166b2878c 169 // bits = 0xFFFFF)
mjr 45:c42166b2878c 170 return (DMA0->DMA[channel < 0 ? _channel : channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 171 }
mjr 45:c42166b2878c 172
mjr 45:c42166b2878c 173 /*****************************************************************/
mjr 47:df7a88cd249c 174 void SimpleDMA::irq_handler(void)
mjr 47:df7a88cd249c 175 {
mjr 45:c42166b2878c 176 DMAMUX0->CHCFG[_channel] = 0;
mjr 54:fd77a6b2f76c 177 DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK;
mjr 45:c42166b2878c 178 _callback.call();
mjr 45:c42166b2878c 179 }
mjr 45:c42166b2878c 180
mjr 47:df7a88cd249c 181 void SimpleDMA::irq_handler0( void )
mjr 47:df7a88cd249c 182 {
mjr 54:fd77a6b2f76c 183 if (irq_owner[0] != NULL)
mjr 45:c42166b2878c 184 irq_owner[0]->irq_handler();
mjr 45:c42166b2878c 185 }
mjr 45:c42166b2878c 186
mjr 47:df7a88cd249c 187 void SimpleDMA::irq_handler1( void )
mjr 47:df7a88cd249c 188 {
mjr 54:fd77a6b2f76c 189 if (irq_owner[1] != NULL)
mjr 45:c42166b2878c 190 irq_owner[1]->irq_handler();
mjr 45:c42166b2878c 191 }
mjr 45:c42166b2878c 192
mjr 47:df7a88cd249c 193 void SimpleDMA::irq_handler2( void )
mjr 47:df7a88cd249c 194 {
mjr 54:fd77a6b2f76c 195 if (irq_owner[2] != NULL)
mjr 45:c42166b2878c 196 irq_owner[2]->irq_handler();
mjr 45:c42166b2878c 197 }
mjr 45:c42166b2878c 198
mjr 47:df7a88cd249c 199 void SimpleDMA::irq_handler3( void )
mjr 47:df7a88cd249c 200 {
mjr 54:fd77a6b2f76c 201 if (irq_owner[3] != NULL)
mjr 45:c42166b2878c 202 irq_owner[3]->irq_handler();
mjr 45:c42166b2878c 203 }
mjr 54:fd77a6b2f76c 204 #endif