Electronics Design AU
Communications

What Causes UART Framing, Parity, and Overrun Errors?

Last updated 20 July 2026 · 13 min read

Direct Answer

A UART framing error means the receiver sampled a logic-low where the stop bit should be, and the overwhelming cause is a baud rate mismatch between transmitter and receiver, with cable noise or a marginal signal a distant second. A parity error means the received parity bit didn't match what the receiver calculated from the data bits, almost always because the two ends are configured with different parity settings rather than because of a corrupted bit. An overrun error means a new byte finished arriving in the UART's shift register before firmware read the previous byte out of the data register, so the previous byte (or the new one, depending on the peripheral) is silently lost; the usual cause is a receive interrupt that isn't serviced in time, whether from polling too slowly, a higher-priority interrupt blocking it, or interrupts disabled for too long. A break condition is different from all three: it's the line deliberately or accidentally held low for longer than a full character frame, with no valid stop bit ever appearing, and some bootloaders use it as an unambiguous out-of-band signal to force a firmware update mode rather than booting the application.

Detailed Explanation

A UART receiver has no shared clock with the transmitter, so it has to reconstruct frame boundaries purely from timing: it watches for the start bit's falling edge, then samples the line at the bit periods implied by its configured baud rate. Framing, parity, and overrun errors are three separate ways that reconstruction can fail, and each has a status flag most UART peripherals expose to firmware. A break condition is a fourth, distinct case that isn't really an "error" so much as a line state the receiver has to recognise and report differently. This page assumes you're already familiar with the basic UART frame structure; see What Is UART? if you need that groundwork first.

How the receiver actually checks each frame

After the start bit, the receiver's baud-rate generator samples the line at each expected bit position, usually well after the sampling clock has already been running for a while so it can land near the middle of each bit rather than right on an edge. When the frame is expected to end, the receiver checks whether the line is actually high at the stop bit position. If parity is enabled, it also recalculates the parity of the received data bits and compares that against the parity bit it just sampled. Separately, whenever a complete byte has been assembled in the receive shift register, it gets moved into the data register that firmware reads, and a receive-ready flag (commonly named something like RXNE, RDRF, or similar depending on the vendor) is set. Framing, parity, and overrun errors correspond to three different checks failing in this sequence, which is why a UART status register almost always has three separate bits for them rather than one combined "error" flag.

Framing errors: mismatched or drifting baud rate

A framing error fires when the receiver samples the stop bit position and finds a logic-low instead of the expected logic-high. The dominant cause, by a wide margin, is a baud rate mismatch between the two ends. A UART frame is typically 10 bit periods long at 8N1 (one start bit, eight data bits, one stop bit), and any error in the baud rate accumulates across that whole frame. A mismatch of even a few percent is enough for the receiver's sampling point to drift away from the middle of each bit, and by the time it reaches the stop bit position, it may be sampling what is actually the next frame's start bit or early data bits instead, both of which are commonly low. That reads as a framing error, and because it happens on essentially every frame, the visible symptom is a continuous stream of garbled characters rather than an occasional glitch.

Signal integrity problems are a distant second cause. A long or unterminated cable run, a floating RX input with no pull resistor, ground bounce, or EMI coupling near the stop bit's sampling instant can corrupt that single bit even when the configured baud rate genuinely matches on both ends. This tends to show up as sporadic framing errors under otherwise normal operation, rather than the constant stream you get from a real baud mismatch, and it's more common on long RS-232 or RS-485 runs than on a short board-to-board TTL link. See What Is RS-485? for why fail-safe biasing matters on longer multi-drop buses; an undriven or floating differential pair can produce the same kind of spurious framing symptoms.

Parity errors: mismatched parity configuration

Parity checking is a simple single-bit error-detection scheme: with even parity, the total count of 1-bits across the data plus the parity bit must be even; with odd parity, it must be odd. A parity error fires when the receiver's recalculated parity doesn't match the parity bit it actually received. In practice, the most common cause isn't line noise at all, it's that the transmitter and receiver are configured with different parity modes: one side set to even, the other to odd or none. Because roughly half of all possible byte values have an odd number of set bits, a parity mismatch between the two ends typically produces parity errors on a large fraction of received bytes rather than an occasional one, which is a useful signal that you're looking at a configuration problem rather than a noisy link.

Most modern embedded UART links run with no parity (the "N" in 8N1) and rely on a higher-layer checksum or CRC for error detection instead, since a single parity bit only catches an odd number of bit flips and misses even-numbered corruption entirely. If you're seeing parity errors on a link that's supposed to be running with parity enabled, checking that both ends agree on the parity mode is the first thing to verify, well before assuming a noisy cable.

Overrun errors: when RXNE isn't serviced in time

