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: SCI DMA Pending Register + Interrupt Delay

Part Number: TMS570LC4357

Hello,

Over the past few months we have begun using DMA on the SCI2 port for transmit operations only. Another coworker has also been using DMA for transmit operations on the SCI1 port in a separate project, and both of these DMA implementations have been seemingly stable. We are now at the stage of combining both implementations in order to use DMA on both SCI1 and SCI2 for transmit operations only. This should be possible according to the technical reference manual, as it indicates that the DMA supports concurrent operations on up to two channels.

After turning on the DMA for both SCI ports I began to notice strange behavior; specifically, the SCI1 DMA seemed to stop working after ~1 minute of operation, and the SCI2 DMA would stop after 5-10 minutes or so. This was empirically observed by monitoring the end devices connected to these ports (a PC-side COM port application for SCI1, and a second MCU on SCI2). In an effort to determine what exactly was causing this behavior, I implemented some basic DMA test functions and am seeing unexpected results. 

One of the most bizarre things that I have been seeing is a delay in the DMA pending register being set. I have code which initiates the DMA transfer by configuring the control packet and writing the appropriate bit of the SCI SETINT register, and following this enters a loop which waits for the DMA PEND register to indicate that the channel has been serviced. This logic follows the following blurb from the TRM:

The DMA controller cannot recognize two software requests on the same channel if the first
software request is still pending. If such a request occurs, the DMA will discard it. Therefore,
the user software should check the pending register before issuing a new software request.

Strangely, the loop seems to exit after only a single register check. There is no implemented delay or sleep function within the loop, which indicates that the pending register is cleared nearly immediately after starting the transfer (within microseconds). The buffer size + baud rate are configured to take roughly ~350 microseconds to transfer, so this indicates that the pending register is not being properly set. I have the BTC interrupt set a flag (declared globally and volatile) as well upon transfer completion, and this flag is also not set after the pending loop is skipped. What is perhaps most strange is that the transfer actually completes! I can observe that the bytes are sent using my PC COM reader. Using the JTAG debugger on the Launchpad, I have consistently observed the following sequence of events:

  1. DMA transfer function is called, which configures the control packet and calls dmaSetCtrlPacket() and dmaSetChEnable() HAL functions. dmaSetChEnable() is called to trigger on a HW request
  2. A SW breakpoint is triggered on the line of code where the SCI SETINT register bit 16 is set, which allows the SCI transfer to occur. At this point the COM reader does not show any data
  3. I allow the code to continue running and a SW breakpoint triggers on the line of code following the PEND register check loop. The loop counter has a value of '1' which indicates that the loop has exited nearly immediately. The BTC interrupt completion flag has not been set, indicating that the interrupt has not executed. However, I see data transferred using the COM reader at this point, indicating that the transfer has concluded
  4. At a seemingly arbitrary point in code execution, a breakpoint in the BTC interrupt function occurs and the flag is now set
  5. While stepping through the code, an additional check of the PEND register now shows that the transfer is pending. This happens after the BTC interrupt occurs, which should be the end of the transfer

A watered-down version of the code is presented below:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void unit_test(void)
{
//Initialize test variables, other function calls
//...
/*
* Start a transfer on UART0. Loop until the DMA is no longer
* pending and verify that the callback flag is incremented.
*/
dma_ut_uart0_complete = 0U;
dma_tf_rtn = DMA_start_transfer(DMA_UT_CH_UART0,
DMA_UT_DATA_UART0,
DMA_UT_DATA_UART0_LEN,
DMA_UT_DATA_UART0_ADDR);
if(dma_tf_rtn != DMA_STARTED)
{
dma_unit_rtn = FAILURE;
}
else
{
/* Enable interrupt to kick-off transfer */
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

I understand that there is likely some delay within the VIM in generating the interrupt, so I can understand that this fires later than expected. What concerns me though is that the PEND register does not indicate that the channel is pending service after initiating the transfer, and only seems to indicate that it is pending after some sort of delay. To summarize, my questions are essentially:

  1. Why am I observing a delay in the DMA PEND register being set for the channel?
  2. Is the use of the DMA PEND register to check for the channel being unavailable a reliable method?
  3. Why does the DMA PEND register continue to indicate that the channel is pending after the BTC interrupt occurs?
  4. Does the use of JTAG interfere with this testing in any way? E.g. staving off interrupts and/or messing with timing

Any advice or wisdom is much appreciated. If I have misunderstood the operation of the DMA or use of the PEND register, please correct my understanding as well.

Best,

James

  • Hi James,

    The DMA controller cannot recognize two software requests on the same channel if the first
    software request is still pending.

    This condition is when we used single channel for both the SCI instances, In our case i wish we are using two different channels for both the instances and two different requests for both the instances.

    --

    Thanks & Regards,
    Jagadish.

  • Hello Jagadish,

    Thank you for the reply. In our code, we have mapped the channels and requests as follows:

    • UART 0 TX -- Channel 0 -- Request 29
    • UART 1 TX -- Channel 1 -- Request 41

    According to the TRM, these are the highest priority channels (with Channel 0 taking priority in the event of required arbitration) and these are the only two enabled DMA channels in our system, so I assume that there is no issue with contention. I have confirmed that these requests are correct, both by observing the data output and by referencing the TRM.

    My confusion lies with what seems to me is a delay between beginning the transfer and the DMA PEND register being set for the channel. The seeming delay between observing data on the COM port and BTC callback within the code is confusing to me as well. There is likely something that I'm not understanding about the internal DMA mechanisms or about how JTAG debugging may be impacting the behavior (which is what I have been using to try and step through my test code).

    Any information about this topic of confusion would be greatly appreciated.

    Best,

    James

  • Hi James,

    One thing i am suspecting is that cache.

    Can you please check whether cache is enabled or not?

    If it is enabled, can you please try by disabling it?

    --

    Thanks & Regards,
    Jagadish. 

  • Hello Jagadish,

    The cache was indeed enabled in my build. However, disabling the cache did not have any impact on what I have been seeing.

    I actually was able to resolve all of my issues by setting and clearing flags in software to indicate that the DMA is busy, rather than using the PEND register. This very strongly indicates to me that there is some mechanism or interaction that I do not understand about the DMA, or possibly that the TRM is unclear in its explanation of how the system works. 

    We will move forward with this software solution for now, but if there is any insight you can share on the behavior of this PEND register please let me know. Going forward we would prefer to receive these indications from the hardware if possible. Perhaps there is a better register to poll for status rather than PEND?

    Best regards,

    James

  • Hi James,

    DMA pending register is used to track status of Direct Memory Access (DMA) transactions. It is a hardware register that stores the status of ongoing DMA transfers, allowing the system to monitor and manage the flow of data. The bits in the DMA pending register represent the channels in the system that have pending DMA requests. By reading the contents of this register, the system can determine which channels have requested access to the system's memory and prioritize them accordingly.

    It is simple whenever a trigger comes the corresponding channel pending bit will get set and it is cleared only after end of frame or block transfer depending upon the how channel is configured.

    For example:

    If you see below fixed priority scheme

    --

    Thanks & Regards,
    Jagadish.

  • Hello Jagadish,

    Thank you for the response. This is how I understood the use of this register as well after reading the technical reference manual. The behavior that I had observed in software did not seem to align to this description, unfortunately, which led me to believe that I may have somehow misconfigured my project. 

    The software solution that I had described above is sufficient for our project, and we will move forward with that. Perhaps in the future we will revisit this issue, but I am good to close this topic for now.

    Thanks,

    James