Skip to content

USART1 never receives RC data (CRSF) on custom STM32H743 board despite correct config, confirmed-good signal #28531

Description

@opijimkins1st

Describe the bug

USART1 never receives RC data (CRSF) on custom STM32H743 board despite correct configuration, confirmed-good signal, and working software stack

Summary

On a custom STM32H743 board (PX4 v1.17.0), USART1 (configured for RC input via crsf_rc/rc_input, on pins PA9/PA10) never receives any bytes, despite:

  • A confirmed-clean CRSF signal at the correct 420000 baud present at the RX pin (oscilloscope-verified)
  • The same physical receiver, wiring, and pins work correctly using Betaflight on the exact same hardware (nothing was unplugged or removed)
  • The port opening successfully in PX4/NuttX with the correct baud rate negotiated
  • The exact same generic serial driver code (stm32_serial.c, shared g_uart_ops struct) working correctly on other UARTs on the same board (USART6 for GPS, UART8 for DShot ESC telemetry)

This suggests either a genuine NuttX/PX4 bug specific to USART1 reception on STM32H743, or an undocumented constraint/requirement for using USART1 as an RC input UART that we have not been able to identify despite fairly deep investigation (see below).

Hardware

  • Custom flight controller, STM32H743 (Winegard Kestrel)
  • Receiver: RadioMaster RP4TD ELRS receiver, CRSF protocol, wired to J4 (UART1: PA9=TX, PA10=RX)
  • Confirmed working identically-wired setup using Betaflight (see "Cross-validation" below)

PX4 / Build Configuration

  • PX4 v1.17.0
  • CONFIG_BOARD_SERIAL_RC="/dev/ttyS1"
  • CONFIG_DRIVERS_RC_CRSF_RC=y (also tested with generic rc_input, identical result)
  • CONFIG_STM32H7_USART1=y
  • board.h: GPIO_USART1_RX = GPIO_USART1_RX_2 (PA10), GPIO_USART1_TX = GPIO_USART1_TX_2 (PA9) — matches schematic
  • Tested with CONFIG_USART1_RXDMA/TXDMA both disabled (plain interrupt-driven) and enabled (with DMAMAP_USART1_RX/TX added to board_dma_map.h) — identical result both ways
  • Console is on USART3 (CONFIG_USART3_SERIAL_CONSOLE=y), separate from USART1

Symptom

nsh> crsf_rc start -d /dev/ttyS1
nsh> crsf_rc status
INFO  [crsf_rc] UART device: /dev/ttyS1
INFO  [crsf_rc] UART RX bytes: 0
INFO  [crsf_rc] Telemetry: no
Disposed bytes: 0
Valid known packet CRCs: 0
Valid unknown packet CRCs: 0
Invalid CRCs: 0

UART RX bytes remains 0 indefinitely, with the receiver actively transmitting.

What has been ruled out

  1. Wiring/hardware: Same physical wiring confirmed fully functional under Betaflight - live, correct channel data observed in Betaflight's Receiver tab (throttle/AUX channels responding to stick movement).
  2. Signal presence/correctness: Oscilloscope capture on PA10 shows a clean, active digital signal. Bit timing measured at 2.4us, matching CRSF's 420000 baud spec (1/420000 = 2.381us) almost exactly.
  3. Baud rate configuration: crsf_rc correctly requests 420000 baud; confirmed via log: WARN [SerialImpl] Using non-standard baudrate: 420000 followed by INFO [crsf_rc] Crsf serial opened sucessfully.
  4. Pin mux: GPIO_USART1_RX_2/GPIO_USART1_TX_2 (PA10/PA9) confirmed correct against schematic and STM32H743 datasheet AF table.
  5. Device node existence: /dev/ttyS1 exists (confirmed via ls /dev).
  6. Driver contention: Tested with rc_input fully stopped before starting crsf_rc; also tested rc_input alone. Both drivers show identical zero-byte symptom independently.
  7. RXDMA vs plain interrupt mode: Tested both; no behavioral difference.
  8. VBUS/PA9 conflict: Found and fixed an unrelated real bug where GPIO_OTGFS_VBUS was configured on PA9 (conflicting with USART1_TX comment claimed PA8 but macro used PIN9); fixed, no effect on RX.
  9. RX/TX swap mode: board_rc_swap_rxtx() confirmed returning false (not swapped) for this board.
  10. Console/serial-reordering interaction: Tried CONFIG_STM32H7_SERIAL_DISABLE_REORDERING=y + disabling the UART-based console entirely (matching a pattern seen on a MicoAir H743 board) - this broke GPS (which uses a different, working UART) without changing the USART1 symptom, and was reverted.
  11. ttySx numbering: Traced the actual NuttX registration logic (g_uart_devs[] array order + console exclusion) and confirmed /dev/ttyS1 genuinely corresponds to USART1 on this board's specific enabled-peripheral set.

