Skip to content

SX1262 intermittent busyRx on Raspberry Pi 5 with TXen/RXen (PiMesh 1W / MeshAdv) #9933

Description

@NearlCrews

Description

Intermittent [RadioIf] Can not send yet, busyRx errors on Raspberry Pi 5 with an SX1262-based LoRa HAT using TXen/RXen RF switching (PiMesh 1W V1 / MeshAdv Pi Hat with Ebyte E22-900M30S). The radio initializes successfully but intermittently gets stuck in RX state due to false preamble detection, preventing transmission.

Hardware

  • Board: Raspberry Pi 5 Model B Rev 1.1
  • OS: DietPi (Debian Trixie 13, kernel 6.12.75+rpt-rpi-2712)
  • LoRa HAT: PiMesh 1W V1 (Ebyte E22-900M30S / SX1262, 1W with external PA)
  • GPS: ATGM336H (UART on /dev/ttyAMA0)
  • meshtasticd: 2.7.20 (016e68e, native-tft)
  • Connection: SPI (spidev0.0), GPIO via RP1 (gpiochip4)

LoRa Config (config.d/lora-pimesh-1w-v1.yaml)

Lora:
  Module: sx1262
  CS: 21
  IRQ: 16
  Busy: 20
  Reset: 18
  TXen: 13
  RXen: 12
  DIO3_TCXO_VOLTAGE: true
  SX126X_MAX_POWER: 22
  spidev: spidev0.0
  gpiochip: 4

config.txt (relevant lines)

dtparam=spi=on
enable_uart=1
dtoverlay=disable-bt

Note: dtoverlay=spi0-0cs must NOT be used on Pi 5 — it conflicts with the RP1 SPI controller and causes SX126x init result -2 (chip not found) followed by a crash.

Symptoms

  1. Radio initializes successfully (SX126x init result 0)
  2. Some packets transmit fine (e.g., NodeInfo at 30s after startup)
  3. Other packets intermittently fail with busyRx (e.g., HostMetrics at 60s, GPS position at ~28s)
  4. Debug log shows Ignore false preamble detection immediately after the busyRx warnings
  5. Once stuck, the radio never recovers to transmit that packet — the queue fills and discards

Debug Log (verbose mode)

INFO  | Set radio: region=US, name=LongFast, config=0, ch=19, power=30
INFO  | Final Tx power: 22 dBm
INFO  | SX126x init result 0
INFO  | Frequency set to 906.875000
INFO  | Bandwidth set to 250.000000
INFO  | Power output set to 22
INFO  | Set RX gain to boosted mode; result: 0
INFO  | Applied SX1262 register 0x8B5 patch for RX improvement
INFO  | sx1262 init success
...
INFO  | [GPS] Send pos@...:6 to mesh (wantReplies=0)
DEBUG | [GPS] enqueue for send (id=... encrypted len=68 ...)
WARN  | [RadioIf] Can not send yet, busyRx
WARN  | [RadioIf] Can not send yet, busyRx
WARN  | [RadioIf] Can not send yet, busyRx
DEBUG | [RadioIf] Ignore false preamble detection

After longer runs without recovery:

INFO  | [RadioIf] tophone queue status queue is full, discard oldest

Findings

Pi 5 GPIO chip matters

  • gpiochip: 0 (default) → radio initializes but BUSY pin reads incorrectly, busyRx on every TX attempt
  • gpiochip: 4 → radio works, busyRx is intermittent rather than constant
  • On Pi 5 DietPi/Trixie, /dev/gpiochip4 symlinks to /dev/gpiochip0, but the RP1 GPIO driver behaves differently depending on which chip number is requested

SX126X_MAX_POWER: 22 reduces frequency

  • Without SX126X_MAX_POWER: 22: busyRx on nearly every TX attempt
  • With SX126X_MAX_POWER: 22: busyRx is intermittent (~1 in 3 TX attempts)

spi0-0cs overlay breaks SX1262 init on Pi 5

  • With dtoverlay=spi0-0cs: SX126x init result -2 → crash (free(): invalid pointer)
  • Without it: init succeeds. Default Pi 5 SPI config works fine since meshtasticd manages CS via GPIO21

Likely Root Cause

The RP1 GPIO controller on Pi 5 has different interrupt/edge detection behavior than the BCM GPIO on Pi 4 and earlier. The SX1262's IRQ pin (GPIO16) edge detection or the BUSY pin (GPIO20) level reading appears to be unreliable through the RP1, causing false preamble detections that prevent the radio from transitioning out of RX mode.

This may be related to:

  • How libgpiod handles edge events on the RP1
  • Timing of BUSY pin polling after an IRQ event
  • The RP1's GPIO interrupt coalescing or debouncing behavior

Related Issues

Steps to Reproduce

  1. Raspberry Pi 5 with any SX1262 HAT using TXen/RXen (PiMesh 1W V1, MeshAdv, etc.)
  2. Install meshtasticd 2.7.20
  3. Configure with gpiochip: 4, SX126X_MAX_POWER: 22
  4. Set region, wait for GPS fix or HostMetrics timer (60s)
  5. Observe intermittent busyRx in logs: journalctl -u meshtasticd -f

Metadata

Metadata

Assignees

No one assigned

    Labels

    StaleIssues that will be closed if not triaged.first-contributionneeds-logsDevice logs requested for triage

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions