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/LAUNCHXL-CC1310: UART_read low performance

Part Number: LAUNCHXL-CC1310
Other Parts Discussed in Thread: CC1310

Tool/software: TI-RTOS

Hi,

Tool/software: TI-RTOS 2.13.00.06

I'm implementing Modbus RTU slave on CC1310 hardware. Modbus protocol supposes receiving requests 1 byte at a time, measuring sub-byte timings to detect frame end (and frame errors).

I faced low UART performance (both in BLOCKING and CALLBACK modes) when receiving 1 byte at a time. I have the following simple code to measure receive timings:

void initialize_uart()
{
    UART_Params uartParams;

    /* Create a UART with data processing off. */
    UART_Params_init(&uartParams);
    uartParams.readMode = UART_MODE_BLOCKING;
    uartParams.writeMode = UART_MODE_CALLBACK;
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = MODBUS_UART_BAUDRATE;
    uartParams.readTimeout = UART_WAIT_FOREVER;
    uartParams.writeCallback = UartWriteCallback;

    uart = UART_open(Board_UART0, &uartParams);

    if (uart == NULL)
    {
        System_abort("Error opening the UART");
    }

}

void initialize_modbus()
{
    calculate_timeouts();
    construct_timers();

    resetRxBuffer();
    initialize_uart();

    for (;;)
    {
        t1 = Clock_getTicks();
        int size = UART_read(uart, rxBuffer, UART_RX_BUFFER_SIZE); // 1 byte
        
        memcpy(modbusRxBuffer + rxBufferLength, rxBuffer, size);
        rxBufferLength += size;

        t2 = Clock_getTicks();
        System_printf("recieving took [%lu]us\n", (t2 - t1) * Clock_tick);
    }
}

Using the above code I get approx 3.3ms per byte (stable). At 9600 baudrate it takes roughly 1ms to transfer 1 byte, and 3.3ms per byte leaves much to be desired.

My test app contains one more task that blinks LED, so it is not CPU heavy.

I have lifted UART interrupt priorities, but no luck there. Currently I have:

/* UART hardware parameter structure, also used to assign UART pins */
const UARTCC26XX_HWAttrsV2 uartCC26XXHWAttrs[CC1310_LAUNCHXL_UARTCOUNT] = {
    {
        .baseAddr       = UART0_BASE,
        .powerMngrId    = PowerCC26XX_PERIPH_UART0,
        .intNum         = INT_UART0_COMB,
        .intPriority    = (2 << 5),
        .swiPriority    = 10,
        .txPin          = Board_UART_TX,
        .rxPin          = Board_UART_RX,
        .ctsPin         = PIN_UNASSIGNED,
        .rtsPin         = PIN_UNASSIGNED,
        .ringBufPtr     = uartCC26XXRingBuffer[0],
        .ringBufSize    = sizeof(uartCC26XXRingBuffer[0])
    }
};

Can anyone explain what I am doing wrong with UART setup? Is it possible to reduce processing time?

  • Hi Aliaksei,
    I am trying to reproduce your problem, but I am getting on the order of 1 msec for the UART_read() calls at 9600 baud. Are you calling UART_write() somewhere in your code between the UART_read() calls? Also, you have 'Clock_tick' in your code. I assume you meant Clock_tickPeriod?
    Best regards,
    Janet
  • Hi, janet. Thanks for your reply

    1) I am not calling UART_write until all request bytes are read and timeout is fired

    2) Yes, I meant Clock_tickPeriod (I had hardcoded '10' in original source code, just replaced it here for clearance, but made even worse, sorry)

    I use QModbus to initiate UART requests. Here are my setting for sample request

    Looking at logic analyzer request is emitted OK without halts;

    I am attaching my CCS project for your more convenient diagnostics 

    5635.CC1310_uart_perfomance.zip

    Using the code I get these log records:

    ,Constructed timers t15=1710 us, t35=3990 us (at baudrate=9600)
    ,recieving took [3576500]us
    ,recieving took [3380]us
    ,recieving took [3350]us
    ,recieving took [3350]us
    ,recieving took [3360]us
    ,recieving took [3360]us
    ,recieving took [3360]us
    ,recieving took [3360]us
    ,Subframe timeout fired [4150]us after uart habdle
    ,Initiated response send at [360561]
    ,Received modbus frame: 1 3 0 0 0 62 196 26 
  • Just a little update.

    I'm getting the same behaviour with generic uart_echo (uartecho_CC1310_LAUNCHXL_TI) project.

    (CCS 7.1, xdctools_3_32)

    I've modified main task like this:

    Void echoFxn(UArg arg0, UArg arg1)
    {
    
    // no changes to original uart_echo code above
    
        ULong t1, t2;
        /* Loop forever echoing */
        while (1)
        {
            t1 = Clock_getTicks();
    
            UART_read(uart, &input, 1);
            //UART_write(uart, &input, 1);
            t2 = Clock_getTicks();
            System_printf("recieving took [%lu]us\n", (t2 - t1) * Clock_tickPeriod);
        }
    }

    And I'm getting the same timings ~3,3ms per byte

    recieving took [3360]us
    ,recieving took [3350]us
    ,recieving took [3350]us
    ,recieving took [3360]us
    ,recieving took [3360]us
    

  • Hi Aliakei,
    I copied some of your test code and I am seeing similar times for UART_read() of one byte at 9600 baud (on the order of 3 msecs). I'm not sure what's going on here. I'll need to do some measurements within the driver code to see where the time is being spent. I tried a similar test on a CC3220, and I see the UART_read() times oscillate between about 7us and 1800 us. The short times occur when the data is in the UART's ring buffer and the read just has to copy it out.
    I'll keep you posted on what I find.
    Best regards,
    Janet
  • Thanks for your help, Janet.
    I tried to debug the driver too, but had no luck in finding the cause of this issue.
  • , sorry to bother you. Have you managed to get any additional info/thoughts on the point?
  • Hi Alaksei,
    No problem. This is still on my radar, and I should have more time to look into it early next week.
    Best regards,
    Janet
  • Hi Alaksei,

    I did some more testing on this driver, and I found that if my test only calls UART_read(), the read times come out to approximately 1 msec.  My modified code does the following:

        /* Loop forever echoing */
        while (1) {
            for (i = 0; i < BUFLEN; i++) {    // BUFLEN = 20
                t1 = Clock_getTicks();
                UART_read(uart, buffer + i, 1);
                t2 = Clock_getTicks();

                readTimes[i] = t2 - t1;
                count++;
            }
    #if 0
            for (i = 0; i < BUFLEN; i++) {
                UART_write(uart, buffer + i, 1);
            }
    #endif
        }

    I added UIA instrumentation and you can see that the UART Hwi runs about every 1 msec:

    If I add in the code that calls UART_write(), I then see that the first few reads take about 1 msec, and afterwards about 3 msecs.  The execution graph looks like this:

    I'm not sure why this is happening, though.

    Best regards,

    Janet

  • Hey, Janet

    I confirm that I'm seeing  the same strange behaviour with different periods between Hwi calls.

    But in my case it behaves exactly the same disregarding UART_Write() calls

  • Hi Aliaksei,

    Looking at the UARTCC26XX driver, I see that the interrupt is triggered when the fifo is half full (16 bytes), or when a read timeout occurs.  If you're sending a very small number of bytes at a time to the CC1310 then probably the read timeout is occurring, causing you to get the data at 3 msec intervals instead of 1 msec intervals.  According to the data sheet, the read timeout is 32 periods of the SSIn_CLK.  So at 9600 baud, the timeout would be about 3msecs.  I'm wondering though, why the UART driver ISR isn't copying all the data from the fifo into the ring buffer, so that subsequent reads would pull data from the ring buffer instead of waiting for the read timeout.  I'll look into this some more to find out if this was intentional.

    Best regards,

    Janet