### 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]
- Press RST physically (without BOOT) to boot the freshly flashed firmware.
- 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
- 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.
- 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.
- 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).
Output:
python -m acconeer.exptool.app(Stream tab), or viacustom CLI using
a121.Client.open(serial_port=PORT, override_baudrate=115200, flow_control=False).Expected
SystemInfoResponsereceived within ~1 s, server info displayed.Actual
recv timeouton the initial handshake. Both via the GUI and via direct CLI use.Full traceback (GUI):
Additional diagnostics
I verified the following independently of
acconeer-exptool:(no kernel error, no busy state outside of CoolTerm-like apps holding the port).
0x7Fat 115200 8E1 yields no0x79ACK. So the firmware is actually runningfrom flash; it is not stuck in DFU.
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.)ExplorationProtocolsends(
b'{"cmd":"get_system_info"}\n') yields no response at any of those baudrates, regardless of
parity(None/Even),rtscts=False,dsrdtr=False,with a 3 s read window.
control and baud must be 115200. I used both
flow_control=Falseand115200and the result is unchanged.
Cross-check: the same physical board works perfectly in I²C mode
I subsequently flashed
i2c_distance_detector.binfrom the Acconeer XM125 SDKto the same board (via
STM32CubeProgrammerover UART at115200 / 8E1 / 0x08000000, also worked over CH340 — the flashing path itself is fine). Afterthat flash, the board responds correctly at I²C address
0x52on an ESP32host using SparkFun's Arduino library:
So:
and i2c_distance_detector)
running, specifically on this Mac + CH340 combo.
Hypotheses
XM125may be configured for anUART 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_a121forXM125uses a differentUSART, the firmware runs but its TX/RX go to dead pins.
CH340 leaves floating in a way macOS handles differently from Linux/Windows.
across users on macOS specifically.
Ask
XM125Exploration Server image distributed byacconeer-flash --fetchis intended to work over the SparkFun SEN-24540USB-C path (CH340 → STM32 USART).
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).