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.

EK-TM4C1294XL: Issues with reading a packet with TI RTOS UART_read()

Part Number: EK-TM4C1294XL

Hi, 

I am writing a uart driver code for TM4C1294XL using TI RTOS for TIVA C version 2.16.0.08. I have attached .c file.

The goal is to segregate the UART packet based on the packet header and store it in a particular variable.

As I am new to TI RTOS, I referred the 'uartecho.c' and made the changes accordingly.

However, sometimes I see that the packets are corrupted.

Can anyone suggest any ideas on how to debug this issue?

Thank you

Shaunak

/*
 * Copyright (c) 2015, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 *  ======== uartecho.c ========
 */

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>

/* TI-RTOS Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/UART.h>

/* Example/Board Header files */
#include "Board.h"

#include "USBCDCD_LoggerIdle.h"

#include <stdint.h>

//#include "uc_pinmap.h"

#define TASKSTACKSIZE     8192

uint32_t g_data_array[10];
uint32_t g_setup[5];
uint32_t g_experiment_data[10][100];
uint32_t g_temp_prog_data[10][8];
uint32_t g_header;
uint8_t g_experiment_index;
uint8_t g_temp_prog_index;

Task_Struct task0Struct;
Char task0Stack[TASKSTACKSIZE];

/*
 *  ======== echoFxn ========
 *  Task for this function is created statically. See the project's .cfg file.
 */
Void echoFxn(UArg arg0, UArg arg1)
{

//    Log_info2("tsk1 Entering. arg0,1 = %d %d", arg0, arg1);

    int j;
    for (j = 0; j < 10; j++)
        g_data_array[0] = 0;

    uint32_t packet_header = 0;
    uint32_t packet_size = 0;
    uint32_t uart_rx_data = 0;
    int ret;

//    System_printf("Size of uart data array is %d\n", sizeof(uart_data));
//    System_flush();

    UART_Handle uart;
    UART_Params uartParams;
//    const char echoPrompt[] = "UART DATA:\r\n";

    /* Create a UART with data processing off. */
    UART_Params_init(&uartParams);
    uartParams.dataLength = UART_LEN_8;
    uartParams.parityType = UART_PAR_NONE;
    uartParams.stopBits = UART_STOP_ONE;
    uartParams.baudRate = 9600;
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readMode = UART_MODE_BLOCKING;
    uartParams.readEcho = UART_ECHO_OFF;

    uart = UART_open(Board_UART0, &uartParams);

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

//    UART_write(uart, echoPrompt, sizeof(echoPrompt));

//    uint32_t status = 0;

    while (1)
    {
        // Read packet header and process accordingly
        ret = UART_read(uart, &packet_header, sizeof(packet_header));
        g_data_array[0] = packet_header;
        g_header = packet_header;
        System_printf("%d\n", g_header);
        System_flush();

        if (ret > 0)
        {
            // Read size of incoming packet
            ret = UART_read(uart, &packet_size, sizeof(packet_size));
            g_data_array[1] = packet_size;

            switch (packet_header)
            {

            case (SETUP):
            {

                g_experiment_index = 0;
                g_temp_prog_index = 0;
                int i = 0;
                g_setup[0] = packet_header;

                // Read the data and store in appropriate variable
                for (i = 0; i < packet_size; i++)
                {
                    UART_read(uart, &uart_rx_data, sizeof(uart_rx_data));
                    g_data_array[i + 2] = uart_rx_data;
                    g_setup[i + 1] = uart_rx_data;
                }

                break;
            }
            case (TIME):
            {
                int i = 0;
                g_experiment_data[g_experiment_index][0] = packet_header;
                g_experiment_data[g_experiment_index][1] = packet_size;

                // Read the data and store in appropriate variable
                for (i = 0; i < packet_size; i++)
                {
                    UART_read(uart, &uart_rx_data, sizeof(uart_rx_data));
                    g_data_array[i + 2] = uart_rx_data;
                    g_experiment_data[g_experiment_index][i + 2] = uart_rx_data;
                }

                g_experiment_index++;
                System_printf("Experiment Index is %d\n", g_experiment_index);
                System_flush();
                break;
            }
            case (VALVE):
            {
                int i = 0;
                g_experiment_data[g_experiment_index][0] = packet_header;
                g_experiment_data[g_experiment_index][1] = packet_size;

                // Read the data and store in appropriate variable
                for (i = 0; i < packet_size; i++)
                {
                    UART_read(uart, &uart_rx_data, sizeof(uart_rx_data));
                    g_data_array[i + 2] = uart_rx_data;
                    g_experiment_data[g_experiment_index][i + 2] = uart_rx_data;
                }

                g_experiment_index++;
                System_printf("Experiment Index is %d\n", g_experiment_index);
                System_flush();
                break;
            }
            case (PUMP):
            {
                int i = 0;

                g_experiment_data[g_experiment_index][0] = packet_header;
                g_experiment_data[g_experiment_index][1] = packet_size;

                // Read the data and store in appropriate variable
                for (i = 0; i < packet_size; i++)
                {
                    UART_read(uart, &uart_rx_data, sizeof(uart_rx_data));
                    g_data_array[i + 2] = uart_rx_data;
                    g_experiment_data[g_experiment_index][i + 2] = uart_rx_data;
                }

                g_experiment_index++;
                System_printf("Experiment Index is %d\n", g_experiment_index);
                System_flush();
                break;
            }
            case (HEATER):
            {

                int i = 0;

                g_experiment_data[g_experiment_index][0] = packet_header;
                g_experiment_data[g_experiment_index][1] = packet_size;

                // Read the data and store in appropriate variable
                for (i = 0; i < packet_size; i++)
                {
                    UART_read(uart, &uart_rx_data, sizeof(uart_rx_data));
                    g_data_array[i + 2] = uart_rx_data;
                    g_experiment_data[g_experiment_index][i + 2] = uart_rx_data;
                }

                g_experiment_index++;
                System_printf("Experiment Index is %d\n", g_experiment_index);
                System_flush();
                break;
            }
            case (TEMP_PROG):
            {
                int i = 0;
                g_temp_prog_data[0][0] = packet_header;
                g_temp_prog_data[0][1] = packet_size;

                // Read the data and store in appropriate variable
                for (i = 0; i < packet_size; i++)
                {
                    UART_read(uart, &uart_rx_data, sizeof(uart_rx_data));
                    g_data_array[i + 2] = uart_rx_data;
                    g_temp_prog_data[g_temp_prog_index][i + 2] = uart_rx_data;
                }

                g_temp_prog_index++;
                break;
            }
            case (COMM_COMPLETE):
            {

                // Reset variable after COMM_COMPLETE is received
                g_temp_prog_index = 0;
                g_experiment_index = 0;

                System_printf("Resetting experiment and temp prog data\n");
                System_flush();
            }
            default:
            {
                break;
            }
            }
        }
    }
}