A UART receiver has (at minimum) two separate storage points for incoming data: the shift register, which assembles the incoming bit stream one bit at a time, and the data register, which holds the last complete byte for firmware to read. When the shift register finishes assembling a byte, it's transferred into the data register and the receive-ready flag sets. If firmware hasn't read that data register before the shift register finishes assembling the next byte, there's nowhere for the new byte to go: depending on the specific peripheral, either the new byte is discarded or it overwrites the still-unread previous byte, and either way, an overrun error flag sets and a byte is silently lost. Exactly which byte gets lost, and whether the peripheral keeps accepting data afterward or stalls until the flag is cleared, varies by vendor, so check the specific part's reference manual rather than assuming a universal behaviour.

The most common root cause is firmware simply not servicing the receive-ready flag quickly enough:

  • Polling the flag in a slow main loop, especially once the loop has other work competing for time and the baud rate is high enough that each byte's frame time is short.
  • A receive interrupt that's technically enabled but gets blocked by a higher-priority interrupt that runs longer than one byte time. This is the same class of problem covered on the STM32 NVIC interrupt priority configuration page and in what interrupts are and how they work: if something else holds the CPU for longer than a single UART frame takes to arrive, the next byte will overrun before the receive ISR ever runs.
  • Interrupts disabled globally for an extended critical section, such as a flash erase/write routine, while UART traffic keeps arriving in the background.

This is why overrun errors are notoriously intermittent and load-dependent, and much nastier to chase than a framing error. At light system load, firmware services every byte comfortably within its frame time and no overrun ever occurs; bench testing at a relaxed pace can look completely clean. Add a burst of higher-priority interrupt activity, an occasional long critical section, or a period of heavier bus traffic, and one byte gets missed just often enough to cause an intermittent, hard-to-reproduce field failure. Computing the worst-case time your receive interrupt can be blocked, and comparing it against the byte time at your configured baud rate, is worth doing at design time rather than after the fact.

Break conditions: a deliberate line-level signal

A UART line idles high between frames. A break condition is the line held low continuously for longer than a full character frame, with no stop bit ever appearing during that time. It's architecturally different from a framing error: a framing error is a single corrupted frame that the line typically recovers from immediately afterward, while a break is an extended condition with no valid frame at all. Many UART peripherals expose a separate break-detected flag alongside the frame, parity, and overrun flags for exactly this reason; some initially raise a framing error the moment the stop bit position samples low, then promote it to a distinct break condition if the line stays low past a full frame duration, though the precise behaviour differs between vendors.

An unintended break usually comes from a disconnected or floating line: an RX pin with no pull-up, connected to a transmitter that's been unplugged, powered down, or held in reset, can sit at a low level indefinitely and read as a continuous break rather than idle. This is the same failure mode called out on the RS-485 page regarding fail-safe biasing: an undriven differential bus without bias resistors can float to a state that some receivers interpret as a continuous break, generating spurious garbage rather than clean silence.

Break conditions and bootloader entry

Because a break can't be mistaken for any valid data frame, it's a useful out-of-band signal, something a receiver can recognise as fundamentally different from ordinary traffic without needing a separate physical pin. Some ROM and custom microcontroller bootloaders use exactly this: firmware watches the UART RX line at start-up, and if it sees a break condition of sufficient duration, it interprets that as a request to enter a firmware update or service mode instead of jumping straight into the application. The exact detection scheme, how long the line must be held low, and whether it needs to span the reset itself or just arrive within a timeout window afterward, is implementation-specific, so check the documentation for the particular bootloader you're targeting rather than assuming one fixed rule. Not every vendor ROM bootloader works this way; some, including STM32's, instead rely on a dedicated boot-select pin plus a synchronisation byte sent by the host for baud-rate autodetection, with no break signal involved at all. See What Is a Bootloader in an Embedded System? for how that boot-mode selection generally works.

Break-as-signal isn't limited to microcontroller bootloaders, either. A serial console break is also the standard way to trigger the Linux kernel's Magic SysRq handling or drop into a kernel debugger over a serial connection, which is a good illustration of why break is treated as a control signal rather than corrupted data: an operating system watching a serial port for a break condition needs to distinguish it reliably from any possible byte value, and the extended low-line duration is what makes that possible.

Practical Examples

A field technician reports a device that used to talk to a GPS module fine now streams nothing but garbage after a firmware update changed the MCU's clock configuration. The peripheral clock the UART divider is based on changed, but the UART wasn't reinitialised afterward, so its baud rate divisor is now stale and every byte reads as a framing error. Reinitialising the UART peripheral (or recomputing the divisor) after any clock-tree change fixes it immediately; see the related forum thread on UART garbage output after a PLL clock change for a worked example of tracking this down with a debugger.

A data logger receiving sensor telemetry at 921600 baud works fine on the bench, but drops occasional bytes in the field, corrupting one message in a few thousand. The receive interrupt is enabled and generally fast, but an unrelated timer interrupt at a higher priority occasionally runs for slightly longer than a single UART byte time (roughly 11 microseconds at that baud rate for a 10-bit frame), which is enough to trip an overrun on the rare occasions both events line up. Moving UART reception to DMA, which drains the peripheral independently of any single ISR's priority, removes the dependency on interrupt latency entirely.

