I have a DMA application with a chain of TDs which has to be restarted before finishing the complete chain, for some cases. At present, I just using the API "CyDmaChSetInitialTd(channelHandle, DMA_TD)" to start again from the first TD, i.e. DMA_TD.
The DMA is configured with a hardware request (drq input) for each byte transfer and ensured that there is no more requests or any pending requests. The DMA is never disabled (CY_DMA_INVALID_TD is set as the next TD for the last one), does it require to disable the DMA before setting the initial TD again?
Solved! Go to Solution.
I am not sure whether I understood the exact use case. In the normal scenario does the transfer stop after the chain is complete ?CyDmaChSetInitialTd funciton sets the initial TD to be executed for the channel when the CyDmaChEnable() function is called. With current implementation what issues are you facing? .
The best way will be to disable the and enable it back again. You may release and re-initialize the channel again.
Additionally these documents might be helpful.
I'm assuming that you want to manually restart your DMA chain. If not, you can have the last TD in the chain point to the first TD in the chain.
When you restart the chain, you want to reinitialize it to the parameters originally set. To do this used the preserveTds argment in CyDmaChEnable()
cystatus CyDmaChEnable(uint8 chHandle, uint8 preserveTds)
Enables the DMA channel. A software or hardware request still must happen before the channel is executed.
Note While the channel is enabled and is currently being serviced by the DMA controller, any other configuration information for the channel should NOT be altered to ensure graceful operation.
uint8 chHandle: A handle previously returned by CyDmaChAlloc() or DMA_DmaInitalize().
uint8 preserveTds: Preserves the original TD state when the TD has completed. This parameter applies to all TDs in the channel. Value Action
0 = When a TD is completed, the DMAC leaves the TD configuration values in their current state, and does not restore them to their original state.
1 = When a TD is completed, the DMAC restores the original configuration values of the TD.
When preserveTds is set, the TD slot that equals the channel number becomes RESERVED and that becomes where the working registers exist. So, for example, if you are using CH06 and preserveTds is set, you are not allowed to use TD slot 6. That is reclaimed by the DMA engine for its private use.
Note Do not chain back to a completed TD if the preserveTds for the channel is set to 0. When a TD has completed preserveTds for the channel set to 0, the transfer count will be at 0. If a TD with a transfer count of 0 is started, the TD will transfer an indefinite amount of data.
Take extra precautions when using the hardware request (DRQ) option when the preserveTds is set to 0, as you might be requesting the wrong data.
CYRET_SUCCESS if successful.
CYRET_BAD_PARAM if chHandle is invalid.
For PSoC 3 devices, any pending DMA request prior to enabling the channel will be registered. If this is not desired, call CyDmaClearPendingDrq() just before calling this API to clear the DMA request.
Hi Vasant and LePo,
Yes, I need to manually restart the TD chain from the beginning. I used the preserve TD option, so I didn't reinitialize TD properties and addresses and just calling CyDmaChSetInitialTd to start again from the beginning of the chain.
The current implementation is working so far, but my concern is, does it necessary to disable DMA before calling the function CyDmaChSetInitialTd? The description says "CyDmaChSetInitialTd function sets the initial TD to be executed for the channel when the CyDmaChEnable() function is called", but the DMA is enabled only once in my application as it is never disabled.