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.

Expected DMA behavior after resetting DMA

In my application, I am using DMA to queue CAN messages. If there is an overflow, I want to clear out all the CAN messages and start over with DMA writing to the beginning of the DMA buffer after this. In order to do this, I currently disable the DMA channel using the HWCHENAR register, clear all the DMA buffer memory, store the channel's ISADDR register to itself in order to reset the control packet by writing to it, and enableing the DMA channel by setting the associated HWCHENAS bit. Is there anything wrong with doing it this way?

My concern is with what happens if a frame is being sent when this happens. I know after the control packet is updated, the pending flags are cleared, but does that end the current transmission as well? It is important to me that the end of the frame cannot be finished after I do these steps to reset DMA.

Westin 

  • Westin,

    What you're describing sounds right.

    It's actually going a bit further than this case described in the TRM:

    Changing the contents of a channel control packet will clear the corresponding pending bit
    (Section 16.3.1.2) if the channel has a pending status. If the control packet of an active
    channel (as indicated in Section 16.3.1.3) is changed, then the channel will stop immediately
    at an arbitration boundary. When the same channel is triggered again, it will begin with the
    new control packet information.

    So I think you can be confident that when you re-enable the channel, it'll start with the 'new' instructions from the control packet you updated, rather than continuing on with the control packet in progress before you disabled the channel.
  • I am trying to test this and have found behavior that seems odd to me. If I disable the DMA channel while it is writing, reset the control packet, then enable the DMA channel, it doesn't seem to continue working afterwards.

    dmaREG->HWCHENAR = (uint32)1U << DMA_CH0;
    dmaRAMREG->PCP[DMA_CH0].ISADDR = dmaRAMREG->PCP[DMA_CH0].ISADDR;
    dmaREG->HWCHENAS = (uint32)1U << DMA_CH0;


    I have found that if I wait for the DMA transmit to complete by executing the following line before the first line of the previous block of code, this problem doesn't occur. I have also found if I do not execute the second line of the previous block of code, it continues working, but that doesn't do what I need it to do.

    while(dmaREG->DMASTAT & ((uint32)1U << DMA_CH0));

    Can you tell me why this is happening?

  • Hi Westin,

    The only thing I've found that looks like it may explain what's going on is that there is a FIFO in the DMA port, it's supposed to be 4x64 bits and reads come in one end, writes go out the other.

    While I haven't found anything to contradict the idea that the procedure above is correct - there is mention of the DMA stopping at the 'next aribitration boundary' which seems to relate to emptying the FIFO out. So I could forsee that maybe from the time you disable the channel - there's still additional writes that will occur (emptying the FIFO out) before the DMA actually stops.

    There's someone on our team who knows the innards of the DMA well so I'll check with him - but I'm wondering if this seems about right based on your observations?

    I can see how 4x64-bits might be too much spillage if you're pointing at the DCAN's IF3 register set - since that would pretty much be an entire message, wouldn't it? So we may need to get creative in figuring out how to stop it cold if this is what's happening.

    How complex is your project / would it run pretty standalone on an HDK or other board? I'm thinking that it may even make sense to point the DMA at RAM instead of DCAN as an easy way to confirm just how much data is written after you've asked it to stop.

    Thanks and Best Regards,
    Anthony
  • Anthony,

    I think you are right that the FIFO buffer should be  finishing the write before the DMA channel actually stops, but I'm not sure that it is. My test is to wait until the first byte of the CAN message has been transmitted by DMA, then disable the DMA channel, reset the control packet, and enable the DMA channel. After this, I would check the last byte of the message to see if it was there. The message is 192 bits and I am using 8 byte DMA reads/writes. If I do not wait for the transaction to stop before disabling DMA, I do see that the last byte has not been written yet. Even if that did work as you said, I'm not sure why trying to disable the DMA channel before it was finished would cause any problem.

    I don't understand what you mean by spillage and why it is an issue. The frame size is 3x64 bits.

    I think the project would run just fine on an HDK. I am testing DMA/CAN on a simplified project.

    Thanks,

    Westin

  • Hi Westin, - spillage is a bad choice - I meant that there will be some data that gets transferred even after the channel is disabled.

    I just talked to Charles Tsai about this - he's got previous history w. the DMA module - and we're discussing whether the aribtration boundary is respected if there's only 1 DMA channel in operation and/or if it's fixed priority.

    Do you have other DMA channels in operation / are you using a round-robin priority scheme - or just one.

    We'll do some homework on our end to see if it should be respected for just 1 channel - but would be good to know your use case.
    Also if you send the code we can look at it.

    BTW - which part # is this running on?
  • It seems like the only way to avoid the spillage is to only use one of the words in the FIFO buffer? Is that what you are suggesting? The part is RM48L952PGET. For getting CAN/DMA to work, I am only using one DMA channel, but we don't want to be constrained to just one for the entire project. I will get you some code in a bit.
  • Westin,

    Actually we're thinking that only having 1 channel -> no arbitration -> packet will run to completion instead of stopping.
    This is just a guess at what might be the issue though - need to experiment and also check the design sources.
    A workaround (if this theory is correct) may be to add a 2nd dummy DMA channel that just copies RAM->RAM continually, so
    that arbitrations are created. Again this is just a theory right now that may match your observations - but needs to be confirmed. Could be something completely different.

    There's two table in the TRM that shows the transfer sizes (from a bus transaction standpoint) that the DMA will use given various options.
    This is in 16.2.12 FIFO Buffer. So another idea might be to operate this channel in BYPASS mode and skip the FIFO to break up the transactions more. For CAN's data rate this probably would work fine.
  • I tried enabling another DMA channel and found no difference. BYPASS mode may be acceptable, but I don't know that this will be the only DMA channel used. Anthony, I will send you an example project.