Skip to content

Stage 2: implement NXP LPC8xx build orchestrator (replace stub, unstub LPC804/LPC845 CI) #477

Description

@zackees

Why this is filed

PR #476 stubbed the `Build LPC804` / `Build LPC845` CI workflows
into no-op passes so they stop being perma-red on `main`. That was a
workaround — not a fix. The real fix is to replace the
`NxpLpcStubOrchestrator` with an actual orchestrator that compiles
the existing test fixtures into firmware, and then restore the CI
workflows to call `template_build.yml` for real.

Filing this issue so the work isn't lost.

Stage 1 (already shipped — verified by inspection)

Stage 1 wiring is complete; the only missing piece is the orchestrator
body. Everything below is already in the repo:

  • `Platform::NxpLpc` enum entry + string parsing
    (`crates/fbuild-core/src/lib.rs`).
  • Board JSON definitions:
    • `crates/fbuild-config/assets/boards/json/lpc845.json` — 64 KB Flash, 16 KB RAM, Cortex-M0+ @ 30 MHz, CMSIS framework, upload protocols (lpc21isp, cmsis-dap, jlink, pyocd).
    • `crates/fbuild-config/assets/boards/json/lpc804.json` — 32 KB Flash, 4 KB RAM, Cortex-M0+ @ 15 MHz, CMSIS.
  • Linker scripts:
    • `crates/fbuild-build/src/nxplpc/assets/lpc845.ld` — Flash 64K + SRAM 16K at 0x10000000.
    • `crates/fbuild-build/src/nxplpc/assets/lpc804.ld` — Flash 32K + SRAM 4K.
  • Startup assembly:
    • `crates/fbuild-build/src/nxplpc/assets/startup_lpc845.S` — Reset_Handler, vector table, SystemInit (FRO @ 30 MHz, flash wait states).
    • `crates/fbuild-build/src/nxplpc/assets/startup_lpc804.S` — same pattern @ 15 MHz, zero wait states.
  • Shared MCU config:
    `crates/fbuild-build/src/nxplpc/configs/nxplpc.json` — Cortex-M0+ flags (`-mcpu=cortex-m0plus -mthumb -mfloat-abi=soft`), linker flags, profile flags (release: `-Os -flto`, quick: `-Os`).
  • Toolchain pre-install hook:
    `crates/fbuild-build/src/nxplpc/mod.rs:46-54` — `install_deps()` already calls `fbuild_packages::toolchain::ArmToolchain::ensure_installed()` so the Stage-2 orchestrator can rely on the toolchain being present.
  • Dispatch wiring:
    `crates/fbuild-build/src/lib.rs::get_platform_support(Platform::NxpLpc)`
    returns `NxpLpcPlatformSupport` → `create_orchestrator()` returns
    `NxpLpcStubOrchestrator`. This is the only line that needs to
    change
    at the dispatch level once Stage 2's orchestrator type
    exists.
  • Test fixtures:
    • `tests/platform/lpc845/{lpc845.ino, platformio.ini, README.md}`
    • `tests/platform/lpc804/{lpc804.ino, platformio.ini, README.md}`
      Both `.ino` files are 3-line stubs (empty `setup()` / `loop()`)
      ready to be compiled.

The single missing piece — Stage 2 orchestrator

`crates/fbuild-build/src/nxplpc/mod.rs:71-79` currently returns
`Err(..."Stage 2 ... has not landed yet"...)` unconditionally. Replace
that with a real `build()` that:

  1. Parses `platformio.ini`, loads board config (Stage 1 already
    exposes both via `fbuild_config`).
  2. Sets up build dirs via `fbuild_paths::BuildLayout` (same as every
    other orchestrator, see refactor(paths) + fix(symbols): BuildLayout single-source + PT_LOAD bloat filter #455).
  3. Ensures the ARM GCC toolchain (`ArmToolchain::ensure_installed`
    — already called in `install_deps`, reuse).
  4. Emits the per-MCU linker script + startup `.S` from the embedded
    `include_str!` assets to the build dir.
  5. Compiles `src/*.{ino,cpp,c,S}` with the flags from
    `nxplpc.json` + the board's per-MCU defines, using
    `arm-none-eabi-gcc/g++`.
  6. Links with the MCU-specific `.ld` from step 4, producing
    `firmware.elf`.
  7. Converts ELF → `firmware.bin` via `arm-none-eabi-objcopy`.
  8. Reports size via `arm-none-eabi-size`.

Reference implementation (template to copy)

`crates/fbuild-build/src/teensy/` is the closest comparator — same
Cortex-M family, similar scope (~1690 LOC total across
`mod.rs` + `orchestrator.rs` + `teensy_compiler.rs` +
`teensy_linker.rs`). The LPC8xx orchestrator should be simpler
because LPC has no equivalent to Teensy Cores (no framework-library
machinery — just CMSIS as a system include path + startup .S +
linker script).

Recommended file layout (mirror Teensy):

  • `crates/fbuild-build/src/nxplpc/orchestrator.rs` — the `build()`
    body that replaces the stub.
  • `crates/fbuild-build/src/nxplpc/compiler.rs` — `arm-none-eabi-gcc`
    wrapper, applies `nxplpc.json` flags + board defines.
  • `crates/fbuild-build/src/nxplpc/linker.rs` — link driver, `ar`,
    `objcopy`, `size` invocation.

`mod.rs` shrinks to module declarations + the
`NxpLpcPlatformSupport` impl returning the new orchestrator.

Acceptance criteria

  • `fbuild build tests/platform/lpc845 -e lpc845 --quick` produces
    `tests/platform/lpc845/.fbuild/build/quick/firmware.bin`
    with exit 0.
  • Same for `tests/platform/lpc804 -e lpc804`.
  • `fbuild build ... --release` also produces `.bin` (size
    should be smaller due to `-Os -flto`).
  • Revert `.github/workflows/build-lpc845.yml` and
    `build-lpc804.yml` to the original
    `uses: ./.github/workflows/template_build.yml` caller form
    (template at `.github/workflows/build-lpc845.yml@HEAD`
    pre-ci(lpc8xx): stub Build LPC804 / LPC845 workflows so they pass #476 — restore via `git show ac6b72d^:...build-lpc845.yml`).
    The stub history is preserved in PR ci(lpc8xx): stub Build LPC804 / LPC845 workflows so they pass #476 for reference.
  • No regression on the other 83 board workflows.
  • Add unit test coverage for the new orchestrator mirroring
    `crates/fbuild-build/src/teensy/` patterns (linker invocation,
    hex/bin emit, size parse).

Out of scope

  • Deploy support for LPC8xx (lpc21isp / pyocd / cmsis-dap / jlink) —
    separate follow-up. This issue is about `build`, not `deploy`.
  • Adding more LPC8xx variants beyond lpc804 / lpc845. The
    architectural pattern should extend cleanly, but each new MCU still
    needs its own board JSON + linker script + startup .S (Stage-1
    equivalent work).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions