DMA circular buffer: multiple moves per transaction

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Level 3
Level 3
First solution authored 10 replies posted 5 replies posted
I've recently started using the DMA more, and I seem to have trouble with setting up multiple moves with automatic source/destination address increase. I've managed to sort out Linked Lists, interrupts from multiple sources, daisy chaining channels.

The issue is that I have setup multiple channels to do two moves: read from a local array and write the value directly to the GTM SR0/SR1 of a TOM channel.

I can get the first move to work, but for some reason, the second move doesn't do anything. I'm not sure what's wrong in my configuration.

Here's my code example:
I'm moving 16bits. The source data is in an array of uint16, so I increment the source address by 1 width. The destination addresses are 0x-------4 and 0x-------8, so I increment by 2 widths. The thing I'm not sure is the circular buffer size, but I've tried multiple configurations and none of them work with the second transfer.

cfg.operationMode = IfxDma_ChannelOperationMode_single;
cfg.channelId = IfxDma_ChannelId_127-LegNumber; /* Init channel from highest priority */
cfg.transferCount = NUM_TRANSFERED_WORDS; /* Moving one 16bits register */
cfg.blockMode = IfxDma_ChannelMove_2; /* Two moves SR0 and SR1 */
cfg.requestMode = IfxDma_ChannelRequestMode_completeTransactionPerRequest;
cfg.moveSize = IfxDma_ChannelMoveSize_16bit;
cfg.shadowControl = IfxDma_ChannelShadow_none;
/* Source and destination addresses */
cfg.sourceCircularBufferEnabled = TRUE;
cfg.sourceAddressIncrementStep = IfxDma_ChannelIncrementStep_1; //1 width
cfg.sourceAddressCircularRange = IfxDma_ChannelIncrementCircular_2; //2bytes buff
cfg.destinationCircularBufferEnabled = TRUE;
cfg.destinationAddressIncrementStep = IfxDma_ChannelIncrementStep_2; //2 widths
cfg.destinationAddressCircularRange = IfxDma_ChannelIncrementCircular_4; //4 bytes buffer

cfg.sourceAddress = ... (pointer to my local array)
cfg.destinationAddress = ... (pointer to GTM SR registers)

Can you see anything wrong? I suppose its the circular buffer size but I don't think I understand how it works.
For example on the source address, with IfxDma_ChannelIncrementCircular_2, it should be a buffer of 2 bytes. First move will read from (for example) 0x60000000, second move from 0x60000002, then next transfer, it'll select 0x60000000 again due to the circular buffer size.
Same for the destination address, IfxDma_ChannelIncrementCircular_4 is a 4 bytes buffer, so first write to 0xF0000000 and second write to 0xF0000004 then back to 0xF0000000 on the next transfer, right?

Apparently not...
1 Reply
Level 3
Level 3
First solution authored 10 replies posted 5 replies posted
Any thoughts on this? Can't seem to get multiple moves per transaction work.