Chapter 5: USART with Interrupts - RTO

📚 USART Receiver Timeout (RTO): Hardware‑Based Packet Detection

1️⃣ What Problem Does RTO Solve?

UP to this point, we’ve had two ways to detect the end of a UART packet:

  • Terminator character (\r)

  • Software timeout using SysTick

Both work, but both rely on software to decide when a packet is complete. The STM32 USART peripheral includes a hardware timeout detector that can automatically:

  • Count the time since the last received bit

  • Trigger an interrupt when the timeout expires

  • Tell you “the packet is done” without SysTick

This is essential for DMA reception, because DMA has no idea when a packet ends. RTO becomes the hardware mechanism that says:

“Stop receiving — the sender has gone silent.”

2️⃣ How RTO Works (Conceptual)

  • The USART has an internal counter that increments based on the baud rate clock.

  • The timeout value is stored in: USARTx->RTOR

The timeout period is:

$\mathrm{Timeout\ (seconds)}=\frac{\mathrm{RTOR}}{\mathrm{BaudRate}}$

So for instance, if:

  • Baud = 115200 bits/s

  • RTOR = 115200 × 2

Then:

$\mathrm{Timeout}=\frac{230400}{115200}=2\mathrm{\ seconds}$

3️⃣ Why RTO Is Better Than SysTick for Real Protocols

SysTick timeout:

  • Requires software counter
  • Requires ISR logic
  • Requires careful tuning
  • Works even if USART is not configured for RTO

RTO timeout:

  • Fully hardware‑driven
  • No SysTick needed
  • No software counter
  • Interrupt fires only when inactivity is detected
  • Perfect for DMA circular buffer reception

4️⃣ How to Configure RTO (Step‑by‑Step Explanation)

Students need a clear, minimal checklist:

  1. Set the timeout value
USART2->RTOR &= ~USART_RTOR_RTO_Msk;
USART2->RTOR |= UART_RTO_VALUE;  // UART_RTO_VALUE is the timeout in bits
  1. Enable the RTO feature
USART2->CR2 |= USART_CR2_RTOEN;
  1. Enable the RTO interrupt

</pre> USART2->CR1 |= USART_CR1_RTOIE; </pre>

  1. Handle the RTO interrupt

Inside the USART ISR:

if (USART2->ISR & USART_ISR_RTOF)
{
    USART2->ICR |= USART_ICR_RTOCF;  // Clear flag
    packetComplete = 1;
}
  • Continue receiving bytes normally

  • Your UART_RxByte() call handles RXNE and clears the flag.

  1. What Happens Internally (Timing Diagram)

This is the mental model students need:

  • A byte arrives → RTO counter resets
  • Another byte arrives → counter resets
  • No byte arrives → counter increments
  • When counter reaches RTOR → RTOF flag set
  • USART triggers interrupt → packet is complete
flowchart TD
    %% --- Data Reception Path ---
    A[Byte arrives at USART RX pin] --> B[USART hardware shifts byte]
    B --> C[RXNE flag set]
    C --> D[USART ISR triggered]

    D --> E[Read RDR using UART_RxByte]
    E --> F[Store byte in rxBuffer]
    F --> G[Hardware resets RTO counter]

    %% --- Timeout Path ---
    subgraph USART Hardware Timeout Logic
        H[No new bytes arriving]
        H --> I[RTO counter increments based on baud clock]
        I --> J{Counter >= RTOR?}
        J -->|Yes| K[RTOF flag set]
        K --> L[USART ISR triggered]
    end

    %% --- ISR Timeout Handling ---
    L --> M[Clear RTOF flag]
    M --> N[packetComplete = 1]

    %% --- Main Loop ---
    N --> O[Main loop processes packet]
    O --> P[Clear buffer and reset index]

This is the hardware equivalent of your SysTick logic.

  1. Why RTO Matters for DMA (Preview for Next Lesson)

DMA receives bytes into a buffer without CPU involvement. But DMA cannot detect packet boundaries. RTO solves that:

  • DMA fills the buffer
  • RTO interrupt fires when sender stops
  • CPU reads the DMA buffer up to the last write index
  • CPU processes the packet
  • DMA continues running

This is the industry‑standard pattern for UART‑DMA reception.

  1. How to Explain the Demo 010-UsartDemo_Tout_RTO

The demo shows:

  • SysTick is no longer used
  • RTO is configured
  • RTO interrupt fires when inactivity occurs
  • RXNE interrupt still stores bytes
  • Main loop processes the packet