Contributing to NumCore
Development environment
Required tools
# Rust toolchain
rustup target add thumbv7m-none-eabi
# QEMU for ARM
apt install qemu-system-arm # Debian/Ubuntu
pacman -S qemu-system-arm # Arch
brew install qemu # macOS
# ARM cross-tools (for binary analysis)
apt install binutils-arm-none-eabi gcc-arm-none-eabi
IDE setup
The workspace root .cargo/config.toml does not set a default build target
(because it breaks host-side test compilation).
VS Code with rust-analyzer:
{
"rust-analyzer.cargo.target": "thumbv7m-none-eabi",
"rust-analyzer.checkOnSave.allTargets": false
}
Code conventions
Style
cargo fmtbefore every commitsnake_casefor functions/variables,CamelCasefor types,SCREAMING_SNAKE_CASEfor constants- Maximum line length: 100 characters
- No trailing whitespace
- Alphabetise module declarations, match arms, and import lists
No comments
Do not add comments unless the code cannot be made self-documenting. Prefer meaningful identifier names, small single-purpose functions, and clear type systems. Existing doc comments on modules, types, and public functions are exceptions.
Safety contract
- Only
hal-<mcu>/may perform MMIO viaunsafe numcore-<mcu>/src/boot.rsis the only exception (.bss/.datainit)runtime/,math/,ui/must contain zerounsafeblocks- Every
unsafeblock must have a// SAFETY:comment
Layer rules
| Layer | Location | May import | Must not import |
|---|---|---|---|
| Boot | numcore-<mcu>/boot.rs | core | hal-*, numcore::* |
| HAL | hal-<mcu>/src/* | core, numcore::hal, submodules | runtime, math, ui |
| Runtime | numcore/src/runtime/ | numcore::hal, math, ui | Concrete HAL crates |
| Math | numcore/src/math/ | core only | Any HAL, runtime/, ui/ |
| UI | numcore/src/ui/ | numcore::hal (Display), core | Any HAL, runtime/, math/ |
Math function contract
All math functions must:
- Accept and return
i64(Q31.32) orOption<i64>/Option<Complex> - Never panic — all errors are domain errors returning
None - Use saturating arithmetic for addition and subtraction
- Use i128 intermediates for multiplication and division
- Handle
Nonepropagation via?
Testing
Host-side suite (300 tests)
cargo test -p numcore_math --tests
Adding new tests
Add tests to test-suite/tests/math.rs covering:
- Expected values for representative inputs (verify against Python Decimal)
- Domain errors (invalid inputs returning
None) - Overflow/underflow at Q31.32 boundaries
- Edge cases (zero, negative, min/max values)
Do not use approx::assert_relative_eq — fixed-point arithmetic is exact;
use assert_eq! directly.
Verifying against Python
SCALE = 2**32
def to_q3132(x: float) -> int: return round(x * SCALE)
def from_q3132(x: int) -> float: return x / SCALE
CI pipeline
GitHub Actions runs on every PR:
cargo fmt --check— formattingcargo build --release --target thumbv7m-none-eabi— firmware buildscargo test -p numcore_math --tests— 300 tests pass- QEMU smoke tests via
test_inputs.txt - On merge to
main: builds WASM simulator and attachesindex-standalone.htmlas a release asset alongside the firmware binary
Pull request process
- Create a feature branch from
main - Run
cargo test -p numcore_math --tests— all pass - Run
make build— firmware compiles - Run in QEMU — existing functionality works
- If changing the math engine or UI rendering, verify with
make wasm-serve— the WASM simulator should reflect the behaviour - Open a PR with clear description of what, why, and how tested
Code review checklist
- No new
unsafeblocks outside HAL or boot -
// SAFETY:comment on everyunsafeblock - All math functions return
Optionfor error cases - No heap allocation or
extern crate alloc - Tests cover: expected values, domain errors, overflow
-
cargo fmthas been run -
cargo test -p numcore_math --testspasses - Firmware builds with
make build - Verified in QEMU