Skip to content

SparkFun XM125 (CH340C) — Exploration Server v1.13.0 stays silent on UART after successful flash on macOS #182

@kopierreko

Description

@kopierreko
### Checklist

- [x] I have read the 'Common Issues' without finding a solution
- [x] This issue occurred in the latest release of Exploration Tool (`acconeer-exptool==7.18.1`)
- [x] I have double-checked the 'Installed Packages' format

### Summary

After flashing `acc_exploration_server_a121-v1_13_0` to a SparkFun XM125
Pulsed Coherent Radar Sensor Breakout (SEN-24540) on macOS using
`acconeer-flash --fetch`, the device stays completely silent on its CH340C
UART bridge. Exploration Tool (GUI and CLI) reports `recv timeout` at the
`get_system_info` handshake regardless of baud rate or flow control settings.

This reproduces the unresolved SparkFun community thread:
https://community.sparkfun.com/t/xm125-sen-24540-no-serial-output-with-exploration-server-firmware-on-mac/68293

### Hardware

- **Board**: SparkFun XM125 A121 Radar Breakout, SKU `SEN-24540`
- **MCU**: STM32L431 (Chip ID `0x435`) inside the Acconeer XM125 PB40 v1.1 module
- **USB bridge**: WCH CH340C, VID `0x1A86`, PID `0x7523`
- **Serial device on macOS**: `/dev/cu.usbserial-XXXXX` / `/dev/cu.wchusbserialXXXXX`

### Host environment

- macOS 15.x (Darwin 24.3.0), Intel x86_64
- Python 3.12.13
- `acconeer-exptool==7.18.1`
- `pyserial==3.5`
- `cbor2==5.4.6` (pinned to pure Python to avoid Rust dep)
- CH340 driver: shipped with the macOS kernel (no extra kext)

### Steps to reproduce

1. Fresh venv, `pip install "acconeer-exptool[app]"`.
2. Plug the XM125 over USB-C. Port enumerates as `/dev/cu.usbserial-14430`.
3. `acconeer-flash list` shows the port correctly.
4. Put the board into bootloader (BOOT held + RST tapped + BOOT released).
5. Run:
   ```bash
   acconeer-flash flash XM125 --port /dev/cu.usbserial-14430 --fetch

Output:

Logging in... [OK]
Preparing license agreement... [OK]
Downloading XM125 image file... [OK]
  (version: acconeer_xm125_exploration_server_a121-v1_13_0)
Flashing...
Progress: [100/100]
  1. Press RST physically (without BOOT) to boot the freshly flashed firmware.
  2. Try to connect via python -m acconeer.exptool.app (Stream tab), or via
    custom CLI using a121.Client.open(serial_port=PORT, override_baudrate=115200, flow_control=False).

Expected

SystemInfoResponse received within ~1 s, server info displayed.

Actual

recv timeout on the initial handshake. Both via the GUI and via direct CLI use.

Full traceback (GUI):

acconeer.exptool._core.communication.links.buffered_link.LinkError: recv timeout
... (in exploration_client._retrieve_server_info)

Additional diagnostics

I verified the following independently of acconeer-exptool:

  • The CH340 port opens correctly, and bytes can be written from the host
    (no kernel error, no busy state outside of CoolTerm-like apps holding the port).
  • The STM32L431 is NOT in ROM bootloader anymore after flash + RST: sending
    0x7F at 115200 8E1 yields no 0x79 ACK. So the firmware is actually running
    from flash; it is not stuck in DFU.
  • The firmware does not push any boot banner on the UART. Listening passively
    for 5 s at 115200/921600/460800/230400/57600/9600 yields 0 bytes. (One time
    after RST it produced 3 bytes — "st — but never reproducible.)
  • Sending the exact handshake bytes that ExplorationProtocol sends
    (b'{"cmd":"get_system_info"}\n') yields no response at any of those baud
    rates, regardless of parity (None/Even), rtscts=False, dsrdtr=False,
    with a 3 s read window.
  • Per SparkFun's own docs, the CH340 does not fully support hardware flow
    control and baud must be 115200. I used both flow_control=False and 115200
    and the result is unchanged.

Cross-check: the same physical board works perfectly in I²C mode

I subsequently flashed i2c_distance_detector.bin from the Acconeer XM125 SDK
to the same board (via STM32CubeProgrammer over UART at 115200 / 8E1 / 0x08000000, also worked over CH340 — the flashing path itself is fine). After
that flash, the board responds correctly at I²C address 0x52 on an ESP32
host using SparkFun's Arduino library:

[i2c] scan...
[i2c]   device @ 0x52
[xm125] getDetectorVersion rc=0  v=1.13.0

So:

  • the hardware is OK
  • the CH340 line is OK (used as the flash channel for both Exploration Server
    and i2c_distance_detector)
  • the bootloader is OK
  • only the Exploration Server firmware ends up unresponsive on UART once
    running, specifically on this Mac + CH340 combo.

Hypotheses

  1. The Exploration Server firmware built for XM125 may be configured for an
    UART path different from the one the SparkFun CH340 is wired to. The SparkFun
    schematic shows the CH340 connected to a specific USART of the STM32L431 —
    if the official acc_exploration_server_a121 for XM125 uses a different
    USART, the firmware runs but its TX/RX go to dead pins.
  2. The firmware's UART init might rely on a flow-control line state that the
    CH340 leaves floating in a way macOS handles differently from Linux/Windows.
  3. The SparkFun community thread above strongly suggests this is reproducible
    across users on macOS specifically.

Ask

  • Confirm whether the XM125 Exploration Server image distributed by
    acconeer-flash --fetch is intended to work over the SparkFun SEN-24540
    USB-C path (CH340 → STM32 USART).
  • If yes, any pointers on what might make it silent on macOS.
  • If not, would it be possible to publish (or build) a SparkFun-specific
    variant pinned to the correct USART, or document the workaround.

Happy to capture more diagnostics if useful (logic analyzer trace on
STM32 PA9/PA10 / PB6/PB7 if you can hint which USART the firmware uses).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions