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.

Data lost during reception due to UART interruption

Part Number: TM4C1294NCPDT

Hello!

I have a problem with data loss during the UART interrupt, since the character string that I send from a serial terminal is not completely saved in the buffer destined for data reception.

The implementation of the ISR is as follows:

void ISR_UART0(void)
{

    ui32Status = UARTIntStatus(UART0_BASE,true);
    UARTIntClear(UART0_BASE, ui32Status);        //limpia las banderas de interrupción?*/
    i_rx=0;
      while(UARTCharsAvail(UART0_BASE))
      {
             buffer_UART[i_rx]=UARTCharGet(UART0_BASE);
             i_rx++;

      }
}


  • How long is the string? If it is greater than the FIFO threshold, it will arrive in multiple fragments (interrupts). 

    Each time your ISR is called, you reset the buffer pointer (i_rx=0) so the next fragment is stored on top of the previous one.

    The usual practice is to use a circular buffer, so that you can pull bytes out overlapped with the ISR putting them in. Alternatively, if you know there are pauses in the stream, you can capture a block then have the consumer (main()) set i_rx=0.

  • Hi, 

      Can you try UARTCharGetNonBlocking()? Does it make a difference?

  • Hello!
    Thanks for answering, I already tried using the function you recommend but it doesn't work.
  • Hello!
    Thanks for your reply. The string string does not exceed 16 characters. I reset the buffer pointer each time because I receive different data on each interrupt.
  • How many bytes do you receive on each call to the ISR?

    If you haven't changed it, UARTIFLS is set for 1/2-FIFO, so the interrupt will trigger after 8 bytes. If your string is 16 bytes long, the other 8 bytes will arrive later, in another call to the ISR. (It's possible one more byte might arrive while the ISR is running, but it's improbable that all 8 will.) You need to build up your Rx string until it is complete.

  • Hello
    I have not configured UARTIFLS, how can I configure it?
    I send 16 characters (the buffer space) but only 8 characters arrive in the buffer "buffer_UART".
    
    
  • You can set the FIFO trigger level (UARTIFLS) using UARTFIFOLevelSet(), but there is no setting which will trigger (only) on 16-bytes-in-the-FIFO.

    I suggest instead:

    1) Remove the line that says " i_rx=0;"

    2) Change the line that says

        i_rx++;

    to

         if (i_rx < sizeof(buffer_UART)-1) i_rx++;
    

    [Edit: Code formatting]

  • Hello again!
    I have already tried the TIVAWARE feature that you recommended, but was unsuccessful.
    My main problem is that the buffer I am using has 26 characters, but only 16 characters arrive, I understand that they exceed the FIFO limit, do you have any suggestions?
  • Do you have any other interrupt routines running in your system? By default if the CPU is in an interrupt routine, it will not service another interrupt until the one currently being serviced is complete. If that interrupt routine takes a long time to complete, and the UART FIFO is full, subsequent characters will be lost.

  • Hello Mayra,

    Bob posts an interesting yet possible error point. I posted last year this same issue and tracked it to FIFO Empty flag being culprit, no matter the FIFO threshold setting. Best to monitor error flags in RX interrupt loop and flush/zero the buffer if any error occurs. The RX handler must test the empty flag especially after/during first 8 bytes. Also needed to add delay time in loop for empty flag toggles into clear state or 8 bytes of data was being lost in the FIFO input to buffer transfer outer loop.

    It is not so easy to get 16 or even 26 bytes burst into SRAM array buffer without error. Tivaware blocking RX function does not test the FIFO empty flag, that might have helped too.

  • Hello!
    Thanks for your reply. No, there are no other interruptions running, only the reception interrupt is active.
    
    
  • I think what is happening is that you get an interrupt when the FIFO is half full, after 8 characters received. You read those 8 characters into your buffer. Then when the next eight characters come in, you get another interrupt. The interrupt routine copies these into the buffer, but since the variable i_rx is initialized to zero at the beginning of the interrupt routine, it copies the second 8 characters on top of the original 8.

    Instead, make i_rx a static global variable. (Just declare it outside of the function.) Before you start the reception, in the main code, set it to zero. Then in the main code you can check to see when i_rx is equal to 16. When that happens, you have received 16 characters and your buffer is full.