9
\$\begingroup\$

I would like to know to know why UART errors occur, and when one should check for such errors. There is a post on here that asks about handling individual errors, such as overrun, parity, etc... I am clear on why data overrun happens, why parity error happens, but I would like to know what is the root cause. My question is more focused on why these errors could occur (physical reasons), and when one should do make error checking a factor for their application.

So far my program seems to work great (with no error checking), but I know that noise can mess things up. How could I simulate conditions that could cause the UART Rx/Tx ports to fail?

\$\endgroup\$
0

5 Answers 5

8
\$\begingroup\$

There are several potential sources for noise in any circuit. Some of the most common include:

  • Poorly regulated power supplies;
  • Switching power supplies;
  • Insufficient capacitive decoupling of the power rails near the MCU;
  • Inductive coupling of nearby electromagnetic sources (including 50 or 60Hz from the mains power; even if the circuit is battery powered, it will experience this interference when close enough to a mains source);
  • RF sources near the resonant frequency of a trace on the circuit board, or one of its harmonics;
  • Routing of high-current traces on the circuit board near signal lines;
  • Etc.

In addition (as @jippie mentioned), clock skew is a very common cause of errors in any type of serial communication that uses a predetermined data rate. If you're using an external crystal and interfacing to another system that can reasonably be expected to be accurate, it's less likely to cause problems. Internal oscillators, however, can have tolerances that are several orders of magnitude worse than crystals, and tend to vary more over temperature ranges.

There are several basic tests that can be performed on a running system to determine the basic noise (and skew) immunity of your interface, including:

  • Freezing (cool the circuit to the minimum rating of its components);
  • Baking (heat to the maximum rating);
  • Exposure to EMI:
    • Set the board on top of the power cord of a running space heater;
    • Key a CB radio in the near vicinity of the board;
    • Put the board next to your wireless router;
    • Use long hookup wire (instead of a properly constructed serial cable) for the UART connection.

There are many others--in fact, there are large testing labs dedicated to EMC qualification.

In general, unless some minimal level of data loss is acceptable, it is always prudent to include some sort of error checking in your communications code. Even a simple checksum is better than nothing.

\$\endgroup\$
7
\$\begingroup\$

One common source of errors on UART besides signal level quality (noise, rise/fall times) is clock skew. If the transmitter clock and receiver clock are not derived from the same source (which is the case most of the time), then one will run faster than the other. When the timing error is too large, you may occasionally read a wrong bit.

\$\endgroup\$
5
  • \$\begingroup\$ What would cause the clock to skew, if the microcontroller was left alone in a blackbox, out in the middle of who knows where? \$\endgroup\$
    – user791953
    Sep 25, 2013 at 13:45
  • 1
    \$\begingroup\$ Free running local clocks. Every oscillator has its own accuracy. The MCU clock can be divided down to a usable frequency for UART, but sometimes it is off by a small percentage. This is in turn caused by the fact that the divisor is an integer number. \$\endgroup\$
    – jippie
    Sep 25, 2013 at 13:47
  • \$\begingroup\$ Eg. MCU clock = 16MHz, UART baudrate = 9600Bd. Then the UART is commonly clocked with 153600Hz. But 16000000/153600 is not an integer number, so the baudrate will be off. \$\endgroup\$
    – jippie
    Sep 25, 2013 at 13:49
  • \$\begingroup\$ Right, that'll give a small error percentage. Guess I have been fortunate enough not to have encountered any errors, but if it is critical data, checks should be done always. \$\endgroup\$
    – user791953
    Sep 25, 2013 at 13:50
  • \$\begingroup\$ Lower baudrate, higher clockrate (increases sampling resolution and timing accuracy). \$\endgroup\$
    – jippie
    Sep 25, 2013 at 13:51
1
\$\begingroup\$

Framing errors can be caused by what @jippie mentions - the receiver has detected the start bit and where it expects the stop bit the data is inverted. This can also be due to data corruption caused by line interference impinging on the stop bit. You always need to check this for each byte received.

Parity errors occur when parity is implemented on the data link and there is a corruption that causes a parity mismatch in the received data. You always need to check this for each byte received.

Receive break is also regarded as an error although it's really an indication that the incoming data has fallen to logical zero for longer than 1 byte of data. Normally logical 1 is the "ambient" state between successive data bytes and it remains this way. It's a throw back to old telegraphy systems I think. I wouldn't bother checking this unless you were using this "feature" to indicate (say) a reset command to the receiver.

Overrun error is when a new byte is received before the previous byte was read by a CPU. Slightly different when a FIFO is involved but amounts to the same thing - valid received data is lost due to CPU slowness. Always check this before reading a byte and if the byte is part of a longer message (or command) throw the whole message/command away and somehow request the transmitter to resend the whole message/command.