Suspicious finding (needs re-verification - see caveat)

Using a debug print inserted directly into up_rxint() in stm32_serial.c (confirmed present in the compiled binary via strings on the .elf), we found that up_rxint(enable=true) - the function that sets USART_CR1_RXNEIE and arms the RX interrupt - was never called for USART1, even on the very first open() of the port since boot. The same shared, generic code path (g_uart_ops.rxint = up_rxint) is used by USART6 (GPS, confirmed working) and UART8 (DShot ESC telemetry, confirmed working after enabling the previously-unconfigured peripheral) on the same board.

Caveat: We later discovered that _err() (used in an earlier version of this same debug print) silently compiles to a no-op unless CONFIG_DEBUG_ERROR is set, which cost us significant time chasing a false negative earlier in this investigation. We switched to syslog(LOG_ERR, ...) directly (confirmed to be a real function, not a macro) for this specific up_rxint test, and it printed successfully for at least one earlier check (up_interrupt's RXNE branch) - however, due to a separate, still poorly-understood build-caching issue in this environment (edits to NuttX source files intermittently failing to make it into the final linked binary despite strings initially confirming their presence, requiring various combinations of rm -rf, find -delete on .o/.a files, and discovering a stray .config/.config.old directly inside the NuttX submodule source tree that appears to persist Kconfig state across supposedly-clean rebuilds), we were not able to fully re-verify this specific up_rxint result with full confidence before concluding tonight's investigation. We list it here as a strong lead, not a confirmed root cause.

Comparative research across other STM32H743 boards in the PX4 tree

No board we could find in the PX4 tree (boards/holybro/kakuteh7dualimu, boards/micoair/h743, boards/micoair/h743-v2) uses USART1 for RC input specifically, despite several of them using the identical PA9/PA10 pin pair (GPIO_USART1_RX_2/GPIO_USART1_TX_2) for other roles (typically a generic TEL/AUX telemetry slot). RC input on these reference boards is consistently routed to a different physical UART (e.g., MicoAir h743-v2 uses UART6 for RC, confirmed via manufacturer manual). We were unable to determine whether this is coincidental board-design preference or reflects a known limitation of USART1 for this specific use case.

Build environment note (unrelated to the bug itself, but relevant to reproducing our testing)

We encountered significant, unexplained build-caching issues in our WSL2/Ubuntu development environment throughout this investigation - debug print edits to NuttX source files intermittently failed to appear in the final compiled .elf (verified via strings) despite ccache being disabled and object files being deleted, across multiple different source files. We eventually found a stray .config/.config.old pair directly inside platforms/nuttx/NuttX/nuttx/ (the submodule source directory itself, not the build/ output directory) that we suspect may be involved, though deleting it did not fully resolve a separate, later Kconfig-caching symptom we encountered (select-based Kconfig dependencies aside). We mention this in case it's a known quirk of the PX4/NuttX CMake+Ninja+recursive-Make build system that others have encountered.

Questions for maintainers

  1. Is there a known limitation or additional requirement for using USART1 as an RC input UART on STM32H743 that isn't reflected in board documentation?
  2. Is up_rxint() genuinely expected to be called on every open() of a non-DMA UART, and is there a known scenario where it would be skipped for a specific peripheral instance while working correctly for others using the identical shared driver code?
  3. Any guidance on reliably avoiding the build-caching behavior described above would also be appreciated, independent of the main issue.

Happy to provide full board files, defconfig, and further scope captures if useful.

Flight Log / Additional Information

HW arch: WINEGARD_KESTREL
PX4 git-hash: 28ee3c0
PX4 version: 1.17.0 0 (17891328)
PX4 git-branch: fix-uart8-esc-telemetry
OS: NuttX
OS version: Release 11.0.0 (184549631)
OS git-hash: 3f5532b7dcf98d43544f4270e75e9900064cd83b
Build datetime: Sep 3 2026 13:11:51
Build uri: localhost
Build variant: default
Toolchain: GNU GCC, 13.2.1 20231009
PX4GUID: 000600000000383839343034511000240049
MCU: STM32H7[4|5]xxx, rev. V

The target is a custom 4 motor 7 inch

Here is a scope capture or the UART1 RX pin that is connected to the receiver.

Image

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:needs-triageAuto-assigned to new issues and removed after maintainers review it and assign the specific label.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions