|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Last refreshed: 2026-08-22 (test inventory and execution evidence refresh).
Status: First draft, 2026-05-02. Authored against the Phase 7 schedule in ../QUALIFICATION_ROADMAP.md Section 3. DO-178C reference: Section 11.2. IEC 61508-3 reference: Clause 7.1.2 + Clause 7.4 (software design and development). ISO 26262-6 reference: Clause 5.4 (general tailoring of the software development process). Project: ra8-firmware. Maintainer: Brighton Sikarskie (single developer).
This SDP defines the development environment, the standards the source must meet, and the lifecycle gates the source passes through on its way from a contributor's working copy to the main branch. It is the authoritative companion to the PSAC (./PSAC.md) and the roadmap (../QUALIFICATION_ROADMAP.md).
The authoritative coding standard is the combination of:
The C language baseline is C23 with the GCC/Clang dialect required by arm-none-eabi-gcc. The standard headers (<stdbool.h>, _Static_assert, = {0} zero-initialiser) explicitly forbidden by ../../CLAUDE.md "Critical Rules" are not used.
Architecture is governed by ../RING_AND_WORLD.md (ring 0..6 layering, TrustZone S/NS/NSC world tagging) and by the memory layout in ../MEMORY_MAP.md. Per-feature design intent is captured in the corresponding docs/<feature>.md files (e.g. ../HARDWARE_BRINGUP.md, ../MCDC.md) and in the per-module @brief/@details doxygen corpus.
ra8-firmware does not maintain a separate requirements management system. Requirements are captured in two places:
This is consistent with DO-178C Section 11.9 (software requirements data) being an aggregate of design notes plus the source-of-truth declarations in headers.
Doxygen rules are stated in ../../CLAUDE.md "Doxygen Documentation Requirements" – every applicable tag is mandatory. The current gap list is ../DOXYGEN_GAPS.md. Its archived measurement must be regenerated for the release evidence pack.
Every register-level write must cite the Renesas Hardware User's Manual R01UH1065EJ section that authorises the bit pattern. Citations use the @cite doxygen tag and are audited in strict mode by scripts/checks/cite_check.py.
| Tool | Role | Version basis |
|---|---|---|
| arm-none-eabi-gcc | Cortex-M85 / M33 cross-compiler | ARM GNU Toolchain |
| arm-none-eabi-ld | Linker (per-app linker scripts) | bundled with gcc |
| arm-none-eabi-objcopy | ELF -> HEX for JLinkExe loadfile | bundled with gcc |
| arm-none-eabi-addr2line | Smoke-test PC resolution | bundled with gcc |
| arm-none-eabi-nm | Symbol-table extraction (diag global addrs) | bundled with gcc |
| cmake >= 3.20 | Build system | top-level + per-app |
| just | Build orchestrator (just apps::build <app>) | host |
| clang-format | Style enforcement | matches .clang-format |
| clang-tidy | Naming + complexity gate | matches .clang-tidy |
| clang >= 18 | Host MC/DC instrumentation (-fcoverage-mcdc) | clang-18 profile in pinned devcontainer |
| llvm-profdata/llvm-cov | MC/DC measurement | matches clang |
| cppcheck 2.13.0 | MISRA-C 2012 audit + general static check | pinned devcontainer |
| python3 | Audit scripts under scripts/checks/ | 3.11+ |
| JLinkExe | Flash + halt + register dump | installed rig version recorded with evidence |
| gdb-multiarch | Interactive debug | host |
The cross-compile settings are pinned in ../../cmake/toolchain-ra8d2.cmake. Host (test) builds use the platform-default gcc/clang.
Development is performed on macOS (Apple Silicon) and Linux. A devcontainer is checked in under .devcontainer/ and uses the canonical image preparation/execution helpers under scripts/ci/. Native development remains supported, but qualification commands should use the pinned environment when host tool versions differ.
CI runs in GitHub Actions via ../../.github/workflows/firmware.yml. The pre-commit hook (../../scripts/git/pre-commit) enforces the same gates locally. Hardware-in-the-loop uses the dedicated native listener on the dev box to build, then drives the guarded Raspberry Pi 5 instrument host documented in ../HIL_DEVELOPER_WORKFLOW.md. HIL-relevant pushes and trusted same-repository pull requests schedule .github/workflows/hil.yml automatically; manual dispatch and selected local-app runs remain available.
The reference probe is the on-board J-Link OB-RA4M2 (its serial is bench configuration, set as JLINK_SN in the gitignored .env; see .env.example). Target is EK-RA8D2 v1 (R7KA8D2KFLCAC). VCOM is exposed on /dev/cu.usbmodem<JLINK_SN>1 on macOS and bridges SCI8 per the verified UART bring-up in ../HARDWARE_BRINGUP.md "2026-05-02 follow-up: UART working".
Per ../../CLAUDE.md "Development Approach", every source file in libs/ is hand-written against the Renesas Hardware User's Manual R01UH1065EJ. Renesas FSP source is reference- only and is not copied into this tree. The cite-check script (scripts/checks/cite_check.py) verifies that register-level translation units carry HUM citations.
Third-party libraries are admitted to the build under the SOUP register at ../SOUP/. Each library is wrapped behind a first-party platform abstraction layer (libs/ra8_*_pal/, libs/ra8_tls/, libs/ra8_ota/, port/netxduo/, port/usbx/, port/levelx/, port/nimble/) so that:
NASA Power-of-10 Rule 3 is enforced by ../../scripts/checks/check_no_dynamic_alloc.py in the pre-commit hook. The xorshift32 rand() override added in commit 6d2ebbfac is the canonical example of how third-party calls into newlib heap functions are intercepted (see ../HARDWARE_BRINGUP.md "ra8_rand_stub fix"). Failures of this rule are recorded by ra8_sbrk_trap as fatal_error events on hardware.
Each selected application carries examples/ek_ra8d2/<tier>/.../<app>/src/main.c (or the RA8P1 equivalent) and a thin root-level CMakeLists.txt. Application implementations live under src/, interfaces under inc/, and linker or manifest files at the app root. The selected libs/ra8_board_<board>/ layer supplies the default boot files and linker script. An application carries a local boot or linker file only when it intentionally overrides that default.
../../CLAUDE.md "Terminology Standard" mandates controller/peripheral, COPI/CIPO, CS, primary/main throughout the codebase. Renesas reference text is mapped in comments where it uses legacy terms.
Captured per Section 1.3. There is no separate requirements tool; the @brief corpus and the per-feature design docs serve that role. The traceability artefact is the doxygen-generated cross reference (produced by Phase 3 once the gap list is closed).
Captured per Section 1.2. Architectural design lives in ../RING_AND_WORLD.md and ../MEMORY_MAP.md; detailed design lives in header @brief/@details blocks.
Code is hand-written against the standards in Section 1. Every commit must pass:
The pre-commit hook is at ../../scripts/git/pre-commit and is the source of truth for the gate set.
Host-side tests are distributed across tests/, apps/**/tests/, and the small examples/**/tests/ population. The retained 2026-08-22 snapshot contains 693 source files (689 C, 4 C++) and 689 CTest registrations on clean standalone macOS and Linux configurations. Its authoritative Linux/devcontainer unit gate passed 689/689 in 8.66 s. This is historical evidence rather than a current-tree census. macOS execution was not claimed: the low-address peripheral-mock tests require Linux/container execution, as documented in ../TOOLCHAIN.md. just quality::local::test runs the native suite, and just quality::local::mcdc re-runs it under clang's MC/DC instrumentation.
Integration uses the live scripts/dev/ra8_apps.py inventory, distributed app-local and mock tests, and guarded target execution. The retained 118/118 RA8D2 build is historical evidence. The selected-app HIL and remote-GDB lifecycle results are historical; current-candidate target execution, the complete per-app trace, and full-fleet execution remain pending. Hardware bring-up is documented in ../HARDWARE_BRINGUP.md.
See Section 6.
All source, scripts, plans, and reference PDFs are tracked in this git repository. The long-lived dev branch is the working integration branch and main is the release branch. Feature work is done in issue worktrees, lands on dev after validation, and is promoted to main through a pull request. There is no separate release branch and no semantic-version tag discipline yet (this is a personal-project codebase per ../../CLAUDE.md "Backward Compatibility Policy"); signed tags will be introduced when the SCMP (./SCMP.md) lands.
Commit messages follow a <scope>: <subject> convention seen in the recent history (e.g. secure_app+tests: properly order key_import enums; wire ra8_psa_crypto). Per ../../CLAUDE.md "Git Commits and Pull Requests", no AI attribution is added to commit messages or PR descriptions.
ra8-firmware is a personal in-house codebase with zero backward-compatibility requirements. The full policy is in ../../CLAUDE.md "Backward Compatibility Policy". Net effect on this SDP: APIs may be renamed freely in the same commit that updates all call sites; no deprecation shims are permitted.
main is protected by the CI gate set (../../.github/workflows/firmware.yml) and by the local pre-commit hook. The hook is committed under ../../scripts/git/ and must be installed by each contributor with just hooks.
just quality::local::test runs the host-side suite. Coverage targets are tracked in ../MCDC.md (MC/DC) and the broader gap list is in ../MCDC_GAPS.md. Test files follow test_*.c or test_*.cpp naming and are discovered across the root test categories and module-local test directories by ../../tests/CMakeLists.txt. The retained 2026-08-22 Linux/devcontainer unit-gate result passed all 689 registered tests in 8.66 s. A release evidence pack must retain its own log; this result does not restamp MC/DC or other coverage evidence.
Applications under ../../examples/ek_ra8d2/ exercise the full software stack (HAL + PAL + middleware + app). The live EIL inventory comes from scripts/dev/ra8_apps.py; the 118/118 RA8D2 build and selected-app run are retained historical evidence; current-candidate real target execution and full-fleet execution remain pending.
just quality::local::mcdc invokes ../../scripts/report/mcdc_report.sh which builds tests with clang -fcoverage-mcdc, runs each test binary with LLVM_PROFILE_FILE set, merges via llvm-profdata merge -sparse, and renders the report under build/mcdc-report/. Default threshold is 100 % (per DO-178C Section 6.4.4.2 for Level B); the threshold is overridable via RA8_MCDC_THRESHOLD=NN for intermediate phase gates. The 100.00 % reachable / 92.29 % absolute measurement from 2026-05 is historical; use the current gate output for the candidate under review (see ../MCDC.md measurement history). The archived 2026-05 result classified 58 conditions as deactivated under DO-178C 6.4.4.3. The current decision set is derived in ../MCDC_DEACTIVATIONS.md.
just hil::run invokes ../../scripts/hil/all.sh which auto-discovers every app under examples/ek_ra8d2/hw_validated/hil/ carrying a hil.conf, flashes each to the bench board, and verifies it by the mode that hil.conf declares (uart_scrape, jlink_memprobe, usb_cdc, usb_hid, usb_msc, ...). An app under hil/ with no hil.conf fails the run rather than being skipped. Hardware-in-the-loop is guarded by the shared bench lock. HIL-relevant pushes and trusted same-repository pull requests schedule the managed dev-box listener automatically; a developer checkout and manual workflow dispatch remain available for targeted operation. GitHub Actions retains the current run logs and results as the execution evidence; this plan does not freeze a historical pass count.
just quality::local::misra invokes ../../scripts/checks/misra_check_inner.sh which runs cppcheck with the MISRA addon and writes build/misra/results.txt. The current result and ratchet are produced by the gate and must not be copied from the archived 2026-05 audit. The deviation register at ./MISRA_DEVIATIONS.md tracks the formal disposition (D-001 .. D-005 today). The project's permanent MISRA posture is cppcheck-only (no commercial checker – LDRA / Helix QAC / Polyspace are out of scope under the MIT-licensed personal- project policy in ../CERTIFICATION_SCOPE.md).
scripts/checks/check_stack_usage.sh plus scripts/checks/stack_usage_check.py analyse the per-function .su files emitted by arm-none-eabi-gcc -fstack-usage. Results roll up into ../STACK_USAGE.md. This satisfies IEC 61508-3 Annex B (control of coding-time error sources, stack overflow).
scripts/checks/doxy_audit.py walks libs/, port/, tools/, apps/ (third party excluded) and reports per-function missing-tag counts to ../DOXYGEN_GAPS.md. The release evidence pack must regenerate and restamp the result.
cppcheck-MISRA implements roughly two thirds of the mandatory + required rules (../MISRA.md "The cppcheck-MISRA limitation"). The project's permanent policy is cppcheck-only; commercial checker procurement is out of scope per ../CERTIFICATION_SCOPE.md. Downstream adopters who need full mandatory + required coverage must engage their own qualified checker.
Source: ../../scripts/git/pre-commit.
| Gate | Tool / script |
|---|---|
| ASCII-only encoding | inline check in pre-commit hook |
| C23 typed-enum + zero-init pattern | inline check in pre-commit hook |
| Defensive macro paren | inline check in pre-commit hook |
| clang-format | scripts/checks/format_code.sh --check |
| clang-tidy | scripts/checks/clang_tidy.sh --check |
| @since tag presence | scripts/checks/check-since-version.py |
| Copyright header presence | scripts/checks/check-copyright.py |
| cppcheck (general) | cppcheck --enable=warning,style,performance,portability |
| HUM citations | scripts/checks/cite_check.py --strict |
| Ring/world tags | scripts/checks/check_world_tags.py --strict |
| Roadmap stats freshness | scripts/report/roadmap_stats.py --check |
| Obsolete-standard references | scripts/checks/check_obsolete_standards.py |
| MC/DC-blocking pattern check | scripts/checks/check_mcdc_block.py |
Source: ../../.github/workflows/firmware.yml.
CI re-runs the pre-commit gate set on every PR plus the configured cross-build matrix. The separate hil.yml workflow automatically schedules HIL-relevant pushes and trusted same-repository pull requests on the dedicated dev-box listener, while the shared lock serialises access to the remote bench.
| Activity | Cadence | Owner |
|---|---|---|
| just quality::local::mcdc end-to-end | per Phase-1/2 sprint | dev |
| just quality::local::misra | quarterly | dev |
| just hil::run full sweep | per hardware session | dev |
| scripts/checks/doxy_audit.py regen | per Phase-3 sprint | dev |
| SOUP re-review | <= 12 months per entry | dev |
| Stack-usage report regen | per HAL change | dev |