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/EK-TM4C123GXL: Multiple UARTs reading simulatenously

Part Number: EK-TM4C123GXL
Other Parts Discussed in Thread: SYSBIOS

Tool/software: TI-RTOS

Hi,

We have a EK-TM4C123GXL evaluation board to which 3 BMD modules are connected via UART1,UART4 and UART5 lines. TIVA board is supposed to read data from these 3 UART modules and push via USB.  We are using USB serial device as base The three devices work individually without issues. While combining multiple UART reads in a single task, data corruption as well as loss is happening.

Can't multiple UART instances be accessed simultaneously?  I have attached the code snippet where reading is happening. It would be great if someone can point out what I am doing wrong and confirm if this is feasible or not? 

#include <string.h>
#include <stdbool.h>

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

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

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

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

/* USB Reference Module Header file */
#include "USBCDCD.h"

#include <ti/drivers/UART.h>

#define TASKSTACKSIZE 2768

unsigned char text[40] = {0x0}; //"TI-RTOS controls USB.\r\n";

Task_Struct task0Struct, task1Struct;
Char task0Stack[TASKSTACKSIZE], task1Stack[TASKSTACKSIZE];
unsigned char data_uart1[20]={0};
unsigned char data_uart2[20]={0};
unsigned char data_uart3[20]={0};
uint16_t uart1_length=0;
uint16_t uart2_length=0;
uint16_t uart3_length=0;
UART_Handle uart, uart1, uart2, uart3, uart4, uart5;
UART_Params uartParams, uart1Params, uart2Params, uart3Params, uartParams4, uartParams5;
/
/*
* ======== receiveFxn ========
* Task to receive serial data.
*
* This task will receive data when data is available and block while the
* device is not connected to the USB host or if no data was received.
*/
Void receiveFxn(UArg arg0, UArg arg1)
{

UART_Params_init(&uart1Params);
uart1Params.writeDataMode = UART_DATA_BINARY;
uart1Params.readDataMode = UART_DATA_BINARY;
uart1Params.readReturnMode = UART_RETURN_FULL;
uart1Params.readEcho = UART_ECHO_OFF;
uart1Params.baudRate = 115200;
uart1 = UART_open(Board_UART1, &uart1Params);

if (uart1 == NULL) {
System_printf("NOT opened");
System_flush();
}

UART_Params_init(&uart3Params);
uart3Params.writeDataMode = UART_DATA_BINARY;
uart3Params.readDataMode = UART_DATA_BINARY;
uart3Params.readReturnMode = UART_RETURN_FULL;
uart3Params.readEcho = UART_ECHO_OFF;
uart3Params.baudRate = 115200;
uart3 = UART_open(Board_UART5, &uart3Params);

if (uart3 == NULL) {
System_printf("NOT opened");
System_flush();
}

UART_Params_init(&uart2Params);
uart2Params.writeDataMode = UART_DATA_BINARY;
uart2Params.readDataMode = UART_DATA_BINARY;
uart2Params.readReturnMode = UART_RETURN_FULL;
uart2Params.readEcho = UART_ECHO_OFF;
uart2Params.baudRate = 115200;
uart2 = UART_open(Board_UART4, &uart2Params);

if (uart2 == NULL) {
System_printf("NOT opened");
System_flush();
}
while (true) {

memset(data_uart1,0x00,sizeof(data_uart1));
memset(data_uart3,0x00,sizeof(data_uart3));
memset(data_uart2,0x00,sizeof(data_uart2));
memset(text,0x00,sizeof(text));

uart1_length =UART_read(uart1,data_uart1,sizeof(data_uart1));
uart3_length =UART_read(uart3,data_uart3,sizeof(data_uart3));
uart2_length =UART_read(uart2,data_uart2,sizeof(data_uart2));
memcpy(text,data_uart1,sizeof(data_uart1));
memcpy(text+sizeof(data_uart1),data_uart2,sizeof(data_uart2));
 memcpy(text+sizeof(data_uart1)+sizeof(data_uart2),data_uart3,sizeof(data_uart3));
USBCDCD_waitForConnect(BIOS_WAIT_FOREVER);
USBCDCD_sendData(text, sizeof(text), BIOS_WAIT_FOREVER);
}
}

