This guide covers two jobs: adapting existing bounded application logic to NobroRTOS contracts and adding a new MCU/board target. It intentionally avoids framework-specific translation rules; the public API is the source of truth.
Code is easiest to reuse when it is no_std, does not allocate on hot paths, accepts
its dependencies through traits, and has explicit buffer capacities.
| Existing element | NobroRTOS destination |
|---|---|
| Pure algorithm, DSP, or control law | Call from a module task or bounded async task |
Synchronous embedded-hal driver |
Mount behind an adapter in core/adapters/<domain>/ |
| Message schema | Fixed-capacity record or generated bounded ROS record |
| Periodic task | Graph task with period, budget, criticality, and dependencies |
| Queue | Bounded mailbox or channel with explicit capacity |
| Shared peripheral | Capability grant plus a HAL lease/provider |
| Board configuration | Data-only board.json profile |
Do not carry over a scheduler, allocator, global peripheral singleton, or unbounded queue. Keep the reusable register/algorithm layer and express ownership, timing, and capacity through Nobro contracts.
- Choose the domain under
core/adapters/(imu,wireless,power, and so on). - Implement the domain contract without embedding board policy.
- Accept a bus/provider through a trait instead of constructing global hardware.
- Bound every buffer, retry count, and recovery window.
- Add the adapter path to
core/adapters/catalog.json. - Compose it in an application under
core/apps/<use-case>/.
Crates hold shared domain contracts. Adapters hold device or library implementations. Applications select and connect them. Avoid another parallel “ecosystem” hierarchy.
Board profiles live under core/boards/<platform>/<board>/board.json. A profile is data,
not proof of a working port. Give it a globally unique board_id and describe:
- architecture and memory regions;
- boot/application flash origin;
- RAM capacity;
- critical pins and buses;
- supported upload format where applicable.
Run:
python tools/check_board_profiles.py
python tools/check_core_layout.pyPorts live in core/ports/<mcu-family>/ as isolated target workspaces.
- Add the target and linker memory layout without hardcoding a developer-machine path.
- Implement
HalClockfirst and declare only capabilities that are present. - Add deadline, bus, PWM, USB, event, and lease providers independently.
- Keep board pin selection outside reusable provider types.
- Return explicit unsupported/capacity errors; do not substitute a software stub for a hardware capability.
- Add a repository-contained implementation directory, a named composition, and only
implemented claims to
core/boards/platform_tiers.json. - Scope every host/target gate to the exact platform, composition, and capabilities it exercises. Bind its runner to a hosted workflow job and receipt driver; the validator rejects a required gate that the driver does not invoke.
- Begin a clean receipt session, execute the matrix argv through
tools/check_platform_tiers.py --run-gate, and assert all runner receipts. Receipts bind the current matrix and session to Git HEAD, the tracked diff, and every nonignored untracked source path and its content. Ignored_workoutput is excluded. This is local freshness bookkeeping, not signed or physical attestation.
The public provider traits are in nobro_hal::traits. A provider tier means at least
one real trait implementation exists for the target. A deep tier requires one native
composition to implement every capability in the current provider vocabulary.
- Keep application flash origins in board data and linker scripts synchronized.
- Never erase or rewrite a bootloader as a side effect of a normal application upload.
- Package only application regions in UF2/bin artifacts.
- Treat signing keys and provisioning transports as board integrations, not generic kernel behavior.
- Public paths contain no endpoint names, local serial ports, machine paths, or private project notes.
- The adapter/application/board/port lives in the existing categorized tree.
- Every capacity and unsupported path is explicit.
- Board and platform matrices describe only implemented public capabilities.
-
python tools/run_checks.pypasses. -
tools/ci_matrix.shpasses in an MSYS2 or POSIX shell.