Memory Corruption when Writing to DMA CITER

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Memory Corruption when Writing to DMA CITER

ソリューションへジャンプ
734件の閲覧回数
benjaminschroed
Contributor III

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.

ラベル(1)
タグ(1)
0 件の賞賛
返信
1 解決策
555件の閲覧回数
benjaminschroed
Contributor III

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;

元の投稿で解決策を見る

0 件の賞賛
返信
1 返信
556件の閲覧回数
benjaminschroed
Contributor III

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;

0 件の賞賛
返信