Help with K22F eDMA

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Help with K22F eDMA

Jump to solution
1,204 Views
robotjosh
Contributor IV

I am able to use the DMA in the KL26 to output to DMA using this tutorial Tutorial: PWM with DMA on ARM/Kinetis | MCU on Eclipse

But now I am using the K22F freedom board and have some problems.  I have tried using the dma channel bean and observed the code output but have not been able to see it work.  I have reduced the problem down to the following code- maybe a bit somewhere is being set incorrectly.  I have flextimer 0 channel 0 setup as a pwm and can see it output correctly if I change the value of FTM0_C0V in the debugger.  What I attempt to do is output a series of 5 pulses and then a 6th pulse set to 0 to turn off the pwm.  The following code is the dma bean output boiled down into readable code.  When this code runs, the FTM0_C0V remains zero and the dma never activates.

//setup clock gates for pwm and dma
SIM_SCGC6 |= SIM_SCGC6_FTM0_MASK|SIM_SCGC6_DMAMUX_MASK;
SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;

//setup pwm module
FTM0_MOD = 74; //set timer period (75 ticks * 60MHz = 1.25us)
FTM0_C0SC = FTM_CnSC_ELSB_MASK|FTM_CnSC_MSB_MASK|FTM_CnSC_DMA_MASK; //edge-aligned pwm, enable dma request
PORTC_PCR1 |= PORT_PCR_MUX(4); //select alt4 for tmr0ch0 control see chapter 10 Signal Multiplexing and Signal Descriptions
FTM0_C0V = 0;
FTM0_SC = FTM_SC_CLKS(1); //enable FTM clock source

//configure channel 0 to send frame
DMAMUX_CHCFG0 = DMAMUX_CHCFG_ENBL_MASK|20; //see RM "DMA request sources"
DMA_ERQ &= ~(1<<0); //disable dma channel 0
DMA_TCD0_CSR = 0; //clears done flag and dreq bit
DMA_TCD0_NBYTES_MLNO = 2*6; //number of transfers
DMA_TCD0_ATTR = DMA_ATTR_SSIZE(1)|DMA_ATTR_DSIZE(1); //set source size, destination size to 16bits, no modulo
DMA_TCD0_SOFF = 2; //increment source by 2 bytes for 16bit transfers
DMA_TCD0_SADDR = (uint32_t)&dmabuf[0]; //dmabuf is uint16_t array containing {7, 14, 21, 28, 35, 0}
DMA_TCD0_DOFF = 0; //destination address doesnt increment
DMA_TCD0_DADDR = (uint32_t)&FTM0_C0V; //destination address
DMA_TCD0_CITER_ELINKNO = 1; //current major loop iteration for 1 transfer
DMA_TCD0_BITER_ELINKNO = 1; //beginning major loop iterations, 1 transfer only

DMA_TCD0_DLASTSGA = 0; //just to make sure

//reset timer count and channel flags
FTM0_CNT = 0; //make sure flag is clear when dma requests are enabled
FTM0_C0SC &= ~FTM_CnSC_CHF_MASK; //channel flag must be read and then written 0 to clear
//enable peripheral dma requests
DMA_ERQ |= (1<<0);
0 Kudos
Reply
1 Solution
736 Views
robotjosh
Contributor IV

I had at least 2 misconceptions that stopped memory to pwm edma from working.  First, channel interrupts must be enabled along with the dma bit in FTMx_CxSC, says right on page 995 (in table format) that both have to be enabled to generate the dma request.  On chips with non-flex timers and regular dma, only the dma bit has to be set to generate a dma request.  Second, the channel event flag will never be set if the compare value is zero.  To begin a memory to pwm transfer you have to transfer the first byte manually if the CxV value is initially zero.  On chips with non-flex timers, channel flag is set when compare value is zero and timer value is zero but on flex timers, channel flag never gets set if the compare value is zero no matter what value the counter reaches. This means that a dma transfer to pwm is stopped if any data is zero.  I'm not 100% happy with this solution but I think I can make it work for my application.

View solution in original post

0 Kudos
Reply
3 Replies
737 Views
robotjosh
Contributor IV

I had at least 2 misconceptions that stopped memory to pwm edma from working.  First, channel interrupts must be enabled along with the dma bit in FTMx_CxSC, says right on page 995 (in table format) that both have to be enabled to generate the dma request.  On chips with non-flex timers and regular dma, only the dma bit has to be set to generate a dma request.  Second, the channel event flag will never be set if the compare value is zero.  To begin a memory to pwm transfer you have to transfer the first byte manually if the CxV value is initially zero.  On chips with non-flex timers, channel flag is set when compare value is zero and timer value is zero but on flex timers, channel flag never gets set if the compare value is zero no matter what value the counter reaches. This means that a dma transfer to pwm is stopped if any data is zero.  I'm not 100% happy with this solution but I think I can make it work for my application.

0 Kudos
Reply
736 Views
robotjosh
Contributor IV

No bits ever get set in DMA_HRS in this configuration.  It looks like the dma might be setup right but the dma bit in FTM0_C0SC is not causing a signal to reach the dma module.

0 Kudos
Reply
736 Views
robotjosh
Contributor IV

I see equivalents for everything in the K22 edma as in the KL26 dma except for one thing- the cycle steal bit.  On the kl26, this bit enables peripheral requests to trigger 1 dma transfer at a time such as for the pwm module to update its CxV register after each period.  I do not see an equivalent bit in the K22 edma.  I am wondering if this type of transfer is possible on the k22.

0 Kudos
Reply