Under run is not really an error but indicates to the sending UART that it's transmit buffer is empty i.e. it is requesting a new byte to transmit. You don't need to check this.

\$\endgroup\$
3
  • \$\begingroup\$ I understand what these errors are and why they occur, my question is more along the lings of when should one provide error checking for them. \$\endgroup\$
    – user791953
    Sep 25, 2013 at 13:56
  • \$\begingroup\$ @user791953 - done \$\endgroup\$
    – Andy aka
    Sep 25, 2013 at 14:02
  • \$\begingroup\$ BTW, underrun isn't a problem with most protocols, but some protocols use an idle line to indicate end-of-packet. In such cases, an underrun on the transmit side may cause the receiver to incorrectly think the packet ends before it's supposed to. \$\endgroup\$
    – supercat
    Sep 25, 2013 at 17:42
1
\$\begingroup\$

Most errors stem from three causes: (1) the transmitter's generated signal did not represent valid data; (2) the transmitter's signal was not received as generated, or (3) the receiver was not ready to handle the data when it was received. The most common cause I've seen for problem #1 is a transmitter that gets reconfigured or shut down while it is transmitting data. Problem #2 can easily occur for signals traveling through the "outside world" as a result of things like radio interference (mobile phones can be surprisingly nasty!), but should generally not occur for signals confined to a single board. Problem #3 can either occur because too many bytes arrive faster than they can be processed, or because the receiver is reconfigured, shut down, or started up during a transmission.

In many cases, it's difficult to completely eliminate all of these problems; one's goal should be to ensure that the total "damage" done by them (probability of occurrence, times damage per occurrence) is acceptably low. This can most easily be done by choosing a pessimistic estimate of reliability, and then designing a protocol so that the impact on system performance of even the worst failures that were consistent with one's estimates would be within acceptable limits.

\$\endgroup\$
0
\$\begingroup\$

In order to deal with these errors, you must implement a higher level logical protocol. something akin to TCP, or check the OSI stack for ideas.

basically, two important parts to start with are checksums, and timeouts. use an algorithm to compute a redundent value that represents, in a smaller form, the contents of each message. then check this in the received message. if the sums don't match, you have possibly gotten a framing error, bit noise, etc, etc. and you'll need to discard the message and attempt some sort of recovery, resend, NACK ( not acknlowledged )signal, etc.

also, make sure to implement timeouts in your upper level protocol. if you get some kind of framing error, your UART may never recover and begin processing again. it may be waiting for the stop bit on a frame that the sender UART thinks has already been sent, but was corrupted by noise , clock skew, etc. this will send any input code into an infinite loop. make sure that you have a sane limit as to how long your input reading should wait until deciding to abandon this message, and again, retry, NACK, abandon, etc.

\$\endgroup\$
5
  • \$\begingroup\$ Timeouts need to be implemented on at least one side of any higher-level protocol; in many cases, it's best to implement them on exactly one side. Having one side waiting forever for data that never arrives is only a problem if there's something else useful it could have been doing instead. If X asks Y for some data, X will need to be prepared to resend his request in case Y doesn't receive it. Y, however, won't need to worry about whether X gets his response. If X doesn't get it, X will ask for the data again. The fact that X doesn't ask again for the data means Y doesn't need to resend it. \$\endgroup\$
    – supercat
    Sep 25, 2013 at 17:40
  • \$\begingroup\$ @supercat right, this is a good pattern, but i'm aiming more towards the low level line by line coding. you are always going to have a loop that is reading data, and trying to figure out if a complete message is ready, if a complete message is never there, it can hang the input subsystem, regardless if there is nothing else but waiting to be done. in this case, the input subsystem needs to at least realize that a failure occurred, flush any gabage data and get reset for another try. \$\endgroup\$ Sep 25, 2013 at 18:05
  • \$\begingroup\$ If each packet starts with a byte sequence which is always identifiable in any context, and if the receiver has nothing useful it can do until it receives a complete packet, why should it care if a few hours elapse after it's received a partial packet? The next time someone tries to send a real packet, the receiver will see the start-of-packet marker and abandon the partial packet. \$\endgroup\$
    – supercat
    Sep 25, 2013 at 18:21
  • \$\begingroup\$ @supercat because then you have a loop that is looking for multiple things. it's still looking for the end of the partial packet, and it's looking for the beginning of a fresh, uncorrupted packet. this makes the logic much more complex in terms of practical, if then, do while, coding. \$\endgroup\$ Sep 25, 2013 at 19:02
  • \$\begingroup\$ I'm not quite sure what the difficulty is. If one's using a receive-byte loop one will have to break out of it if either a timeout occurs or a start byte is seen. Both behaviors need to be handled identically, save only for the fact that the start sequence should set a flag, so the next code that would look for it won't bother. \$\endgroup\$
    – supercat
    Sep 25, 2013 at 19:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.