Part Number: AM263P4
Other Parts Discussed in Thread: SYSCONFIG,
Currently using SDK 10.2.0.5. UART transfer mode set to interrupt.
Serial cable is connected from our board to laptop using an isolater. The bus is a bit noise and evident in seeing non ascii characters being echoed back and not all characters received at the MCU. This can potentially cause bus errors.
When running in a live system after several hours, the UART RX on the MCU stops working but the TX is still working. A thread is able to TX characters to the laptop.
MCU is unable to RX any commands which leaves the product in a very dangerous state since we can't shut it down.
As a first step, I asked AI to help find the issue. I understand AI can hallucinate and gaslight, but it's response seems believable and highlighted some potential issues with the driver.
Can TI help confirm if this is indeed an issue with the driver or not? This would really help focus my search on where this issue could reside.
Claude Opus' analysis:
================================================
Your UART is configured with transferMode = UART_CONFIG_MODE_INTERRUPT (line 698 of ti_drivers_open_close.c). This creates race conditions because:
- TX and RX share hUart->state — the HLD UART_write() unconditionally sets state = UART_STATE_READY (line 555 of uart_v0.c) before every write, even if a read is in progress. This is a TI SDK workaround to allow concurrent TX/RX but it corrupts state machine invariants.
- Semaphore race — the read path uses SemaphoreP_pend() with a 10ms timeout. If a byte arrives between the timeout and UART_readCancelNoCB(), the ISR posts the binary semaphore but the HLD ignores the result. This stale semaphore post causes the next read to return immediately with uninitialized data, and over many occurrences can permanently desynchronize the driver.
- RX line errors (overrun/framing from USB-serial adapters) trigger UART_procLineStatusErr() which disables RX interrupts and flushes the FIFO inside the ISR, then skips the normal read-completion path. The semaphore is never posted, the read times out, but repeated errors can make the CLI appear permanently dead.
Recommended Fix
- Change the UART transfer mode to UART_CONFIG_MODE_POLLED in SysConfig. This is appropriate because:
- You're already doing 1-byte reads with a 10ms timeout (polling semantics)
- Polled mode uses UART_lld_read()/UART_lld_write() which are self-contained, always restore state = READY, and don't involve semaphores or ISRs
- The HLD's state = READY hack on line 555 of uart_v0.c still allows writes to proceed during reads
- Eliminates all ISR-related race conditions
- No code changes needed in bsp_uart.cpp
The change is in SysConfig for the UART0 instance: set Transfer Mode from "Interrupt" to "Polled".
Yes, it's a bug (or at minimum a serious design deficiency) in TI's UART HLD/LLD driver stack. Specifically:
The Bug: Line 555 of uart_v0.c
// Inside UART_write(), before every write:
hUart->state = UART_STATE_READY;
TI unconditionally resets the shared state to READY before every write, even if a read is in progress. This was likely an intentional workaround to allow simultaneous TX and RX on the same UART instance, but it breaks the state machine contract that the LLD relies on.
Why It's a Bug
- The LLD state machine assumes mutual exclusion. UART_lld_readIntr() checks state == UART_STATE_READY as a guard (line 2722), transitions to UART_STATE_BUSY, and expects state to remain BUSY until the ISR completes the transfer. The HLD write path violates this assumption.
- The ISR checks state. In interrupt mode, the ISR uses state to decide whether a read is active. If UART_write() resets it to READY mid-read, the ISR may skip processing received data, leaving the read semaphore un-posted and the read hanging until timeout.
- Stale semaphore posts. When a read times out and you call UART_readCancelNoCB(), if a byte arrives between the timeout and the cancel, the ISR posts the binary semaphore. This stale post causes the next SemaphoreP_pend() to return immediately with no actual data, corrupting the read flow. Over time this desynchronizes the driver permanently.
- Line status errors (overrun/framing) disable RX interrupts in UART_procLineStatusErr() but never re-enable them in the error path — only the normal completion path re-enables them on the next read. If the error coincides with the state corruption above, RX can become permanently disabled.
TI's Stance
This pattern exists across multiple TI SDK versions (MCU+ SDK 10.x). It's not documented as a known issue. TI's examples typically use UART in a simple request-response pattern (write, then read, never concurrent), which masks the bug. Your use case — continuous background polling for RX while asynchronously writing TX — exposes it.
Bottom Line
It's a TI driver bug triggered by concurrent TX and RX in interrupt mode. Your options:
- Switch to polled mode (recommended — matches your polling usage pattern, sidesteps all the bugs)
- File a bug with TI via E2E forums referencing the state = READY reset in UART_write() and the lack of separate TX/RX state tracking