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.

RTOS/AM5728: Operate two UART instances with DMA

Part Number: AM5728

Tool/software: TI-RTOS

Hello,

We need to operate two UART instances (instance number 4 & 5) on an AM572x processor in DMA mode in order to achieve transmitting 180 contiguous bytes without any time gaps. Therefore we copied source-code from the TI example project 'UART_BasicExample_idkAM572x_DMA_armTestproject' into our project. The example test case is called 'UART_TEST_ID_DMA_CB'.

Inside our *.cfg file we only did the following (like inside the example project):

/* Load the uart package */
var Uart = xdc.loadPackage('ti.drv.uart');

But we can see that the transmission is not contiguous, which is an indication that we do not send the data via DMA to the Tx FIFO, see below the time gap in a logic analyzer measurement inside the red circle:

We figured out via the map file that the UART example project links a different library to the project:

The example project uses:

.text.UART_open_v1
0x8002fef0 0x278 C:\ti\pdk_am57xx_1_0_10\packages\ti\drv\uart\lib\a15\release\ti.drv.uart.profiling.aa15fg(UART_v1.oa15fg)

Our project uses:

0x8814fa0c 0x98 C:\ti\pdk_am57xx_1_0_10\packages\ti\drv\uart\lib\a15\release\ti.drv.uart.aa15fg(UART_v1.oa15fg)
.text.UART_open_v1

So I have basically the following questions:

1) Why doesn't the function 'UART_open()' return a NULL pointer although obviously no DMA transfer is being used for sending data to the Tx FIFO?
2) Why does the example project link a different library to the project?
3) What do we have to do in order to get those two UART instances working in DMA mode inside our own project?

Regards,

Andreas

  • Hi,

    Quick answer to Q2:
    /* Load the uart package */
    var Uart = xdc.loadPackage('ti.drv.uart');
    Uart.Settings.enableProfiling = true;

    Regards, Eric
  • Hi,

    For Q1, I stepped through the TI test example 'UART_BasicExample_idkAM572x_DMA_armTestproject'. The UART_SOC.c, the hardware attribute uses the EDMA enable and sets the Tx FIFO with 56 spaces for reload. The test project uses -DUART_DMA_ENABLE for compilation and the test case also the DMA enables: {UART_test_callback, true, UART_TEST_ID_DMA_CB, "\r\n UART DMA read write test in callback mode"},

    However, I found that UART_configDMA() and EDMA3_DRV_requestChannel() are not called inside UART_open_v1 function. It determined the library linked was wrong.

    Please use:
    /* Load the uart package */
    var Uart = xdc.loadPackage('ti.drv.uart');
    Uart.Settings.enableProfiling = true;
    Uart.Settings.socType = socType;
    Uart.Settings.useDma = "true";

    This loads the library ti.drv.uart:./lib/am572x/a15/release/ti.drv.uart.profiling.dma.aa15fg, and should work for DMA mode. Let me know if you can see that UART TX is contiguous.

    Also, please ignore my answer to Q2, this test example linked to a wrong library and DMA was actually not tested.

    Regards, Eric
  • Hi Eric,

    After applying your suggestions above I can confirm that the expected library is being linked:

    .text.UART_open
    0x8815661c 0x6c C:\ti\pdk_am57xx_1_0_10\packages\ti\drv\uart\lib\am572x\a15\release\ti.drv.uart.profiling.dma.aa15fg(UART_drv.oa15fg)
    0x8815661c UART_open

    The problem is now, that I do not see any Rx data anymore although I see via the logic analyzer, that data is being on the Rx line. That means I always run into an Rx timeout (I selected 100[ms] as a timeout).

    My colleague found the following post, which states that in the past it wasn't possible to run 2 UART instances via DMA simultaneously.

    https://e2e.ti.com/support/processors/f/791/t/719947?RTOS-AM5728-UART-DMA-issues

    We are using PDK version "pdk_am57xx_1_0_10". I need to do more testing and maybe remove one UART instance in order to see that this might be the problem, but the following if-condition is true after using the other library:

      if (UART_osalPendLock(acyclicCallbackSem, callbackTransaction.timeout) != SemaphoreP_OK)

    So something in Rx direction is not working.

    Additional update

    I removed temporarily the usage of the second UART instance 5 and the behavior changed as follows:

    a) I do not receive a timeout anymore for UART instance 4, so it seems that the UART driver detected the expected number of bytes and called afterwards the read-callback function.
    b) The data that we receive is all zeros although I know that we receive different data. So the data inside my receive buffer is wrong.

    Summary

    a) The correct library is linked to the project after adding the proposed instructions to the *.cfg-file (ti.drv.uart.profiling.dma.aa15fg)
    b) When setting up 2 UART instances via the UART driver in DMA mode, then the Rx does not recognize the incoming bytes and I get a timeout. Maybe it is possible that the UART instance 5 (this one expects to receive 180[bytes]) overwrites the setting of instance 4 (instance 4 expects to receive 60[bytes]), but this is just a guess.
    c) When using only UART instance 4, then I don't get a timeout anymore but all received data is zero, which is not the data that I see in a logic analyzer capture on the Rx lines.

    Please note that I did not change any source code, I simply added your proposed instructions inside the *.cfg file. The two UART instances worked simultaneously before adding the additional settings to the cfg file, just not in DMA mode (since there were time gaps in the Tx telegram).

  • Hi,

    Thanks for the summary. Are you able to use TI AM572x IDK EVM to test the UART_BasicExample_idkAM572x_DMA_armTestproject with the ti.drv.uart.profiling.dma.aa15fg linked? For now, I assume the Tx is OK, you didn't see the gaps.

    For the UART, the EVM uses the UART3 (1-based) I tested it and I saw it passed the read and write test. E.g, it takes what I typed into UART console and print it out to console.

    In the CCS memory browser, I can look at the offset 0x0 which is RHR register to see what the UART received in FIFO. For example when using a fixed input pattern "555555555555..." I saw RHR with "35" this is ASCII "5".

    If you can verify the EVM worked, then in your own board with only one UART 4, are you able to see the pattern in RHR, or, they are zero?

    Regards, Eric

  • Hello Eric,

    First of all we use UART DMA in callback mode and not blocking mode, but that is just a minor difference. The problem with the UART basic example was in the past, that this example just opens one single RTOS task and therefore no IRQs (beside the RTOS scheduler) are active. In our project we have multiple IRQs that can occur, which basically means that the system is more loaded and the probability that an IRQ interrupts an ongoing data transfer between a buffer and the Tx FIFO is much higher in our system. That was most likely the reason why we identified no time gaps in the UART basic example project.

    Now we linked successfully the intended library to our own project and I see data being transmitted on our UART instance. I guess that the Tx is now working since I did not yet see any time gaps although I need to do some more testing. But so far the situation in Tx direction looks OK.

    The thing is that we need to get the UART DMA working on our own system with a changed board library (which reflects our hardware situation) and we also added changes and bug-fixes to the UART driver (e.g. we changed the oversampling rate in order to achieve  the correct baud-rate). That means that currently the UART example project does not help anymore, we need to get the code running on our own platform.

    What I can say is, that we can send and receive data (obviously not in DMA mode) when the cfg file looks like this:

    /* Load the uart package */
    var Uart = xdc.loadPackage('ti.drv.uart');
    /*
    Uart.Settings.enableProfiling = true;
    Uart.Settings.socType = socType;
    Uart.Settings.useDma = "true";
    */

    Receiving data does not work anymore is the cfg file is as follows:

    /* Load the uart package */
    var Uart = xdc.loadPackage('ti.drv.uart');
    Uart.Settings.enableProfiling = true;
    Uart.Settings.socType = socType;
    Uart.Settings.useDma = "true";

    The question is now how we can proceed. I will discuss our next steps with Carlo Colombo.

    Regards, Andreas

  • Andreas,

    Progress here is that one UART port RX DMA worked now. TI is trying to duplicate and debug the two UART ports case with DMA.

    Regards, Eric
  • The issue for 2 UART channels + DMA was reproduced. I am debugging it.

    Regards, Eric

  • Hi,

    I recalled you used the pdk_am57xx_1_0_10. Attached is the fix, we added a field called rxTcc in the header file, then use this to record the rxTcc number in UART_configDMA(UART_Handle handle ) function, and programmed into  UART_v1_receiveDMA(UART_Handle handle, const void *buffer, size_t size ). UART_v1.h

    UART_v1.c

    Let us know if worked for you.

    Regards, Eric

  • Posting the feedback from customer:

    We found the following issues:

    Issue 1
    A wrong library was linked to the project due to missing settings inside the application configuration file. The following entries needs to be added to the cfg file:

    /* Load Profiling package */
    var Utils = xdc.loadPackage('ti.utils.profiling');

    /* Load the uart package */
    var Uart = xdc.loadPackage('ti.drv.uart');
    Uart.Settings.enableProfiling = true;
    Uart.Settings.socType = socType;
    Uart.Settings.useDma = "true";

    Afterwards the correct library ‘ti.uart.profiling.dma.aa15fg’ is being used.

    Question 1
    I think that those settings are also missing inside the UART basic example, can you please check this?

    Question 2
    Does it make sense that UART_open() retruns an error in case that DMA is expected but a wrong library is being linked?

    Issue 2
    The buffers where data is read/written from/to were not 128[byte] aligned although the attribute __attribute__ ((aligned (128))) has been added to the variable declaration. The following E2E post refers to the problem:
    e2e.ti.com/.../771857
    As a workaround I added a helper buffer to the firmware, which is 128[bytes] bigger than the expected data to read/write from/to the buffer and use the first 128[byte] aligned address inside that buffer as a pointer for the DMA transfer.

    Question 3
    Does it make sense if the UART driver checks for a 128[byte] alignment and reports an error when calling UART_write2 / UART_read2?

    Issue 3
    It is recommended adding a cache invalidate instruction to the code after the UART DMA read process, such as:
    if (dmaMode)
    {
    CacheP_Inv((void *)l2_global_address((uint32_t)&u8_Input_Buffer_Helper_Array[0]),
    (int32_t)sizeof(u8_Input_Buffer_Helper_Array));
    }
    Question 4
    I think that this instruction is also missing inside the UART basic example after reading the data, can you please check this and tell me in which SDK/PDK version that instruction is being added?

    Issue 4
    There was a bug inside the UART drivers. The RX direction had so far no own DMA channel number element inside structure 'UART_V1_Object'. Therefore it was not possible to run UART DMA on two or more UART instances simultaneously. The fix will be in the next PRSDK release (2019 Q1)

    Issue 5
    You need to ensure that the number of bytes is an integer multiple of your Rx/Tx FIFO level, that you configure prior to open a UART handle.
    if dmaMode == true)
    {
    uart_cfg.edmaHandle = UartApp_edmaInit();
    uart_cfg.dmaMode = TRUE;
    uart_cfg.txTrigLvl = UART_TXTRIGLVL_32;
    uart_cfg.rxTrigLvl = UART_RXTRIGLVL_8;
    }
    Otherwise an additional interrupt will trigger a second DMA process for the remaining bytes that are not an integer multiple of the FIFO levels. Nevertheless one additional interrupt finalizes the UART DMA process in any case. This is simply the behavior of the UART driver.


    Mit freundlichen Grüßen / Best regards,
    Andreas

  • Reply from TI:

    Thanks summarizing the issues met during the UART+DMA usage and driving the quality of the our software!

    • Issue 1: It was fixed in TI 2018 Q4 release (Processor SDK RTOS 5.2).   
    • Issue 2: this is how to align of a field inside a structure. Please see  for more discussion, it is good for the application/test example add a check of alignment, this is not inside he driver.
    • Issue 3: it is valid and we should do this in the test application code.
    • Issue 4: it will be fixed in 2019 Q1 release (PRSDK 5.3)
    • Issue 5: this is an application level usage note how to get uninterrupted DMA transfer.

    Regards, Eric