Design Considerations

  • Capture the actual bit timing before assuming a cause. A logic analyser or oscilloscope on the TX/RX lines shows the real bit period, which you can compare directly against 1 divided by the configured baud rate. If the measured bit period is consistently off by a fixed percentage from what's configured, that confirms a baud mismatch or a wrong clock-derived divisor rather than noise. See Logic Analyser vs Oscilloscope: Which Should You Use? for guidance on which tool suits which symptom, and the general embedded firmware debugging workflow for combining a debugger with the capture.
  • Verify every configuration parameter matches on both ends, not just the baud rate. Baud rate, data bit count, parity mode, stop bit count, and flow control must all match exactly. It's easy to check baud rate and assume the rest is fine; a parity or stop-bit mismatch produces symptoms that look similar to a baud mismatch at a glance.
  • For overrun errors, check the receive interrupt's actual worst-case latency. Compute the byte time at your configured baud rate (10 bit periods for 8N1) and compare it against the longest period any equal-or-higher-priority interrupt, or any section with interrupts disabled, can run. If the margin is thin, DMA-based reception removes the dependency on a specific ISR's response time altogether.
  • Confirm whether your specific peripheral requires an explicit clear sequence for the overrun flag, and whether it keeps accepting new bytes once the flag is set or stalls until cleared. This detail varies by vendor and is easy to miss until a device stops receiving entirely after the first overrun in the field.
  • Diagnosing an intermittent UART overrun or framing error that only shows up under production load, rather than on the bench, is exactly the kind of interrupt-timing and serial driver work Zeus Design's embedded firmware team handles as part of bringing up communication interfaces on new hardware.

Common Mistakes

  • Assuming garbled characters mean EMI or corruption before checking the configuration. A stream of garbage on every single byte is the signature of a configuration mismatch, almost always baud rate, occasionally parity or stop bits. Reaching for a scope or shielding before confirming both ends agree on all four UART parameters wastes time chasing a problem that isn't there.
  • Ignoring the overrun error flag instead of clearing it. On many peripherals, an unserviced overrun condition leaves the receiver in a state where it stops accepting further data until the flag is explicitly cleared, which looks like a dead link rather than a single dropped byte.
  • Not budgeting for interrupt latency in high-throughput UART designs. Choosing a high baud rate without checking whether any other interrupt or critical section in the system can run longer than a single byte time turns an occasional overrun into a persistent, hard-to-reproduce field bug.
  • Treating a break condition as if it were repeated framing errors. The two look superficially similar (both involve a low line where a high is expected) but a break is an extended, deliberate or accidental line state, not corrupted data, and conflating the two usually sends debugging in the wrong direction.
  • Leaving an unused or disconnectable RX line floating. Without a pull-up, a floating or momentarily disconnected RX input can read as random noise, a continuous break, or both, producing symptoms that look like a protocol bug when the real issue is a missing pull resistor.

Frequently Asked Questions

Why do I get garbled characters instead of a framing error flag?
Whether you see an explicit error or just garbage depends on two things: whether the UART peripheral actually reports framing errors at all, and whether the firmware reading it bothers to check that status bit. A lot of simple polled UART code reads the data register and ignores the error flags entirely, so a baud mismatch just produces a stream of wrong bytes with no visible fault. It's also possible for a fixed baud rate error to occasionally land back within the stop-bit sampling window by chance on some bytes (depending on the specific bit pattern), which is why a mismatch doesn't always trip the framing error flag on every single byte. If your driver silently discards frame and parity errors, that's usually the first thing to fix before debugging anything else.
How do you recover from a UART overrun error once it happens?
Most UART peripherals require an explicit read-and-clear sequence (often reading the status register followed by the data register) to clear the overrun flag, and on some parts the receiver stops accepting further data until it's cleared, which looks like a dead link rather than a dropped byte. Clearing the flag recovers the peripheral, but it doesn't recover the lost byte itself; if your protocol has no framing or checksum to resynchronise on, a single dropped byte can desynchronise every byte that follows. The actual fix is preventing the overrun in the first place: move to DMA-based reception so the hardware drains bytes without firmware intervention, raise the RX interrupt's priority, or shorten whatever section of code is currently blocking it.
What's the difference between a break condition and a framing error?
A framing error is scoped to a single corrupted frame: the receiver expected a stop bit and got a low, but the line typically returns to a normal idle or start-bit pattern afterward. A break condition is the line held low continuously for a full frame duration or longer, with no valid stop bit appearing at all during that time. Many UART peripherals expose the two as separate status flags rather than reporting a break as a repeating framing error, because a break isn't corrupted data, it's the absence of any frame at all. Treating a genuine break as though it were noise-induced framing errors, or vice versa, usually points debugging effort in the wrong direction.

References

Related Questions

Related Forum Discussions