/*
 *  ======== main ========
 */
int main(void)
{
    /* Call board init functions */
    Board_initGeneral();
    Board_initGPIO();
    Board_initUART();

    Board_initUSB(Board_USBDEVICE);

    /* Construct BIOS objects */
    Task_Params taskParams;

    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    taskParams.stack = &task0Stack;
    taskParams.instance->name = "echo";
    taskParams.priority = 1;
    Task_construct(&task0Struct, (Task_FuncPtr) echoFxn, &taskParams, NULL);

    /* Turn on user LED */
    GPIO_write(Board_LED0, Board_LED_ON);

    USBCDCD_init();

    /* This example has logging and many other debug capabilities enabled */
    System_printf("Parse UART Packets using RTOS\n");
    System_flush();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

  • Hello Shaunak,

    Can you describe more what you mean by how packets are corrupted? Your code is rather large to sift through and so I would need more detail here to be able to better guide you.

    I see you have print statements in multiple sections, have you tried labeling those based on the section they are in to see which segments of your code is having an issue?

    Is there any particular pattern you see regarding the corruption?

    Do you have the ability to use a logic analyzer to view the UART lines and see if the data is arriving correctly?

  • Following up on Ralph's request, are the packet header and packet size really both four characters each? You define both packet_header and packet_size as uint32_t. Therefore sizeof(packet_header) is 4. Did you really want to read four bytes when reading the packet header?

  • Hey Ralph,

    I have attached two images.

    This image shows accurate parsing of incoming UART packet

    Whereas, in the following image you can see corrupted packet

    The data for some reason takes value of 2^24/2^25.

    Ralph Jacobi said:

    Do you have the ability to use a logic analyzer to view the UART lines and see if the data is arriving correctly?

    Currently, I don't have access to a logic analyzer. 

    Thank you,

    Shaunak

  • Hi Bob,

    Yes, packet_header and packet_header does not require 4 bytes, but the software sends 4 bytes unsigned int over uart. Thus, they are defined as uin32_t.

    Thanks,

    Shaunak

  • shaunak m said:
    The data for some reason takes value of 2^24/2^25.

    Looking at those values in hex suggests 3 bytes have got dropped somewhere, and the 4 byte packet_header then gets 'offset' to the actual stream.

    I haven't yet looked at your code, but a previous investigation into the TI-RTOS to TivaC UART driver found if receive errors occur the receive characters with the errors are not placed in the ring buffer and UART_read() doesn't return UART_ERROR. See TM4C129ENCPDT: Issue with UART_read(). Perhaps you could try setting a breakpoint on the errorCallback() function shown in the referenced thread to see if receive errors are occurring.

  • Hello Shaunak,

    I agree with Chester's thoughts here as well. Reviewing your code I noticed that you do not check the return value for UART_read to verify the data is valid after the initial check to read the size. Though I hadn't heard yet that there is an issue with the UART_read return. My understanding, and correct me if I am wrong Chester, is that UART_read will sometimes fail to return UART_ERROR under specific conditions. If so, I believe it would still be useful to check first to see if there are errors occurring before trying to workaround the issue with the UART_read.

  • It looks to me like UART_read() will return the number of characters that are in the buffer. If you don't want it to return until you get all of the characters requested, you should call UART_readPolling().

  • Sure, will try this and update here.