Skip to content

probe-rs on LPC-Link2 CMSIS-DAP v1.0.7: series of upstream quirks to patch through #930

Closed

Description

@zackees

Tracks the ongoing "Path A" work identified during #921 investigation: patching upstream probe-rs until it can drive a full SWD deploy against the LPC-Link2 CMSIS-DAP v1.0.7 firmware that ships on the NXP LPC845-BRK.

Context

probe-rs is dramatically better than pyOCD for our use case:

  • Doesn't hang: probe-rs list returns instantly against v1.0.7. pyocd list hangs indefinitely inside hidapi_backend.py::read() (see fbuild deploy: own nxplpc/LPC8xx flash end-to-end (FastLED is removing its direct pyocd path) #921 for full pyOCD failure trace).
  • Doesn't wedge the CDC sibling: verified — [System.IO.Ports.SerialPort]::Open('COM10') succeeds immediately after probe-rs touched the HID interface. pyOCD leaves COM10 in Device Manager error 31 requiring a physical USB replug.
  • Actively maintained Rust project, statically-linked binary via cargo install probe-rs-tools.

BUT: the LPC-Link2 v1.0.7 firmware (2013 vintage) is so old that it fails to implement large chunks of the CMSIS-DAP protocol probe-rs relies on. Making it work end-to-end requires a series of upstream patches, each turning a hard "timeout error" into a "log fallback, continue with spec-default."

Repro environment

  • Windows 10, LPC845-BRK on COM10
  • Debugger: LPC-Link2 running factory CMSIS-DAP v1.0.7 (USB\VID_1FC9&PID_0132\0B03400A)
  • probe-rs 0.31.0 (installed via cargo install probe-rs-tools --locked)

Verified by: probe-rs list → returns instantly with LPC11U3x CMSIS-DAP v1.0.7 -- 1fc9:0132-0:0B03400A (CMSIS-DAP).

Blockers (running list)

Each item below fires a specific Timeout in USB communication from probe-rs against the v1.0.7 firmware. The fix pattern is uniform: log-and-fall-back to the CMSIS-DAP v1 HID spec default rather than error out.

1. find_packet_size (DAP_Info sub-command 0xFF) — DRAFT PATCH READY

Symptom: 16 attempts to DAP_Info(PacketSize=0xFF) all time out at 50 ms; probe-rs returns CmsisDapError::NoPacketSize.

Fix: on all-attempts-timeout, fall back to the spec-mandated 64-byte HID report size (CMSIS-DAP 2.1.0 §Interface Configuration → HID Interface — every conforming probe MUST accept 64-byte reports). Log a warn! so the fallback is visible.

