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.

Loosing bytes with UART reception (TM4C123)

very strange behaviour:

About every 10000th byte is lost in a simple 8byte Modbus frame reception.FIFO is enabled, Baud rate is 19200 8E1 (UART2)

1. Setup receive through serial interrupt routine, discovered the missing bytes, about every 1000th byte was missing

2. set break point after timed out reception,observed on Oscilloscope, that it was a regular frame from MODbusmaster

3. changed the reception in polling mode with highest interrupt priority timer 100usec, about every 10000th byte was missing here

4. made debug software to copy timed out frames to buffer, found out that mostly 0x00 and 0x01 bytes were missing in buffer

5. changed baud rate from 19200 to 19400, found that mostly 0xA0 bytes were missing in buffer (Baud rate of Honeywell Modbus Master is accurat)
never had Framing Error, Overrun or Parity Errors in Status Registers

6. changed hardware and software from UART2 to UART4 which is also used for an internal faultless modbus master connection with 115200 Baud
this also did not help.

The system works with 80MHz, uses RTC, and some other serial connections.

I have no idea anymore were to look..

  • About every 10000th byte is lost in a simple 8byte Modbus frame reception.

    RTU or ASCII (albeit that might not make any difference) ?

    I could imagine two scenarios (or, actually three) where you could lose chars:

    • 1. high temporary interrupt load, that results in a receive (FIFO) overflow and lost character(s)
    • 2. receive errors  - do you check all UART error bits ?

    The third scenario is a derivation of the first. If your receive frame size does not match the FIFO size (which practically always the case), an almost complete frame can be stuck in the FIFO, and is "pushed out" by the next frame. In effect, this would look like two frames in very short sequence, with a temporary overload (like 1.). That is one reason why I use to avoid FIFOs or DMA for packet-based serial protocols, and use a single character interrupt instead. A rate of 19200 bps could easily be managed this way.

    I remember similar issues with a Modbus slave implementation on a (i86-based) PLC in one of my former companies. Since it had only hardware-FIFO based UART, the user had to adjust the polling rate of the master (together with the FIFO poll rate), else packet loss was inevitable.

  • thank you, f.m
    it's modbus RTU
    FIFO has 16 bytes, modbus master only sends 8byte packets, so with 100usec polling rate or receive interrupt solution, a fifo overflow cannot happen, a packet takes >4msec.
    I found that I was wrong in above 6. statement, moving exact handling from UART2 to UART4 made the lost bytes disappear!! no more problems.
    I cannot explain it at all.
    Anybody else had issues with UART2?
  • Well, fine if your problem is gone.
    However, (remembering some more RTU details now), I can't understand how RTU and FIFO play together well.
    RTU frames have no explicit termination, but use inter-character idle times. How does that work with a FIFO ?
  • Fifo is transparent, as soon as you read UARTDR, one byte is read out of the receive fifo. Frame Timeout / transmission timing is handled also within the 100usec interrupt, everything works fine.

    BTW. I have now one compiled version which uses UART4 without any lost bytes, but expanding this version with some more other functions brings back the problem..

    I increased stack and heap, but this did not help either. Conclusion: it is not UART2 which causes the problem.

  • Really solved now, the culprit was a reinit command, which set Baudrate / Parity according a dip switch every 1 second. I did always reinit and not just when settings changed...
    feeling a bit humiliated right now by this stupid error, but Lesson learned "do not reinit a serial interface with the exact same parameters" :)
  • Guess the initialization had taken too long, causing the issue.
    Regarding the FIFO, I assumed you work on a "FIFO full" of "FIFO half-full" interrupt. That would hardly coincide with RTU frame lengths and inter-frame timeouts ...
  • From the description, I think the op is polling. The FIFO is just acting as a double buffer.

    Robert
  • From the description, I think the op is polling. The FIFO is just acting as a double buffer.

    Most probably correct. But taking the inter-character timing requirements of Modbus-RTU into account, polling seems to be a rather inefficient method - at least to me.

  • Loosing Bytes: The  function UARTConfigSetExpClk which sets new Baudrates, contains UARTDisable(ui32Base) then after a few instructions UARTEnable(ui32Base) again.

    I did not start in polling mode, but since interframe delay requirements and also reception timeout detection requirements had to be done in the 100usec interval anyway and trying to find out whats happening, I integrated the whole packet handling there. I can now optimize the solution.


    Thanks to you all

  • ... had to be done in the 100usec interval anyway ...

    That interval depends on the baudrate (as the timeouts are specified in "character times", so I would have used a different approach.

    I would have configured the UART with single character interrupt. And at each character reception started (or restarted) a timer with an appropriate (configurable) timeout. Each following character reception again restarts the timer. If it times out (giving you an interrupt), a RTU frame is (supposedly) available for processing.

    BTW, there are other (say, competitor's) Cortex M MCUs available that have this inter-character timer integrated in the UART peripheral ...

  • you are right, we support 9600 and 19200, >= 19200 the timeout definitions and interframe time stay the same. 100usec gives enough resolution to meet Modbus requirements. We have 2 other modbus communications running plus many other tasks, so to we had to share timer resources among these.
    "I would have configured the UART with single character interrupt. And at each character reception started (or restarted) a timer with an appropriate (configurable) timeout. "
    This is our approach as well, timeout is then handled with 100usec resolution.
    Timeout or the reception of 8bytes (in this communication, we only support READHOLDINGREGISTER) assumes reception of a frame.

    than you!

  • There are many ways for polling-based solutions to go wrong when you have hard real-time requirements.   

    A model that works very well on the Cortex-Ms is a high priority interrupt handler (based on a timer) that triggers lower-priority handlers vi pended interrupts or the software-triggered interrupt register (STIR).  This gives you an advancing timebase and allows the NVIC to prioritize the interrupt workload.   I've got a system on my desk based on this approach that remains responsive within spec even under 100% CPU load.