Mirror with some correction

Dependencies:   mbed FastIO FastPWM USBDevice

Committer:
arnoz
Date:
Fri Oct 01 08:19:46 2021 +0000
Revision:
116:7a67265d7c19
Parent:
100:1ff35c07217c
- Correct information regarding your last merge

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 100:1ff35c07217c 69 // prepare the transfer
mjr 100:1ff35c07217c 70 volatile uint8_t *chcfg = prepare(length, wait);
mjr 100:1ff35c07217c 71
mjr 100:1ff35c07217c 72 // check for errors
mjr 100:1ff35c07217c 73 if (chcfg == NULL)
mjr 100:1ff35c07217c 74 return -1;
mjr 100:1ff35c07217c 75
mjr 100:1ff35c07217c 76 // ready to go - set the ENBL bit in the DMAMUX channel config register
mjr 100:1ff35c07217c 77 // to start the trnasfer
mjr 100:1ff35c07217c 78 *chcfg |= DMAMUX_CHCFG_ENBL_MASK;
mjr 100:1ff35c07217c 79
mjr 100:1ff35c07217c 80 // return success
mjr 100:1ff35c07217c 81 return 0;
mjr 100:1ff35c07217c 82 }
mjr 100:1ff35c07217c 83
mjr 100:1ff35c07217c 84 volatile uint8_t *SimpleDMA::prepare(uint32_t length, bool wait)
mjr 100:1ff35c07217c 85 {
mjr 45:c42166b2878c 86 if (auto_channel)
mjr 45:c42166b2878c 87 _channel = getFreeChannel();
mjr 54:fd77a6b2f76c 88 else if (!wait && isBusy())
mjr 100:1ff35c07217c 89 return NULL;
mjr 54:fd77a6b2f76c 90 else {
mjr 54:fd77a6b2f76c 91 while (isBusy());
mjr 54:fd77a6b2f76c 92 }
mjr 45:c42166b2878c 93
mjr 45:c42166b2878c 94 if (length > DMA_DSR_BCR_BCR_MASK)
mjr 100:1ff35c07217c 95 return NULL;
mjr 45:c42166b2878c 96
mjr 45:c42166b2878c 97 irq_owner[_channel] = this;
mjr 76:7f5912b6340e 98
mjr 76:7f5912b6340e 99 // get pointers to the register locations
mjr 76:7f5912b6340e 100 volatile uint8_t *chcfg = &DMAMUX0->CHCFG[_channel];
mjr 76:7f5912b6340e 101 volatile DMA_Reg_Type *dmareg = (volatile DMA_Reg_Type *)&DMA0->DMA[_channel];
mjr 48:058ace2aed1d 102
mjr 48:058ace2aed1d 103 // disable the channel while we're setting it up
mjr 76:7f5912b6340e 104 *chcfg = 0;
mjr 54:fd77a6b2f76c 105
mjr 54:fd77a6b2f76c 106 // set the DONE flag on the channel
mjr 76:7f5912b6340e 107 dmareg->DSR_BCR = DMA_DSR_BCR_DONE_MASK;
mjr 48:058ace2aed1d 108
mjr 45:c42166b2878c 109 uint32_t config =
mjr 45:c42166b2878c 110 DMA_DCR_EINT_MASK
mjr 45:c42166b2878c 111 | DMA_DCR_ERQ_MASK
mjr 48:058ace2aed1d 112 | DMA_DCR_CS_MASK
mjr 54:fd77a6b2f76c 113 | ((source_inc & 0x01) << DMA_DCR_SINC_SHIFT)
mjr 54:fd77a6b2f76c 114 | ((destination_inc & 0x01) << DMA_DCR_DINC_SHIFT)
mjr 54:fd77a6b2f76c 115 | ((linkChannel1 & 0x03) << DMA_DCR_LCH1_SHIFT)
mjr 54:fd77a6b2f76c 116 | ((linkChannel2 & 0x03) << DMA_DCR_LCH2_SHIFT)
mjr 54:fd77a6b2f76c 117 | ((linkMode & 0x03) << DMA_DCR_LINKCC_SHIFT);
mjr 47:df7a88cd249c 118
mjr 54:fd77a6b2f76c 119 switch (source_size)
mjr 54:fd77a6b2f76c 120 {
mjr 54:fd77a6b2f76c 121 case 8:
mjr 54:fd77a6b2f76c 122 config |= 1 << DMA_DCR_SSIZE_SHIFT;
mjr 54:fd77a6b2f76c 123 break;
mjr 54:fd77a6b2f76c 124
mjr 54:fd77a6b2f76c 125 case 16:
mjr 54:fd77a6b2f76c 126 config |= 2 << DMA_DCR_SSIZE_SHIFT;
mjr 54:fd77a6b2f76c 127 break;
mjr 45:c42166b2878c 128 }
mjr 54:fd77a6b2f76c 129
mjr 54:fd77a6b2f76c 130 switch (destination_size)
mjr 54:fd77a6b2f76c 131 {
mjr 54:fd77a6b2f76c 132 case 8:
mjr 54:fd77a6b2f76c 133 config |= 1 << DMA_DCR_DSIZE_SHIFT;
mjr 54:fd77a6b2f76c 134 break;
mjr 54:fd77a6b2f76c 135
mjr 54:fd77a6b2f76c 136 case 16:
mjr 54:fd77a6b2f76c 137 config |= 2 << DMA_DCR_DSIZE_SHIFT;
mjr 54:fd77a6b2f76c 138 break;
mjr 45:c42166b2878c 139 }
mjr 45:c42166b2878c 140
mjr 76:7f5912b6340e 141 dmareg->SAR = _source;
mjr 76:7f5912b6340e 142 dmareg->DAR = _destination;
mjr 76:7f5912b6340e 143 *chcfg = _trigger;
mjr 76:7f5912b6340e 144 dmareg->DCR = config;
mjr 76:7f5912b6340e 145 dmareg->DSR_BCR = length;
mjr 47:df7a88cd249c 146
mjr 100:1ff35c07217c 147 // success - return the channel config register
mjr 100:1ff35c07217c 148 return chcfg;
mjr 45:c42166b2878c 149 }
mjr 45:c42166b2878c 150
mjr 47:df7a88cd249c 151 void SimpleDMA::link(SimpleDMA &dest, bool all)
mjr 47:df7a88cd249c 152 {
mjr 47:df7a88cd249c 153 linkChannel1 = dest._channel;
mjr 47:df7a88cd249c 154 linkChannel2 = 0;
mjr 47:df7a88cd249c 155 linkMode = all ? 3 : 2;
mjr 47:df7a88cd249c 156 }
mjr 47:df7a88cd249c 157
mjr 47:df7a88cd249c 158 void SimpleDMA::link(SimpleDMA &dest1, SimpleDMA &dest2)
mjr 47:df7a88cd249c 159 {
mjr 47:df7a88cd249c 160 linkChannel1 = dest1._channel;
mjr 47:df7a88cd249c 161 linkChannel2 = dest2._channel;
mjr 47:df7a88cd249c 162 linkMode = 1;
mjr 47:df7a88cd249c 163 }
mjr 47:df7a88cd249c 164
mjr 47:df7a88cd249c 165
mjr 47:df7a88cd249c 166 bool SimpleDMA::isBusy( int channel )
mjr 47:df7a88cd249c 167 {
mjr 45:c42166b2878c 168 if (channel == -1)
mjr 45:c42166b2878c 169 channel = _channel;
mjr 54:fd77a6b2f76c 170
mjr 54:fd77a6b2f76c 171 // The busy bit doesn't seem to work as expected. Just check if
mjr 54:fd77a6b2f76c 172 // counter is at zero - if not, treat it as busy.
mjr 54:fd77a6b2f76c 173 //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25);
mjr 45:c42166b2878c 174 return (DMA0->DMA[channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 175 }
mjr 45:c42166b2878c 176
mjr 45:c42166b2878c 177 /*****************************************************************/
mjr 45:c42166b2878c 178 uint32_t SimpleDMA::remaining(int channel)
mjr 45:c42166b2878c 179 {
mjr 45:c42166b2878c 180 // note that the BCR register always reads with binary 1110
mjr 45:c42166b2878c 181 // (if the configuration is correct) or 1111 (if there's an
mjr 45:c42166b2878c 182 // error in the configuration) in bits 23-20, so we need
mjr 45:c42166b2878c 183 // to mask these out - only keep bits 19-0 (low-order 20
mjr 45:c42166b2878c 184 // bits = 0xFFFFF)
mjr 45:c42166b2878c 185 return (DMA0->DMA[channel < 0 ? _channel : channel].DSR_BCR & 0xFFFFF);
mjr 45:c42166b2878c 186 }
mjr 45:c42166b2878c 187
mjr 45:c42166b2878c 188 /*****************************************************************/
mjr 47:df7a88cd249c 189 void SimpleDMA::irq_handler(void)
mjr 47:df7a88cd249c 190 {
mjr 45:c42166b2878c 191 DMAMUX0->CHCFG[_channel] = 0;
mjr 54:fd77a6b2f76c 192 DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK;
mjr 45:c42166b2878c 193 _callback.call();
mjr 45:c42166b2878c 194 }
mjr 45:c42166b2878c 195
mjr 47:df7a88cd249c 196 void SimpleDMA::irq_handler0( void )
mjr 47:df7a88cd249c 197 {
mjr 54:fd77a6b2f76c 198 if (irq_owner[0] != NULL)
mjr 45:c42166b2878c 199 irq_owner[0]->irq_handler();
mjr 45:c42166b2878c 200 }
mjr 45:c42166b2878c 201
mjr 47:df7a88cd249c 202 void SimpleDMA::irq_handler1( void )
mjr 47:df7a88cd249c 203 {
mjr 54:fd77a6b2f76c 204 if (irq_owner[1] != NULL)
mjr 45:c42166b2878c 205 irq_owner[1]->irq_handler();
mjr 45:c42166b2878c 206 }
mjr 45:c42166b2878c 207
mjr 47:df7a88cd249c 208 void SimpleDMA::irq_handler2( void )
mjr 47:df7a88cd249c 209 {
mjr 54:fd77a6b2f76c 210 if (irq_owner[2] != NULL)
mjr 45:c42166b2878c 211 irq_owner[2]->irq_handler();
mjr 45:c42166b2878c 212 }
mjr 45:c42166b2878c 213
mjr 47:df7a88cd249c 214 void SimpleDMA::irq_handler3( void )
mjr 47:df7a88cd249c 215 {
mjr 54:fd77a6b2f76c 216 if (irq_owner[3] != NULL)
mjr 45:c42166b2878c 217 irq_owner[3]->irq_handler();
mjr 45:c42166b2878c 218 }
mjr 54:fd77a6b2f76c 219 #endif