apache / apache/nuttx

[HELP] ESP32-S3 UART repeats stale data after long uptime

Open
#17,179 9 comments 0 reactions 0 assignees View on GitHub
Community: Question
Dominant language
C
Stars
4k
Forks
1.7k
Avg merge
1d 17h
Merged PRs (30d)
237

Description

### Description

Summary
I’m running a long-lived application on an ESP32-S3 using the current NuttX master. After an unpredictable amount of time—sometimes minutes, sometimes hours—the UART stops behaving correctly: incoming traffic seems to replay older bytes (e.g., the tail of a previous AT response) instead of delivering the newest characters. The external device is still transmitting, so it looks as if the driver is serving a stale buffer.

Environment

SoC: ESP32-S3 (esp32s3-devkit)
UART: 115200 bps, 8N1.
Workload: internal modem/PPP service that keeps the link busy (logs + AT commands)
Observed Behavior

System boots and UART traffic flows normally.
After a random interval, reads begin returning bytes that were already consumed earlier (“ghost” data).
From that moment on, the stream never delivers new characters, effectively stalling the higher-level protocol.
Only a full system reset recovers the port.
Hypothesis: the RX FIFO overflows, leaving the hardware/driver in a wedged state with old bytes queued.
Mitigation Attempt
To explore the issue, I tweaked arch/xtensa/src/esp32s3/esp32s3_serial.c:

In the ISR I now watch UART_RXFIFO_OVF_INT_ST_M; when set, I call esp32s3_lowputc_rst_rxfifo(priv) before clearing the status, hoping to drop corrupted data.
Raised the RX “FIFO full” threshold to 8 bytes so bursts don’t trigger an interrupt per byte.
Enabled RX timeout with a threshold of 10, so shorter frames still wake the ISR even if they never fill the FIFO.
These changes seem to postpone the failure but I’m not yet convinced they fully solve it.

Questions for the maintainers

Does resetting the FIFO on overflow and adjusting the thresholds sound like the right approach, or am I just hiding the real root cause?
Are there recommended settings or patches for handling long-term, high-volume UART traffic on the ESP32-S3 under NuttX?

Alterations in esp32s3_serial.c : uart_handler()

```
/* ISR additions */

uint32_t rx_ovf_mask = UART_RXFIFO_OVF_INT_ST_M;
...
if ((int_status & rx_mask) != 0)
{
uart_recvchars(dev);
modifyreg32(UART_INT_CLR_REG(priv->id), rx_mask, rx_mask);
}

if ((int_status & rx_ovf_mask) != 0)
{
esp32s3_lowputc_rst_rxfifo(priv);
modifyreg32(UART_INT_CLR_REG(priv->id), rx_ovf_mask, rx_ovf_mask);
}
```

Alterations in esp32s3_serial.c : esp32s3_setup()
```
static int esp32s3_setup(struct uart_dev_s *dev)
{
struct esp32s3_uart_s *priv = dev->priv;
const uint32_t ticks_tout = 10U;
const uint32_t rx_fifo_thrhd = 8U;
...
modifyreg32(UART_CONF1_REG(priv->id), UART_RXFIFO_FULL_THRHD_M,
rx_fifo_thrhd << UART_RXFIFO_FULL_THRHD_S);

modifyreg32(UART_CONF1_REG(priv->id),
UART_RX_TOUT_THRHD_M | UART_RX_TOUT_EN_M,
(ticks_tout << UART_RX_TOUT_THRHD_S) |
UART_RX_TOUT_EN_M);
...
}
```

### Verification

- [x] I have verified before submitting the report.

Contributor guide

Open the contributing guide

Research direction

Start with arch/xtensa/src/esp32s3/esp32s3_serial.c, focusing on uart_handler() and esp32s3_setup(), then review the existing RX interrupt and FIFO handling. Reproduce the long-uptime workload on an ESP32-S3 with the reported UART settings and compare overflow, FIFO threshold, and timeout behavior. Done means identifying the cause and validating a fix without stale bytes or a stalled stream.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
embedded-iot, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.