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.

TM4C129ENCPDT: Issue with UART_read()

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

While using UART_read with the following configuration

st_uartParams.baudRate = 115200;

st_uartParams.readEcho = UART_ECHO_OFF;

st_uartParams.readTimeout = 5000u;
st_uartParams.readDataMode = UART_DATA_BINARY;
st_uartParams.writeDataMode = UART_DATA_BINARY;
st_uartParams.readReturnMode = UART_RETURN_FULL;
st_uartParams.dataLength = UART_LEN_8;
st_uartParams.parityType = UART_PAR_EVEN;

 

 to communicate  with a module which has 

 

Baud rate :115200 

Data bits : 8 
Stop bits  :1 
Parity : even

Has a fixed response frame length of 12 bytes

This device has RX, TX and Ground connections only

The module is expected to respond within 50ms

 

i am experiencing data loss . i am trying to receive a 12 byte data from a module( i had verified the data by taking a connection from my Controller RX and observing it on a serial software, it was as per the modules manual). my observation is that i am missing some bytes when my controller reads the data , so my controller returns the UART_read (waiting for 12 bytes , s8ReturnBytes = (int8_t)UART_read(s_st_uartHandle, (void_t *)au8RecvPacket, 12); ) as timeout and returns less than 12 bytes.

 

Has anyone experienced a similar issue?

What should be done to solve this? 

 

