Mirror with some correction
Dependencies: mbed FastIO FastPWM USBDevice
Diff: SimpleDMA/SimpleDMA_KL25_46.cpp
- Revision:
- 54:fd77a6b2f76c
- Parent:
- 48:058ace2aed1d
- Child:
- 76:7f5912b6340e
--- a/SimpleDMA/SimpleDMA_KL25_46.cpp Fri Apr 22 17:58:35 2016 +0000 +++ b/SimpleDMA/SimpleDMA_KL25_46.cpp Sat Apr 30 17:43:38 2016 +0000 @@ -25,13 +25,15 @@ SimpleDMA::SimpleDMA(int channel) { class_init(); - + + // remember the channel (-1 means we automatically select on start()) this->channel(channel); - //Enable DMA - SIM->SCGC6 |= 1<<1; //Enable clock to DMA mux - SIM->SCGC7 |= 1<<8; //Enable clock to DMA + // Enable DMA + SIM->SCGC6 |= 1<<1; // Enable clock to DMA mux + SIM->SCGC7 |= 1<<8; // Enable clock to DMA + // use the "always" software trigger by default trigger(Trigger_ALWAYS); // presume no link channels @@ -40,12 +42,15 @@ linkChannel2 = 0; } -int SimpleDMA::start(uint32_t length) +int SimpleDMA::start(uint32_t length, bool wait) { if (auto_channel) _channel = getFreeChannel(); - else - while(isBusy()); + else if (!wait && isBusy()) + return -1; + else { + while (isBusy()); + } if (length > DMA_DSR_BCR_BCR_MASK) return -1; @@ -54,47 +59,51 @@ // disable the channel while we're setting it up DMAMUX0->CHCFG[_channel] = 0; + + // set the DONE flag on the channel + DMA0->DMA[_channel].DSR_BCR = DMA_DSR_BCR_DONE_MASK; uint32_t config = DMA_DCR_EINT_MASK | DMA_DCR_ERQ_MASK | DMA_DCR_CS_MASK - | (source_inc << DMA_DCR_SINC_SHIFT) - | (destination_inc << DMA_DCR_DINC_SHIFT) - | ((linkChannel1 & 3) << DMA_DCR_LCH1_SHIFT) - | ((linkChannel2 & 3) << DMA_DCR_LCH2_SHIFT) - | ((linkMode & 3) << DMA_DCR_LINKCC_SHIFT); + | ((source_inc & 0x01) << DMA_DCR_SINC_SHIFT) + | ((destination_inc & 0x01) << DMA_DCR_DINC_SHIFT) + | ((linkChannel1 & 0x03) << DMA_DCR_LCH1_SHIFT) + | ((linkChannel2 & 0x03) << DMA_DCR_LCH2_SHIFT) + | ((linkMode & 0x03) << DMA_DCR_LINKCC_SHIFT); - switch (source_size) { - case 8: - config |= 1 << DMA_DCR_SSIZE_SHIFT; - break; - case 16: - config |= 2 << DMA_DCR_SSIZE_SHIFT; - break; + switch (source_size) + { + case 8: + config |= 1 << DMA_DCR_SSIZE_SHIFT; + break; + + case 16: + config |= 2 << DMA_DCR_SSIZE_SHIFT; + break; } - switch (destination_size) { - case 8: - config |= 1 << DMA_DCR_DSIZE_SHIFT; - break; - case 16: - config |= 2 << DMA_DCR_DSIZE_SHIFT; - break; + + switch (destination_size) + { + case 8: + config |= 1 << DMA_DCR_DSIZE_SHIFT; + break; + + case 16: + config |= 2 << DMA_DCR_DSIZE_SHIFT; + break; } - DMA0->DMA[_channel].DCR = config; DMA0->DMA[_channel].SAR = _source; DMA0->DMA[_channel].DAR = _destination; DMAMUX0->CHCFG[_channel] = _trigger; + DMA0->DMA[_channel].DCR = config; DMA0->DMA[_channel].DSR_BCR = length; - //$$$ - // static int iii; if (_channel != 0 && iii++ < 3) - // printf("DMA channel %d: mode %04x, source %08lx, dest %08lx, trigger %d, len %d\r\n", _channel, config, _source, _destination, _trigger, length); - - //Start - set ENBL bit in the DMAMUX channel config register - DMAMUX0->CHCFG[_channel] |= 1<<7; - + // Start - set the ENBL bit in the DMAMUX channel config register + DMAMUX0->CHCFG[_channel] |= DMAMUX_CHCFG_ENBL_MASK; + return 0; } @@ -113,22 +122,14 @@ } -int SimpleDMA::restart(uint32_t length) -{ - DMA0->DMA[_channel].SAR = _source; - DMA0->DMA[_channel].DAR = _destination; - DMA0->DMA[_channel].DSR_BCR = length; - DMAMUX0->CHCFG[_channel] |= 1<<7; - return 0; -} - bool SimpleDMA::isBusy( int channel ) { - //Busy bit doesn't work as I expect it to do, so just check if counter is at zero - //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25); if (channel == -1) channel = _channel; - + + // The busy bit doesn't seem to work as expected. Just check if + // counter is at zero - if not, treat it as busy. + //return (DMA0->DMA[_channel].DSR_BCR & (1<<25) == 1<<25); return (DMA0->DMA[channel].DSR_BCR & 0xFFFFF); } @@ -147,31 +148,31 @@ void SimpleDMA::irq_handler(void) { DMAMUX0->CHCFG[_channel] = 0; - DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK ; + DMA0->DMA[_channel].DSR_BCR |= DMA_DSR_BCR_DONE_MASK; _callback.call(); } void SimpleDMA::irq_handler0( void ) { - if (irq_owner[0]!=NULL) + if (irq_owner[0] != NULL) irq_owner[0]->irq_handler(); } void SimpleDMA::irq_handler1( void ) { - if (irq_owner[1]!=NULL) + if (irq_owner[1] != NULL) irq_owner[1]->irq_handler(); } void SimpleDMA::irq_handler2( void ) { - if (irq_owner[2]!=NULL) + if (irq_owner[2] != NULL) irq_owner[2]->irq_handler(); } void SimpleDMA::irq_handler3( void ) { - if (irq_owner[3]!=NULL) + if (irq_owner[3] != NULL) irq_owner[3]->irq_handler(); } -#endif \ No newline at end of file +#endif