I'll be honest in that this has me pretty stumped.
So with my application, I am capturing edges via the FTM. Every edge generates a DMA request to save the counter into a circular buffer.
I currently have the DMA configured to act as a circular buffer in case I don't get to the edges in time if they come in too fast. However, every time I check the edges, I want to reset the DMA pointer, and I do this by writing to CITER.
For instance, my circular buffer has 128 elements. When I check my buffer, I execute the following line of code:
DMA0->TCD[0].CITER_ELINKNO = 128;
This works for a little while, but I noticed after my program has been running for a bit, all of a sudden all of my variable blow up to crazy values, and it seems like there was an illegal jump or something. I'm not able to really figure it out because when I single step through my code, the corruption never happens.
Is what I'm doing fine? Is there an application note somewhere that tells me I shouldn't do this?
Thanks.
Edit: I forgot to mention, I also tried disabling the DMA channel before and after modifying the CITER register, but this does not seem to help either.
DMAMUX0->CHCFG[0] ^= ~(DMAMUX_CHCFG_ENBL_MASK);
Also, I'm using the TWR-K60F120M.
解決済! 解決策の投稿を見る。
I think I might have this figured out now.
The key thing I wasn't doing was I wasn't updating DADDR as well as updating CITER. I didn't realize the actual pointer didn't get reset. Now, with having to update 2 different registers, this introduces issues of atomicity. Because I can't guarantee a DMA request won't come in between the time of me updating these 2 registers, I decided to err on the safe side by disabling the DMA channel beforehand, and re-enabling it afterward, and this seems to be working just fine.
DMAMUX0->CHCFG[0] &= ~(DMAMUX_CHCFG_ENBL_MASK);
DMA0->TCD[0].CITER_ELINKNO = 128;
DMA0->TCD[0].DADDR = (uint32_t)freq_dma_arr[0];
DMAMUX0->CHCFG[0] |= DMAMUX_CHCFG_ENBL_MASK;
I think I might have this figured out now.
The key thing I wasn't doing was I wasn't updating DADDR as well as updating CITER. I didn't realize the actual pointer didn't get reset. Now, with having to update 2 different registers, this introduces issues of atomicity. Because I can't guarantee a DMA request won't come in between the time of me updating these 2 registers, I decided to err on the safe side by disabling the DMA channel beforehand, and re-enabling it afterward, and this seems to be working just fine.
DMAMUX0->CHCFG[0] &= ~(DMAMUX_CHCFG_ENBL_MASK);
DMA0->TCD[0].CITER_ELINKNO = 128;
DMA0->TCD[0].DADDR = (uint32_t)freq_dma_arr[0];
DMAMUX0->CHCFG[0] |= DMAMUX_CHCFG_ENBL_MASK;