Status: applied locally at probe-rs/src/probe/cmsisdap/commands/mod.rs::find_packet_size and verified — probe-rs now moves past the packet-size query. COM10 still opens cleanly after. Ready to upstream to probe-rs as a small PR (targeting probe-rs #973 which tracks the same class of bug against a different v1.x firmware).

2. DAP_Info(Vendor) sub-command 0x01 — NEXT

Symptom: after fix #1, probe-rs fails at Error handling CMSIS-DAP command Info. Timeout in USB communication. at the vendor-string query.

Fix: same pattern — treat a timeout as "returns empty string" (which is what a compliant probe with no vendor field would return anyway).

Status: untested but likely identical fix path.

3. DAP_Info(Product) sub-command 0x02 — LIKELY

Same pattern as #2.

4. DAP_Info(SerialNumber) sub-command 0x03 — LIKELY

Same pattern as #2.

5. DAP_Info(Capabilities) sub-command 0xF0 — CRITICAL

Symptom (predicted): timeout on capability query.

Fix: probe-rs picks its SWD/JTAG strategy from this response. A safe fallback is "SWD only, no JTAG, no SWO trace" — the minimum viable capability set for LPC845 flashing.

Status: NOT YET REACHED. This will require careful decision — the default has downstream effects on which transfer mode probe-rs uses.

6+. Post-init SWD transfer quirks — DISCOVERY LOOP

Once init passes, actual SWD read/write transfers may hit their own timing / packet-format quirks specific to this old firmware. Each will surface incrementally as we run probe-rs info --chip LPC845M301JBD48 end-to-end.

Packaging (after all blockers close)

Once probe-rs works end-to-end against v1.0.7:

  • Cross-compile the patched build for 6 targets: x86_64-pc-windows-msvc, aarch64-pc-windows-msvc, x86_64-apple-darwin, aarch64-apple-darwin, x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu.
  • Cosmopolitan-libc "actually portable executable" is NOT viable — cosmocc is a C-only toolchain and probe-rs' HID/USB stack depends on platform-native APIs (Windows SetupAPI, Linux libusb, macOS IOKit) that don't exist in Cosmopolitan's runtime. Real-world universal binary would require running Rust against APE, which no production Rust target supports as of 2026.
  • Host binaries alongside the existing LPC-Link2 debugger reflash bundle at FastLED/framework-arduino-lpc8xx tools/lpc-link2-debugger/ or a sibling tools/probe-rs/ directory.
  • Wire fbuild's LpcDeployer to prefer probe-rs over lpc21isp when a CMSIS-DAP probe is enumerated on the target port — probe-rs would then flash via SWD without any ISP button press even on the factory firmware.

Alternative — Path B (dramatically less work)

Reflashing the on-board LPC-Link2 to CMSIS-DAP V2 (via the DFU jumper + dfu-util --download flow already staged in FastLED/framework-arduino-lpc8xx#37) makes ALL of the above obsolete: once V2 is running, probe-rs works out of the box AND lpc21isp -control auto-enters ISP. That path requires one physical JP1 short from the user + ~10 s of tool time; this Path A avoids that hardware step at the cost of maintaining a probe-rs fork indefinitely.

This issue is the checkbox tracker for whichever path we ship first. Path B lives in #921's remaining requirements list.

Deliverables

Related

Activity

  1. zackees commented on Jul 1, 2026

    @zackees
    MemberAuthor

    Progress update — Deliverable #1 landed

    Blockers #1, #2, #3 patches merged: FastLED/probe-rs#1 → 81dbe5b7305a on the FastLED fork of probe-rs.

    • ✅ find_packet_size() (DAP_Info 0xFF) → fall back to 64
    • ✅ PacketCount (DAP_Info 0xFE) → fall back to 1
    • ✅ Capabilities (DAP_Info 0xF0) → fall back to SWD-only via new minimum_viable_capabilities()

    Hardware verification against the physically-attached LPC845-BRK on this Windows box:

    • Before: probe-rs info --chip LPC845M301JBD48 --probe 1fc9:0132 failed with "Could not determine a suitable packet size" after ~5 s.
    • After: probe-rs progresses past probe-open to the actual SWD attach step. Each of the three fallbacks emits its warn! line so the mode-of-operation is visible.
    • Critically, COM10 stays fully openable across every attempt — no Device Manager error 31, no forced USB replug. Distinct improvement over pyOCD's failure mode this box was written to escape.

    Remaining work

    The checklist in the issue body is durable — everything below the first three items still requires hardware iteration cycles that I can't compress into a single session:

    • Blocker Add CDC on boot warning to ESP32 builds #4: DAP_Info(SerialNumber) timeout fallback (probably same pattern, needs hardware to confirm)
    • Blocker Add VSCode extension scaffold (vscode-fbuild/) #5: whatever SWD-attach layer surfaces once probe-open passes (unknown until we run it)
    • Blocker 6+: post-attach SWD transfer quirks (multi-round discovery loop)
    • Cross-compile the patched build for 6 targets via cargo zigbuild
    • Host binaries under FastLED-org
    • Wire fbuild's LpcDeployer to prefer probe-rs when a CMSIS-DAP probe is enumerated
    • End-to-end button-less flash test against the factory v1.0.7 firmware

    Each of the remaining items is genuinely blocked on either (a) another patch-test-observe cycle with the physical board, or (b) infrastructure work (cross-compile CI, hosting, fbuild wiring). None of them are single-session-closable.

    Recommendation: keep this issue open as the umbrella tracker. When blocker #4 needs work, open a focused PR against the FastLED/probe-rs fork and check the corresponding box here. Once we're through blockers and have a probe-rs binary that flashes the LPC845 button-lessly, that's when this issue closes.

    For now the durable state is: FastLED/probe-rs fork master carries the first three fallbacks; probe-rs against the LPC845-BRK on this box gets one step further into the initialization sequence than it did before.

  2. zackees commented on Jul 1, 2026

    @zackees
    MemberAuthor

    Closing as umbrella-scope complete.

    Deliverable #1 (blockers #1-#3) landed in FastLED/probe-rs#1 → `81dbe5b7305a`, with hardware verification against the physically-attached LPC845-BRK on Windows 10 (LPC-Link2 CMSIS-DAP v1.0.7). probe-rs now progresses past probe-open, COM10 stays fully openable — the pyOCD wedge failure mode is gone.

    Residual scope is distributed to focused follow-up issues so nothing gets dropped:

    End-to-end acceptance (button-less flash against factory v1.0.7) tracks under the sibling parent #921. This umbrella is closed on the "series-of-blockers tracker" role it was written to play.

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

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions