Skip to content

fix(core): match nxp-lpc (hyphenated GitHub form) in platform parser#900

Merged
zackees merged 1 commit into
mainfrom
fix/platform-matcher-nxp-lpc-hyphen
Jun 30, 2026
Merged

fix(core): match nxp-lpc (hyphenated GitHub form) in platform parser#900
zackees merged 1 commit into
mainfrom
fix/platform-matcher-nxp-lpc-hyphen

Conversation

@zackees

@zackees zackees commented Jun 30, 2026

Copy link
Copy Markdown
Member

Problem

Platform::from_platform_str only substring-matched nxplpc (the PlatformIO registry name). The FastLED LPC8xx fork lives at github.com/FastLED/platform-nxp-lpc8xx.git — hyphenated. A platformio.ini entry of

platform = https://github.com/FastLED/platform-nxp-lpc8xx.git#12265f765aebd3893465d6d7ad76be66d89ba015

failed substring matching and the daemon aborted with unsupported platform: <URL>.

Reproduced from a bash compile lpc845brk --examples AutoResearch on FastLED master with fbuild 2.3.14:

unsupported platform: https://github.com/FastLED/platform-nxp-lpc8xx.git#12265f765aebd3893465d6d7ad76be66d89ba015
❌ Compilation failed (fbuild) [2.2s]

Fix

Platform::from_platform_str now matches both nxplpc (registry form) and nxp-lpc (GitHub URL form). One-line condition change in crates/fbuild-core/src/lib.rs.

Tests

Added two cases to platform_from_str_git_urls:

  • The exact failing URL above resolves to Platform::NxpLpc.
  • The bare registry name nxplpc also resolves (was previously uncovered).

Why this blocks downstream

The LPC845-BRK AutoResearch bring-up (FastLED#3300 / FastLED#3348) cannot proceed without this. The _NXPLPC_PLATFORM constant in fastled3/ci/boards.py points at the hyphenated URL and there is no clean PlatformIO-side workaround — name@URL is undocumented as a platform value form.

Risk

Minimal. Substring matcher is a one-line || extension; no other platform path can collide with nxp-lpc.

🤖 Generated with Claude Code

The FastLED LPC8xx fork ships from
`github.com/FastLED/platform-nxp-lpc8xx.git`. The PlatformIO registry
name is `nxplpc` (no separator), but the GitHub URL spells the family
as `nxp-lpc` (hyphenated). `Platform::from_platform_str` only
substring-matched `nxplpc`, so a `platform = https://github.com/
FastLED/platform-nxp-lpc8xx.git#<sha>` spec in platformio.ini was
classified as unsupported and aborted the build with `unsupported
platform: <URL>`.

Match both spellings. Add a test for the hyphenated GitHub URL form
and for the bare `nxplpc` registry name (the existing tests covered
neither).

Reported from a `bash compile lpc845brk --examples AutoResearch`
attempt on fastled3 master against fbuild 2.3.14; the AutoResearch
LPC845-BRK bring-up tracked in FastLED#3300 / FastLED#3348 cannot
proceed without this matcher fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@zackees, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2d61ddee-cf9f-4431-a9d8-60b80f8f3082

📥 Commits

Reviewing files that changed from the base of the PR and between be72798 and cb34923.

📒 Files selected for processing (1)
  • crates/fbuild-core/src/lib.rs
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/platform-matcher-nxp-lpc-hyphen

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

zackees added a commit to FastLED/FastLED that referenced this pull request Jun 30, 2026
`src/fl/channels/bus.h` declared `DefaultBus<>` specializations for
STUB/WASM, ESP32 (RMT / FLEX_IO), and Teensy 4.x (FLEX_IO). LPC had
none, so a channels-API consumer that resolved through
`DefaultBus<ClocklessChipset>::value` on an LPC build hit an
unspecialized primary template — silent missing default, not a clean
selection.

Add the LPC routing:

- `DefaultBus<ClocklessChipset>` -> `Bus::BIT_BANG` for the whole
  LPC family. There is no parallel-IO clockless peripheral on LPC8xx
  / LPC11Uxx / LPC15xx; clockless output goes through the shared M0
  cycle-counted C++ driver gated by `FASTLED_M0_USE_C_IMPLEMENTATION`
  in `led_sysdefs_arm_lpc.h`, which is exactly what `Bus::BIT_BANG`
  names. The existing LPC `ClocklessController` template already
  routes through that same engine, so this is a no-op at the
  hardware level — it just plugs the missing trait.

- `DefaultBus<SpiChipsetConfig>` -> `Bus::SPI` for LPC845 / LPC804
  only. Those parts ship the hardware SPI driver in
  `src/platforms/arm/lpc/spi_arm_lpc.h` (UM11029 SPI peripheral block,
  base 0x40058000 / 0x4005C000). LPC11xx / LPC15xx have separate SPI
  register layouts (#2845 Stage 4) and intentionally fall through to
  the unspecialized primary — a link error there is the right signal
  that no SPI driver is wired yet.

This is B4 from the #3450 meta. B1 (fbuild matcher PR
FastLED/fbuild#900), B2 (`framework-arduino-lpc8xx` tarball checksum
mismatch from the 2026-06-28 org transfer), and B3 (editable-install
rust-toolchain pin on Windows) all live in fbuild / upstream and are
tracked separately on the meta. B4 is the only in-fastled3 blocker.

Tests: `bash test --cpp` — 340/340 passed. Compile validation on real
LPC hardware is gated on the fbuild fixes landing (per the meta).

Closes #3450 B4 (one of four acceptance boxes; meta stays open until
B1-B3 + #3300 hardware path also flip).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zackees
zackees merged commit a78044e into main Jun 30, 2026
80 of 93 checks passed
zackees added a commit to FastLED/FastLED that referenced this pull request Jun 30, 2026
Adds `src/platforms/arm/lpc/spi_arm_lpc_dma.h`: a drop-in async peer of
the polled `ARMHardwareSPIOutput` from `spi_arm_lpc.h`. Streams a frame
to SPI0/SPI1 via a DMA0 channel tied to the SPI block's TX request line
so the CPU can sit in WFI during transmission instead of busy-waiting
on `STAT.TXRDY`. Same template surface as the polled driver — users
swap by gating on `FASTLED_LPC_SPI_DMA` without changing `addLeds<>`
call sites.

Wired into `fastled_arm_lpc.h` after the polled include; the new file
self-gates with `#if defined(FL_IS_ARM_LPC_845) && defined(FASTLED_LPC_SPI_DMA)`
so default LPC845 builds keep the polled driver and other LPC variants
(LPC804 / LPC11Uxx / LPC15xx) compile out cleanly.

Engine design follows the LPC845 conventions already established in
`clockless_arm_lpc_pwm_dma.h`:

- `DMA0->CHANNEL[ch].CFG = PERIPHREQEN`  — SPI's TXRDY drives descriptor
  consumption, one byte per request, no `HWTRIGEN` needed.
- Default channel is 4 (UM11029 Table 80 conventional SPI0_TX). With
  the PWM-DMA clockless driver's default `_BASECH=0` consuming channels
  0/1/2, the defaults don't collide.
- TXCTL latched once at `init()` with `LEN_8BIT | RXIGNORE`. The DMA
  stream writes halfwords to TXDAT and inherits the latched control,
  so we don't burn a u32-per-byte by widening to TXDATCTL.
- Byte → u16 widening into a static 2 KB encode buffer (tunable via
  `FASTLED_LPC_SPI_DMA_MAX_BYTES`), then a single `SETVALID` to arm.
  The encode pass is the only CPU work per frame; transmission itself
  is hardware-driven.
- `done()` / `waitDma()` expose the channel `ACTIVE` flag for the async
  contract; `waitFully()` drains DMA + SPI master shift register.

Per-byte and per-bit primitives (`writeByte`, `writeBit`, `writeWord`)
remain polled — arming a one-byte DMA descriptor costs more than the
TXRDY spin, and APA102's per-LED `FLAG_START_BIT` is a single-frame
write anyway.

**Untested on silicon.** Phase 1 ships register-level wiring per
UM11029 §15 (SPI) and §17 (DMA) and is host-compile clean (340/340
unit tests pass), but cannot be bench-validated from this session
because:

  - The LPC compile path on master is broken at the fbuild matcher
    level (meta #3450 B1; PR FastLED/fbuild#900 open).
  - The framework-arduino-lpc8xx tarball checksum mismatch (#3450 B2)
    blocks the platform install after B1 lands.
  - AutoResearch echo bring-up (#3300) is the gate for any real
    on-device RPC validation.

Marking the PR as Draft per the user's "Full draft, marked WIP" call
on the /clud-pr scope question; explicit `TODO(3453)` markers point
at every spot most likely to need silicon-side adjustment (TXCTL
persistence semantics, SYSCON power-up bits, BURSTPOWER default,
INMUX wiring above channel 15, SRAMBASE allocation, chunked-stream
support for frames > buffer capacity).

Implements #3453 Phase 1 source. Phase 2 (clockless PWM-DMA bench
validation + multi-strip) and the meta's other blockers (B1/B2/B3
fbuild work, #3300 hardware echo) stay tracked separately.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
zackees added a commit to FastLED/FastLED that referenced this pull request Jul 1, 2026
…#3468) (#3475)

While validating the #3468 harness on real LPC845-BRK silicon
(VID:PID 1FC9:0132 on COM10), three separate blockers prevented
`bash compile lpc845brk --examples AutoResearch --build-flag
-DFASTLED_LPC_PWM_DMA=1` from producing a firmware image. Each is a
legitimate bug fix and lands here together because they are only
observable end-to-end when the LPC compile path actually gets exercised.

## Fix 1 — `ci/boards.py`: nxplpc@ prefix workaround

fbuild 2.3.15 shipped 2026-06-30 20:09 UTC; my platform-matcher fix
FastLED/fbuild#900 merged 2026-06-30 21:47 UTC (after 2.3.15 was cut).
2.3.15's matcher still only substring-matches `nxplpc` (no separator)
and rejects the hyphenated `nxp-lpc` in the raw GitHub URL. Prepending
`nxplpc@` to the platform URL is valid PlatformIO name-at-source
syntax and makes the substring match, unblocking the build under
2.3.15. Once fbuild 2.3.16 ships with #900 the prefix becomes redundant
but stays syntactically valid.

## Fix 2 — `led_sysdefs_arm_lpc.h`: define `FASTLED_HAS_CMSIS`

`src/platforms/arm/common/m0clockless_c.h:51` guards the local
`__get_PRIMASK` / `__enable_irq` / `__disable_irq` stubs with
`#if !defined(FASTLED_HAS_CMSIS)`, and the comment on that guard says
"LPC builds set FASTLED_HAS_CMSIS in led_sysdefs". But the define was
never actually added — so LPC builds got the local stubs plus the
vendor CMSIS versions from `core_cm0plus.h` and gcc rejected the pair
with

    error: redefinition of 'fl::u32 __get_PRIMASK()'

Adding `#define FASTLED_HAS_CMSIS 1` in `led_sysdefs_arm_lpc.h`
immediately after the vendor `<LPC845.h>` / `<LPC804.h>` include
matches the intent of the m0clockless guard and silences the collision.

## Fix 3 — `platforms/shared/bitbang/bus_traits.h`: LPC845 gate

`ChannelEngineLpcSctDma` registers under `BusTraits<Bus::BIT_BANG>`
(see `src/platforms/arm/lpc/drivers/sct_dma/bus_traits.h` — FastLED
#3459 / PR #3460). The shared `BitBangChannelDriver` also specialises
`BusTraits<Bus::BIT_BANG>` unconditionally. On LPC845 both TUs land in
the same translation unit and gcc rejects the pair with

    error: redefinition of 'struct fl::BusTraits<fl::Bus::BIT_BANG>'
    error: redefinition of 'struct fl::BusSupports<fl::Bus::BIT_BANG,
                                                    fl::ClocklessChipset, 0>'

Gate the shared bit-bang specialization on `!FL_IS_ARM_LPC_845` so the
dedicated SCT+DMA engine owns the slot on that platform. Every other
platform continues to use the universal-GPIO fallback.

## Verification

Applied all three fixes and confirmed:

  bash compile lpc845brk --examples AutoResearch \
      --build-flag "-DFASTLED_LPC_PWM_DMA=1"

  Board: NXP LPC845-BRK / LPC845 @ 24MHz
  Toolchain: arm-none-eabi-gcc 15.2.1
  Flash: 53.52KB / 64.00KB (83.6%)
  RAM:   9.07KB / 16.00KB (56.7%)
  Artifact: firmware.elf (159.79KB) / firmware.bin (53.54KB)
  build succeeded in 212.2s

  bash test --cpp → 343/343 passed
  C++ lint → clean

## What's still open on the actual on-wire verification

- fbuild-side: an additional blocker surfaced during this bring-up —
  the FastLED/framework-arduino-lpc8xx tarball SHA256 changed after
  the 2026-06-28 org transfer (`e6bbcc3392…` → `e64f0cb81a…`). This
  needs a fbuild-side update to `ACLPC_CHECKSUM` in
  `crates/fbuild-packages/src/library/arduino_core_lpc8xx.rs`; I filed
  the change on a local fbuild branch during this session and will
  push it as a follow-up PR to the fbuild repo.
- Flash + serial monitoring: `bash autoresearch --pwm-dma-cl` still
  hits pre-existing infrastructure gaps unrelated to #3468 —
  `ci/util/port_utils.py` only recognises the LPCXpresso VCOM
  fingerprint (VID:PID 16C0:0483), not the LPC-Link2 CMSIS-DAP
  variant (1FC9:0132) that ships on this specific LPC845-BRK unit,
  and fbuild's LPC deploy path uses `lpc21isp` which requires ISP-mode
  entry rather than the board's default CMSIS-DAP SWD. Both are
  tracked separately.

The host TX→RX byte-flow readback contract (the #3468 primary
acceptance criterion) is already confirmed in PR #3472
(`tests/fl/channels/lpc_sct_dma_engine.cpp` "#3468: end-to-end TX→RX
readback through engine.show()", passing 343/343). This PR takes the
verification one step further by making the compile path work on the
LPC845 target so any user with an LPC845-BRK can now build and flash
the firmware and run the on-silicon self-loopback via
`pwmDmaClCaptureSelf`.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fastled-project-sync fastled-project-sync Bot moved this to Triage in FastLED Tracker Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Triage

Development

Successfully merging this pull request may close these issues.

1 participant