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: UART Interface receiving first byte '0' at the beginning for actual data packet

Part Number: TM4C129ENCPDT

Kindly ignore if its a blunder mistake, will someone please help me to troubleshoot the issue on receiving data using UART,  I am sending a command through UART1 (baud rate 115200) and receiving the response. the command send and the response data from the other system is correct (the response is analysed using com port) , but on receiving the data bytes to an array; the first byte is received as zero. some help is highly favorable. The same code is below.

Thanks 

UART1_Send((uint8_t *) Receiver_Command, 5);                                              // Sending command 
//------------------------------------------------------------------------------------------
Delay_Milli_Sec(6); // 6 ms delay for receiving the response from receiver   // waiting time for collecting data and response of other device 

_______________________________________________________________________________________________________________________________________________________________

void Delay_Milli_Sec(uint32_t Delay_value)
{
uint32_t Timer_Count;

Timer_Count = (120000 * Delay_value); // Count calcultion for value in milli sec

ROM_IntEnable(INT_TIMER3A);
ROM_TimerIntEnable(TIMER3_BASE, TIMER_TIMA_TIMEOUT);
ROM_TimerLoadSet(TIMER3_BASE, INT_TIMER3A, Timer_Count);
ROM_TimerEnable(TIMER3_BASE, TIMER_A);
while(DelaySet_Flag == 0)
{
// Wait Delay
}
DelaySet_Flag=0;
ROM_TimerIntDisable(TIMER3_BASE, TIMER_A); // Disable Timer3 interrupt
ROM_TimerDisable(TIMER3_BASE, TIMER_A); // Disable Timer3
}

______________________________________________________________________________________________________________________________________________________________

void
UART1_IntHandler(void)
{
Interrupt_Flag = (Interrupt_Flag | uart1_interrupt); // Global variable
Receive_Wait_Flag = (Receive_Wait_Flag | uart1_interrupt); // Global variable >> uart1 interrupt >> Receive wait flag set
static uint32_t ui32Status; // local variable >> interrupt status
static uint8_t uart1_data;
static uint32_t Max_byte=34; // initially set for 34 bytes
static uint32_t Current_Char = 0; // First data location in array
ui32Status = ROM_UARTIntStatus(UART1_BASE, true); // Get the interrrupt status.
ROM_UARTIntClear(UART1_BASE, ui32Status); // Clear the asserted interrupts.
while(ROM_UARTCharsAvail(UART1_BASE)) // Loop while there are characters in the receive FIFO.
{
uart1_data = ROM_UARTCharGetNonBlocking(UART1_BASE); // Read the next character from the UART1

if(Current_Char<Max_byte)
{
uart1_data_packet[Current_Char++] = uart1_data; // read each byte to uart1_data_packet array

if((uart1_data_packet[0]==0xf0)&&(uart1_data_packet[1]==0xf0)) // check for Receiver_Command message ID to set the byte count of the response data
{
Max_byte=34; // update count value according to the Command message ID
if(Current_Char==33)
{
Current_Char = 0; // clear array to 0 location
Receive_Wait_Flag &= 0xfd;
}
}
else if((uart1_data_packet[0]==0xaa)&&(uart1_data_packet[1]==0x79))
{
Max_byte=4; // update count value according to the Command message ID
if(Current_Char==3)
{
Current_Char = 0; // clear array to 0 location
Receive_Wait_Flag &= 0xfd;
}
}
else
{
Current_Char=0;
}
}

}

}

  • Kurian,

    You are using ROM_UARTCharGetNonBlocking(UART1_BASE) to read your FIFO. Although you do wait for an interrupt to enter the routine, maybe the interrupt occurred for a different reason, and there is nothing on your FIFO at that moment.
    A few suggestions:
    - Make your IRS shorter: try to simply enable some sort of flag inside it and process the commands outside.
    - Inside the IRS, check the reason for the interrupt before each code block.
    Cheers
    Bruno
  • And, once you have received a command / string, copy it to another buffer for evaluation in the main code. Don't use the interrupt receive buffer.

    Otherwise, you will have the buffer contents overwritten - via the UART interrupt routine - while you examine it. The effect will be somewhere in between "strange" and "havoc".

  • Thank you Bruno and f.m,

    I have modified the ISR as follows, even though the result is same. 

    _______________________________________________________________________________________________________________________

    void

    UART1_IntHandler(void)

    Interrupt_Flag = (Interrupt_Flag | uart1_interrupt); // Global variable 
    static uint32_t ui32Status; // local variable >> interrupt status 
    static uint8_t uart1_data;

    static uint8_t Current_Char = 0; 

    ui32Status = ROM_UARTIntStatus(UART1_BASE, true); // Get the interrrupt status.
    ROM_UARTIntClear(UART1_BASE, ui32Status); // Clear the asserted interrupts. 
    while(ROM_UARTCharsAvail(UART1_BASE)) // Loop while there are characters in the receive FIFO.
    {
    uart1_data = ROM_UARTCharGetNonBlocking(UART1_BASE); // Read the next character from the UART1 
    uart1_data_packet[Current_Char++] = uart1_data;

    }

    }

    ___________________________________________________________________________________________________________________

  • Hi,

    Please tell us how did you configured uart interrupts. Usually, in uart interrupts you must check which speciffically kind of interrupt occured - either a receive one or a send one or other kind and take corresponding paths in your interrupt routine.

  • And there is something else not reported here and (IMHO) not implemented.

    I am sending a command through UART1 (baud rate 115200) and receiving the response.

    How do these commands look like, i.e. how long are they, and how do the start and termination characters look like ?

    In your (last) UART receive handler code, you write received bytes unconditionally into the receive buffer, and increment the index. That's not quite defensive coding.

  • Thanks f.m, that was the answer.

    The expected bytes are either 4 byte or 34 byte data packet.
    the following code resolves the issue. my sincere thanks to Bruno, f.m, Petrei and the TI team.
    _____________________________________________________________________________________________________________
    void
    UART1_IntHandler(void)
    {
    Interrupt_Flag = (Interrupt_Flag | uart1_interrupt); // Global variable
    static uint32_t ui32Status; // local variable >> interrupt status
    if ((Current_Char == 34)||(Current_Char == 4))
    {
    Current_Char = 0; // First data location in array
    }
    ui32Status = ROM_UARTIntStatus(UART1_BASE, true); // Get the interrrupt status.
    ROM_UARTIntClear(UART1_BASE, ui32Status); // Clear the asserted interrupts.
    while(ROM_UARTCharsAvail(UART1_BASE)) // Loop while there are characters in the receive FIFO.
    {
    uart1_data_packet[Current_Char++] = ROM_UARTCharGetNonBlocking(UART1_BASE); // Read the next character from the UART1
    }
    }
    __________________________________________________________________________________________________________________
  • KurianThomas said:
    ... the following code resolves the issue.

    Actually, I think not.

    KurianThomas said:
    if ((Current_Char == 34)||(Current_Char == 4))
    {
    Current_Char = 0; // First data location in array
    }

    That would reset the index to the begin of the array after the 5.th character (following the supposed end character), and thus effectively scrub the last received command. That was exactly the problem in the first place, wasn't it ?

    And if your command are always either 4 bytes or 34 bytes long, you will never receive a 34 byte command that way.

    I can't see how you pass a received command to the main code. Working directly on data (an array) that are modified by asynchronous events (interrupts) is definitely bound to fail.

  • Kurian,

    This might sound tiring, but bear with us for a moment:

    Do totally separate your code:

    1) one section is responsible to receive ANYTHING from a UART port (later in life you will want it to receive ANYTHING via ANY SORT OF SERIAL COMM LAYER, but that's a more complex story). That part stores received bytes into a circular buffer, and increments the last filled position.

    2) one different section parses the content of your buffer and figures out if some valid command or message was received.

    Hard coded solutions like "expecting a fixed message length", "expecting a particular byte sequence", are rather implemented at your protocol level (inside the parser), not on the communication level.

    Be persistent and don't hesitate to shout back!

    Bruno

  • Bruno Saraiva said:

    This might sound tiring, but bear with us for a moment:

    ...

    Be persistent and don't hesitate to shout back!

    And, you get a code review for free, below the radar of your boss ... ;-)

  • Thank you, this is my case. I have a set of defined protocol for communication and a hard real time system controlled by timer.

    Hope you have observed that in previous case "Current_Char" was static. 

    Please find the working code below:

    //*****************************************************************************
    //
    // The UART1 interrupt handler.
    //
    //*****************************************************************************
    void
    UART1_IntHandler(void)
    {
    Interrupt_Flag = (Interrupt_Flag | uart1_interrupt); // Global variable
    static uint32_t ui32Status; // local variable >> interrupt status
    if ((Current_Char == 34)||(Current_Char == 4))
    {
    Current_Char = 0; // First data location in array
    }
    ui32Status = ROM_UARTIntStatus(UART1_BASE, true); // Get the interrrupt status.
    ROM_UARTIntClear(UART1_BASE, ui32Status); // Clear the asserted interrupts.
    while(ROM_UARTCharsAvail(UART1_BASE)) // Loop while there are characters in the receive FIFO.
    {
    uart1_data_packet[Current_Char++] = ROM_UARTCharGetNonBlocking(UART1_BASE); // Read the next character from the UART1
    }

    ______________________________________________________________________________________________________________________

    if(Interrupt_Flag & uart1_interrupt)
    {
    Interrupt_Flag &= 0xfd; // Clear UART1 interrupt flag
    //------------------------------------------------------------------------------------------
    //
    // collecting Receiver response status after sending the command
    //
    Receiver_Status_Response.Headder1 = uart1_data_packet[0];
    Receiver_Status_Response.Headder2 = uart1_data_packet[1];
    Receiver_Status_Response.Code = uart1_data_packet[2];
    Receiver_Status_Response.Analog_gain_LB = uart1_data_packet[3];
    Receiver_Status_Response.Analog_gain_HB = uart1_data_packet[4];
    Receiver_Status_Response.Time_LB = uart1_data_packet[5];
    Receiver_Status_Response.Time_HB = uart1_data_packet[6];
    Receiver_Status_Response.State = uart1_data_packet[7];
    Receiver_Status_Response.Angle_X_LB = uart1_data_packet[8];
    Receiver_Status_Response.Angle_X_HB = uart1_data_packet[9];
    Receiver_Status_Response.Angle_Y_LB = uart1_data_packet[10];
    Receiver_Status_Response.Angle_Y_HB = uart1_data_packet[11];
    Receiver_Status_Response.Quad_A_LB = uart1_data_packet[12];
    Receiver_Status_Response.Quad_A_MidB = uart1_data_packet[13];
    Receiver_Status_Response.Reserved1 = uart1_data_packet[14];
    Receiver_Status_Response.Reserved2 = uart1_data_packet[15];
    Receiver_Status_Response.Quad_B_LB = uart1_data_packet[16];
    Receiver_Status_Response.Quad_B_MidB = uart1_data_packet[17];
    Receiver_Status_Response.Reserved3 = uart1_data_packet[18];
    Receiver_Status_Response.Reserved4 = uart1_data_packet[19];
    Receiver_Status_Response.Quad_C_LB = uart1_data_packet[20];
    Receiver_Status_Response.Quad_C_MidB = uart1_data_packet[21];
    Receiver_Status_Response.Temp_LB = uart1_data_packet[22];
    Receiver_Status_Response.Temp_HB = uart1_data_packet[23];
    Receiver_Status_Response.Quad_D_LB = uart1_data_packet[24];
    Receiver_Status_Response.Quad_D_MidB = uart1_data_packet[25];
    Receiver_Status_Response.HV_LB = uart1_data_packet[26];
    Receiver_Status_Response.HV_HB = uart1_data_packet[27];
    Receiver_Status_Response.Switch_1_2_Positions = uart1_data_packet[28];
    Receiver_Status_Response.Switch_3_4_Positions = uart1_data_packet[29];
    Receiver_Status_Response.Switch_5_Position = uart1_data_packet[30];
    Receiver_Status_Response.Checksum = uart1_data_packet[31];
    Receiver_Status_Response.Footer1 = uart1_data_packet[32];
    Receiver_Status_Response.Footer2 = uart1_data_packet[33];

    }

  • Somehow I expected something like this.

    KurianThomas said:
    Hope you have observed that in previous case "Current_Char" was static. 

    It's less about the index, but about the data (array) itself. What happens when a new packet arrives while you are working on the previous one ? I suspect this will happen often, because of another bug:

    KurianThomas said:
    if ((Current_Char == 34)||( ...

    I would use the following method:

    • use a buffer greater than the largest expected packet (I would use 40 byte, and a size divisible by 4)
    • check for start characters (Header1), reset the index to zero if detected (and store the character as usual)
    • check for the termination character (Footer2), and if found, copy the buffer + set your flag for the main code
    • store all other characters (and increment the index counter)
    • check for buffer overflow (index), and reset to zero - this should automatically discard corrupted packets

    But as said, working on the same data array from both main code and interrupt code will blow up in your face eventually. Use a copy instead.

  • Thanks a lot f.m, this method is much reliable and optimistic
  • "optimistic" is a good tag here.
    You should always assume that character can get lost, and packets corrupted. And design you processing in a robust way, to recover communication without intervention/reset (the so-called "rainy-day scenarios").