/*
* ======== main ========
*/
int main(void)
{
/* Construct BIOS objects */
Task_Params taskParams;

/* Call board init functions */
Board_initGeneral();
Board_initGPIO();
Board_initUSB(Board_USBDEVICE);
Board_initUART();
USBCDCD_init();

/* Construct tx/rx Task threads */
Task_Params_init(&taskParams);
taskParams.stackSize = TASKSTACKSIZE;
taskParams.stack = &task0Stack;
taskParams.priority = 2;
// Task_construct(&task0Struct, (Task_FuncPtr)transmitFxn, &taskParams, NULL);

taskParams.stack = &task1Stack;
Task_construct(&task1Struct, (Task_FuncPtr)receiveFxn, &taskParams, NULL);

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


/* SysMin will only print to the console when you call flush or exit */
System_flush();

/* Start BIOS */
BIOS_start();

return (0);
}

  • The answer depends on your definition of "simultaneously"

    Each hardware uart is independent from each other and can receive data at the same time.

    However, there is only one core so the mcu has to read the data sequentially . For most people, the read is so fast it is practically simultaneous, but not exactly simultaneous.

  • Hi,

    The data will be received in UARTs independently. As we are using blocking mode of implementation, my assumption is code will wait till one UART receives the mentioned amount of data.

    Our problem is say, UART1 receives 20 byte data, from sensor 1 and UART2 receives 20 bytes from sensor 2 and similarly sensor 3 pushes to UART3. When there is a single UART read in code, we are receiving data as such without mixing. Once that was done, we added UART1 and UART2 together. With UART1 read followed by UART2 read.For sometime, it works without issues, and then it starts mixing say, packet 1 is of format <7D7A1234567890123456789FE> and packet 2 is of format <7D7B12345678901234567890FE> at times the packets received in USB will be like <7D7A12345678FE125468797D7B123467876712EF> sort of. It gets mixed without any specific pattern.

    We tried sending hardcoded data to rule out memcpy() related issues, and it worked fine. so we are left with UART read operations in a sequential manner as the point of corruption.

    Is there a problem in using UART read continuously? Can this be avoided?
  • Hello Annamol,

    I would recommend finding a method to confirm the UART data is received correctly first and foremost. Right now there are two possibilities. 1) the mixing is causing a problem (likely), 2) the UART data is not received right (based on description, less likely IMO).

    To try and separate these possible issues enough that we can identify which one is the root cause, I would recommend to print out the UART data after reception each time, and then apply the mixing afterward and print that out. If the error occurs during mixing/secondary output stage, that's where your problem lies and that would be more of a coding issue than anything. If the UART data is printed wrong, then you should use breakpoints to check the buffer that the UART data was transferred into and see if the corrupt came from print out of data or incorrect reception of data.

    Also, when you say mixing, is that was is being done by functions like this?

    memcpy(text+sizeof(data_uart1),data_uart2,sizeof(data_uart2));
  • We note that the UART data rate is (now) 115K.      Might a simpler determination of error's source result from slowing the data rate?      (suggest 19.2K - if this succeeds - the rate may be gradually increased - to determine "where it breaks!")

    I'm not so sure that any "print operation" would prove best due to the demands imposed.     Would not the establishment of  "Separate buffers" - one for EACH UART - provide a "cleaner & more secure data collection" - while "escaping" any penalties imposed by "print."     Is not the goal - most always - to "capture the data best" - while imposing the minimum "disturbance?"

    The establishment of separate buffers - and the slowed UART data rate - meets "KISS" requirements - and should best lead to success.     (or optimization - in the case where the objective is not (really) obtainable...

    It should be noted - most always - that any poster mention of  "simultaneous" - should properly lead "helper crüe" to "duck & cover!"