This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LC4357: Issue resetting DMA destination address

Part Number: TMS570LC4357
Other Parts Discussed in Thread: HALCOGEN

Hello,

I am using DMA to read/write data over SCI on a TMS570LC4357. I am working with fixed-length messages, so I would like to line up the messages with the start of the DMA receive block to make it easier to copy data out of the buffer. When messages get out of sync with the receive block, I attempt to reset the DMA control packet to get things back in sync. This works most of the time, but sometimes my reset function does not work.

Per the note in section 20.2.4 in the TRM, I should be able to reset the control packet by writing to one of the values. As I understand, this should reset the destination address to the value in IDADDR, which would accomplish what I'm trying to do. However, sometimes DMA gets into a state where writing to the control packet does nothing to reset the destination address and it remains out of sync. It'll remain in this state anywhere from a few seconds to a few minutes, but eventually it will reset properly and resynchronize.

I have tried:
1. Simply overwriting the IDADDR value in the control packet.
2. Disabling the DMA channel, writing IDADDR to a different value, restoring the correct IDADDR value, then enabling the DMA channel.
3. Disabling the DMA channel, rewriting all DMA control packet values, then enabling the DMA channel.
4. Polling DMASTAT before running #2.
5. Putting DMA FIFOs in bypass mode.
6. Both running this as the sole DMA channel in operation and running multiple DMA channels.

I found these similar threads, but these suggestions did not work:
e2e.ti.com/.../resetting-of-dma
e2e.ti.com/.../expected-dma-behavior-after-resetting-dma
e2e.ti.com/.../tms570-reset-dma-with-dma-btc-interrupt

Everything I have tried shows the behavior described above. If I comment out the write to IDADDR and get it out of sync, then the receive never resynchronizes. That leads me to think resync is working most of the time, and something else is preventing the control packet from resetting.

Thanks,

David

  • Hi David,

    We started working on your issue and will provide you an update ASAP.

    --
    Thanks & regards,
    Jagadish.

  • Hi David,

    Can you please provide a simplest project with the out of synchronization issue you are mentioning? And also please provide details on how to trigger the issue?

    If you help me on this then i will debug your issue at my end and i can provide you my suggestions to resync.

    --
    Thanks & regards,
    Jagadish.

  • Hi Jagadish,

    Unfortunately I'm working under export restrictions so I'd have to reproduce this in a HALCoGen project before I can share anything. It would probably take me less time to work around this issue by rewritting the receive function to treat the DMA receive block as an asynchronous circular buffer.

    I have one TMS570 streaming data to another TMS570 and I can cause the issue by power cycling the receiver TMS570 or by pausing and continuing a debug session on the receiver. If the receiver starts up in the middle of an incoming message, then there is maybe a 1 in 10 chance of the DMA control packet failing to reset when I write to one of the registers.

    Is there any condition that could prevent a DMA control packet from resetting, or is there any other way to modify the current destination address of a DMA channel?

    Thanks,

    David

  • Hi David,

    Apologies for the delay in my response.

    Is there any condition that could prevent a DMA control packet from resetting, or is there any other way to modify the current destination address of a DMA channel?

    I don't think there would be any better way to reset the packet other than changing the control packet content in DMA. This should only be the better way.

    --
    Thanks & regards,
    Jagadish.

  • Updating the post for anyone else who runs into this issue. I was not able to resolve the DMA destination address reset issue. Instead, I redesigned the receiver to treat the DMA receive block as a circular buffer and I used the FAACDADDR, FBACDADDR, and CDADDR registers to determine the number of bytes received.

    The basic process is:

    1. Check whether FAACDADDR is within the receive buffer. If it is, then FAACDADDR has the latest destination address.

    2. If FAACDADDR is not within the buffer, check whether FBACDADDR is within the receive buffer. If it is, then FBACDADDR has the latest destination address.

    3. If neither FAACDADDR nor FBACDADDR are within the receive buffer, then get the destination address from CDADDR.

    Here are some tricks I used to make this work:

    1. Perform a single read of these registers by storing the value in a volatile variable before checking whether the address is within the buffer. You don't want to read FAACDADDR twice and risk DMA arbitration between the reads.

    2. If the SCI port hasn't received any data since power up, then none of FAACDADDR, FBACDADDR, and CDADDR will be within the receive buffer. In this case, treat the destination address as the head of the buffer (0 bytes received).

    3. FAACDADDR and FBACDADDR wrap around strangely. They seem to increment one address beyond the buffer before wrapping to index 0, so sometimes your read will point one beyond the buffer. Not sure whether CDADDR does this as well, but I haven't seen it happen. This is fairly rare and I only observed it when streaming data from one TMS570 to another, so I think it's a timing edge case.

      1. The check for whether a destination address is within a buffer needs to allow one address beyond the buffer.

      2. Arrange receive buffers so that they are not adjacent in memory. You could add a pad byte between receive buffers to ensure there isn't any overlap in destination address registers.

      3. When I encounter an address one outside the buffer I decrement the address to the last position within the buffer. I felt this was safer than wrapping it around to the head of the buffer. Maybe this wasn't important though.

    This seems to be working reliably at this point, but if anyone has other suggestions I'd love to hear them.