i am using 12.16.0.08

 

  • HI Joseph,

      Not sure what is wrong. Let me see if I can help you before asking for assistance from our TI-RTOS experts. A couple of things for you to check.

      - Can you check on a scope what is being sent to the MCU for these 12 bytes? Are there 0 being sent as the data?

      - On the scope or logic analyzer, what is the elapsed time between any two bytes?

      - For experimental purpose, what if you change the number of bytes from 12 to something like 4 or 6. Do you still miss the middle bytes? Per your description, you only receive the first and the last byte?

      - Can you check if the external device is properly configured for the same baud rate, parity and stop bits?

      - In the CCS peripheral window, can you check if you are getting any errors on the UART?

      - In your board configuration file can you find out the setting for your uartTivaHWAttrs attributes? Below is from an example. Yours might be different. 

      

    /* UART configuration structure */
    const UARTTiva_HWAttrs uartTivaHWAttrs[EK_TM4C129EXL_UARTCOUNT] = {
    {
    .baseAddr = UART0_BASE,
    .intNum = INT_UART0,
    .intPriority = (~0),
    .flowControl = (UART_FLOWCONTROL_TX | UART_FLOWCONTROL_TX),
    .ringBufPtr = uartTivaRingBuffer[0],
    .ringBufSize = sizeof(uartTivaRingBuffer[0])
    }
    };

  • joseph xavier said:
    mostly i feel zero(0x00) bytes are beining lost .

    I attempted to repeat this with tirtos_tivac_2_16_00_08 by creating the following task which loop-backs 12 bytes 'packets' of binary data over the UART:

    #define BUFFER_LEN 12
    int total_rx_bytes;
    Void echoFxn(UArg arg0, UArg arg1)
    {
        UART_Handle uart;
        UART_Params uartParams;
        Uint8 tx_buffer[BUFFER_LEN];
        Uint8 rx_buffer[BUFFER_LEN];
        Uint8 tx_pattern = 1;
        Uint8 rx_pattern = tx_pattern;
        int rc;
        int index;
    
        /* Create a UART with data processing off. */
        UART_Params_init(&uartParams);
        uartParams.readTimeout = 5000u;
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
        uartParams.dataLength = UART_LEN_8;
        uartParams.parityType = UART_PAR_EVEN;
        uart = UART_open(Board_UART2, &uartParams);
    
        if (uart == NULL) {
            System_abort("Error opening the UART");
        }
    
        /* Loop forever echoing */
        while (1) {
            for (index = 0; index < BUFFER_LEN; index++)
            {
                tx_buffer[index] = tx_pattern++;
            }
            rc = UART_write (uart, tx_buffer, BUFFER_LEN);
            Assert_isTrue (rc == BUFFER_LEN, NULL);
            rc = UART_read (uart, rx_buffer, BUFFER_LEN);
            Assert_isTrue (rc == BUFFER_LEN, NULL);
            for (index = 0; index < BUFFER_LEN; index++)
            {
                Assert_isTrue (rx_buffer[index] == rx_pattern, NULL);
                rx_pattern++;
            }
            total_rx_bytes += rc;
        }
    }
    

    The asserts check if incorrect data is received, and using the CCS Expressions view to monitor continuous updates to the total_rx_bytes global variable can check that continues to run. So far has looped back 10,000,000 bytes without error.

    This uses UART 2 Tx and Rx loop backed externally on a EK-TM4C1294XL with a wire between booster pack A2 pins 5 (PD4) and 6 (PD5). If remove the wire while the program is running it stops with UART_read reporting a timeout (i.e. return less than BUFFER_LEN) as a way of checking the error handling.

    I.e. so far haven't been able to repeat a problem in the TI-RTOS for TivaC UART driver.

  • Hi Tsai,

    Thanks for ur prompt reply, i had added few more details to the query i had posted above

    and regarding the *UART configuration structure i have configured as following

    const UARTTiva_HWAttrs uartTivaHWAttrs[EK_TM4C129EXL_UARTCOUNT] = {

    {
    .baseAddr = UART0_BASE,
    .intNum = INT_UART0,
    .intPriority = (~0),
    .flowControl = UART_FLOWCONTROL_NONE,
    .ringBufPtr = uartTivaRingBuffer[0],
    .ringBufSize = sizeof(uartTivaRingBuffer[0])
    },

    };

    the external device communicates properly when connected to PC using serial application ( i cant configure it as its a bought out module)

  • i don't have this issue consistently , it happens once a while( once in 10 attempts or like that, some times more frequent) and regarding the loop-back ,i think it will be more error free compared to my scenario right?

    as i have mentioned in the query i was able to observed the data by taking a connection from the controller RX at the same time when the controller was showing less bytes in debug mode..

    I am using this UART_read for getting my 12 byte response from another module, which responds in less than 50 ms( i had given time out of 500ms).

    my UART_read is called after the command is transmitted to the module ( in the same thread).

  • HI Joseph,

      Thanks to Chester for his testcase. Can you try Chester's example? What is your external serial device setting? Baud rate, parity and number of stop bits?

  • i have updated it in my 1st query 

    it has a

    Baud rate :115200 

    Data bits : 8 
    Stop bits  :1 
    Parity : even

    Has a fixed response frame length of 12 bytes

    This device has RX, TX and Ground connections only

    The module is expected to respond within 50ms

  • Hi,

      My key take away from you last post is that you said it sometimes works (once or multiple times out of 10).

      Are you able to tell the difference between when it is working and when it is not?

      Can you repeat the same problem with another board?

      I'm not sure if there is something to do with the Ringbuffer. What is your current size on the ring buffer? See below example in the board file. Can you increase it to something larger than what you currently have. Let's say double the amount. 

    unsigned char uartTivaRingBuffer[EK_TM4C129EXL_UARTCOUNT][32];

     Depending on your answers for above, I may need to forward your question to our TI-RTOS expert.

  • joseph xavier said:
    i don't have this issue consistently , it happens once a while( once in 10 attempts or like that, some times more frequent) and regarding the loop-back ,i think it will be more error free compared to my scenario right?

    Agreed, I just created the loop back example to see if could identify any obvious problem with the TI-RTOS UART driver. I left my program running and has got to 142,604,976 bytes looped back with no error.

    joseph xavier said:
    as i have mentioned in the query i was able to observed the data by taking a connection from the controller RX at the same time when the controller was showing less bytes in debug mode..

    Is it possible that some receive errors were detected. E.g. invalid parity?

    From a quick look at the tirtos_tivac_2_16_01_14\products\tidrivers_tivac_2_16_01_13\packages\ti\drivers\uart\UARTTiva.c driver, if receive errors are detected for a character the readIsrBinaryBlocking() function:

    a. Won't place the character with the receive error in the ring buffer.

    b. Will call the errorCallback() function which has Log_printl calls:

    /*
     *  ======== errorCallback ========
     *  Generic log function for when unexpected events occur.
     */
    static void errorCallback(UART_Handle handle, uintptr_t error)
    {
        if (error & UART_RXERROR_OVERRUN) {
            Log_print1(Diags_USER2, "UART:(%p): OVERRUN ERROR",
                ((UARTTiva_HWAttrs const *)handle->hwAttrs)->baseAddr);
        }
        if (error & UART_RXERROR_BREAK) {
            Log_print1(Diags_USER2, "UART:(%p): BREAK ERROR",
                ((UARTTiva_HWAttrs const *)handle->hwAttrs)->baseAddr);
        }
        if (error & UART_RXERROR_PARITY) {
            Log_print1(Diags_USER2, "UART:(%p): PARITY ERROR",
                ((UARTTiva_HWAttrs const *)handle->hwAttrs)->baseAddr);
        }
        if (error & UART_RXERROR_FRAMING) {
            Log_print1(Diags_USER2, "UART:(%p): FRAMING ERROR",
                ((UARTTiva_HWAttrs const *)handle->hwAttrs)->baseAddr);
        }
    }
    

    Not sure if you can enable those log print functions and/or set a breakpoint on the errorCallback() function to see if it is getting called.

  • hi, i also had the same doubt and tried increasing the unsigned char uartTivaRingBuffer[EK_TM4C129EXL_UARTCOUNT][32]; size from 32 to 320 , still had the same issue, its a ring buffer right so is there any chance of data loss?

  • thanks for your reply ,

    i will look into it and update you, but still in case of any error the UART read will return a error(UART_ERROR) right i haven't seen that happening .

    do you fell that i will have any improvement if i use the UART_MODE_CALLBACK method ?

  • joseph xavier said:
    i will look into it and update you, but still in case of any error the UART read will return a error(UART_ERROR) right i haven't seen that happening .

    I performed a test of a loopback using two UARTS with configuration such that:

    a. The transmit UART is configured as 8 bits with no parity. Logically the software transmits 7-bit characters and sets the most significant bit as either odd or even parity on a character-by-character basis.

    b. The receive UART is configured as 7 bits with even parity.

    When UART_write was used to transmit the following 12 characters in a buffer:

    • 0x01(with even parity)
    • 0x02 (with odd parity)
    • 0x03 (with even parity)
    • 0x04 (with even parity)
    • 0x05 (with even parity)
    • 0x06 (with even parity)
    • 0x07 (with even parity)
    • 0x08 (with odd parity)
    • 0x09 (with even parity)
    • 0x0a (with odd parity)
    • 0x0b (with even parity)
    • 0x0c (with even parity)

    Then a call to UART_read for a 12 byte buffer returned the value of 9 and the bytes in the buffer were 01 03 04 05 06 07 09 0b 0c. I.e. when there were 3 characters with parity errors then the UART_read call didn't return UART_ERROR and the characters with the parity errors were simply excluded from the returned buffer. I also think the UART_read ran into the timeout before returning, albeit I didn't add timing to prove this.

    Therefore, receive errors could be the cause of your problem.

    joseph xavier said:
    do you fell that i will have any improvement if i use the UART_MODE_CALLBACK method ?

    Looking into the driver code I don't think the UART_MODE_CALLBACK method will help, but I haven't yet attempted to test that.

  • Chester Gillon said:
    I also think the UART_read ran into the timeout before returning, albeit I didn't add timing to prove this.

    By adding Timestamp_get32() calls around the UART_read(), confirm that when looped back 12 characters consisting of 9 with valid parity and 3 with invalid parity that the UART_read() call for 12 characters only returned after the timeout set in the UART parameters had expired. And as above, the UART_read() call only returned the 9 characters with valid parity.

  • Hi All,

    Over runs seem to occur on 16 byte RX boundary for the TM4C1294 but Joseph has TM4C129 shown in his 1st post header.

    Seemingly a good application should Poll UART status each RX interrupt cycle and print a debug error and flush the RX buffer. If the boundary is less than 12 bytes it may require a delay in the RX loop at byte 11 if excessive over runs occur during repetitive client broadcasts. Perhaps If the baud rate clocks are to far skewed data will randomly get corrupted. A good reason for crystal controlled clocks to be fairly close likewise the rate divisors.

    This status method below works well.

     int i;
     uint32_t ui32IntStatus = 0;
     uint32_t ui32RxErrorStatus;
    
        /* Load the RX error status bits */
        ui32RxErrorStatus = (UART_RXERROR_FRAMING|UART_RXERROR_PARITY
        						|UART_RXERROR_BREAK|UART_RXERROR_OVERRUN);
    
        /* Get the UARTICR status bits.
         * false: RAW bits, true: Mask IM bits */
        ui32IntStatus = MAP_UARTIntStatus(UART3_BASE, true);
    
    
       /* Check interrupts UARTICR bits RXINT, RX timeout, etc.  */
        if(ui32IntStatus & (UART_INT_RX | UART_INT_RT))
        {
            /* Durring interrupt check the RSR/ECR register for
             * RX errors: OE, BE, PE, FE  */
            if(ui32RxErrorStatus &= MAP_UARTRxErrorGet(UART3_BASE))
            {
                /* Clear all ECR error bits and return */
                MAP_UARTRxErrorClear(UART3_BASE);
                //
    #if DEBUG
                /* Print the error event message */
                UARTprintf("\n RxError: %x\n\n", ui32RxErrorStatus);
    #endif
            	/* Flush the RX buffer */
                for(i=0; i <= 32; i++)
                {
                	CcRxBuff[i] = 0;
                }
                //
    #if DEBUG
                UARTprintf("\n>> RxBuffFlush: \n");
    #endif
                //
                return;
    }