Skip to content

Latest commit

 

History

History
267 lines (199 loc) · 11.2 KB

File metadata and controls

267 lines (199 loc) · 11.2 KB

Getting Started

One page from zero to a verified PASS, whichever kind of user you are. Pick your row, follow one section, and end at the same place: a device (or simulator) explaining itself through NOBRO_* reports.

You have Start at
A compatible board and a prebuilt starter image Zero-code path
Rust + a probe/UF2 board Hardware quick start
Just a laptop Toolchains and IDEs

Hardware quick start

Build or obtain an image for the exact board profile, flash it explicitly, then read its fixed NOBRO_* report over the transport that application exposes.

Prerequisites

  • A supported board and its normal upload mechanism (UF2, Arduino, or a debug probe).
  • Rust (rustup target add thumbv7em-none-eabihf) and Python 3.10+.
  • The compiler and image tools required by the selected port.

Public flash command

python sdk/cli/nobro.py flash --help

Applications that expose a serial report end with an explicit verdict:

=== imu on nosd ===
  magic                  = 1313164366 (0x4E42...)
  all_pass               = 1 (0x1)
PASS: all_pass=1

Image generation and upload settings are board-specific. Do not reuse an address, image, or boot layout from another profile.

USB identity and recovery

The bootloader and the application are separate USB devices. They may advertise different VID/PID values, strings, storage volumes, or serial endpoints, and the host may assign them different device paths. UsbConfig controls only the mounted application backend; it does not rename or reconfigure the bootloader.

SoftDevice and no-SoftDevice profiles also use different flash layouts. Select the image from the installed bootloader's own metadata rather than inferring the layout from the board shape or from the application's last USB identity.

If application enumeration stops making progress, a backend that supports UsbStack::force_reenumeration() can detach and reattach the application identity. Rate limit that recovery, continue calling poll(), and wait for configured() before doing I/O. Suspended is a valid host power state and should normally be allowed to resume through poll(); repeatedly forcing enumeration during ordinary suspend creates a reconnect loop. Forced re-enumeration does not enter DFU. Conversely, failure to see a bootloader volume or serial endpoint proves only that the host did not enumerate it, not whether the processor reached bootloader code.

What "PASS" means

The app seals a fixed-layout report (NOBRO_*_REPORT) and consumers check magic, completed, all_pass, and its diagnostic checksum. That unkeyed value detects accidental snapshot corruption only; it is not authentication. A silent target or unavailable peripheral is not a passing result.

No probe? No board?

  • Serial boards: most demos also print their report line over USB-CDC/UART; any serial monitor shows the same all_pass=1.
  • No hardware at all: the Python simulators under bindings/python and the host test suite (cargo test on the portable crates, tools/checks/ci_matrix.sh) exercise the same contracts on your desktop.

Performance notes (facts, not folklore)

  • SPI transfers use EasyDMA. The current portable I2C provider uses bounded CPU-polled legacy TWI and reports TransferMode::Polling; contract checks prevent it from being advertised as DMA.
  • Sensor samples move through the kernel as zero-copy tickets (SamplePool): producers publish a slot, consumers borrow it - payloads are not copied through queues.
  • Resource and timing claims must be measured for the final target and workload.

Zero-code path (no toolchain)

The zero-toolchain path requires a prebuilt image supplied by a release or another trusted builder: flash it by drag-and-drop, watch the board explain itself in a browser, and design your first app as blocks — no Rust, no compiler, no IDE.

1. Flash the starter (once)

You need an nRF52840 board whose installed UF2 bootloader metadata explicitly reports SoftDevice S140.

  1. Double-tap the RESET button. A USB drive appears (its INFO_UF2.TXT should say SoftDevice: S140).
  2. Drag nobrortos-starter-s140.uf2 onto the drive. The board reboots on its own.

There is currently no published release artifact in this repository. A trusted builder runs python tools/release/package_prebuilt_uf2.py --build and hands you the file from _work/prebuilt/.

2. Watch it explain itself

Open packages/web-flasher/index.html in Chrome or Edge and click Open report console, then pick the board's serial port. The starter streams its self-verification and the console translates it into plain sentences:

✅ PASS  CDC: all checks passing
NobroRTOS IMU who=0x71 addr=104 i2c=1 reads=1240 err=0 accel=1002mg ... PASS

If the required sensor is unavailable, you see exactly which check failed — the same first-fault discipline every NobroRTOS app has.

(No browser with Web Serial? Any serial monitor at 115200 shows the same lines; the repository's Python report tools provide the decoder from a source checkout.)

3. Design your own app as blocks

Open packages/block-editor/index.html, add periodic/control/service tasks and wires, and export app.json. Validate the exact firmware input:

python sdk/cli/nobro.py app your-app.json

4. When you outgrow no-code

Turn that same file into native firmware with one command:

python sdk/cli/nobro.py firmware your-app.json --build

The graph describes scheduling and topology. Bind physical sensors, actuators, and payload transport in the provider layer; the editor does not pretend those drivers exist merely because a task has a hardware-like name.

You are here Next rung
No-code starter Arduino library (packages/arduino, no Rust needed)
Arduino sketches Python host tools from this repository
Python C/C++ modules, then the full Rust workspace

Toolchains and IDEs

One project command

The SDK project flow keeps generated work under ignored _work/projects/ by default:

python sdk/cli/nobro.py project new rover
python sdk/cli/nobro.py project run _work/projects/rover
python sdk/cli/nobro.py project report _work/projects/rover/reports/simulation.json

run explains the graph-derived contract and admission headroom, compiles a host graph regenerated from the same workload.json, runs the bounded simulation, and decodes its report. The generated scaffold is a host model, not a flashable image. To opt into a priced capability, edit only the workload's top-level features object, for example "features": {"capacity-report": true}. The SDK catalog drives validation, generation, and explanation; unavailable or unpriced combinations fail instead of being reported as free.

That same file is a native-firmware input—there is no second feature file:

python sdk/cli/nobro.py firmware _work/projects/rover/workload.json \
  --out _work/firmware --build

The no-SoftDevice catalog entry is checked by linked feature-off/feature-on images, including symbol absence/presence and measured resource deltas. Target rows without that evidence remain unavailable.

One-file production firmware

The concise firmware path starts from tutorials/rover-one-file/app.nobro and generates a real no_std nRF crate plus the workload consumed by admission/explain:

python sdk/cli/nobro.py firmware tutorials/rover-one-file/app.nobro --build
python sdk/cli/nobro.py project explain _work/projects/rover/workload.json

The nRF52840 S140/no-SoftDevice, UNO R4 RA4M1, and SAMD21 profiles own distinct linker, startup, clock, interrupt, DMA, and boot contracts. The generator never chooses one from a connected endpoint. Generated files live in ignored _work/projects by default. Omitting budget means unmeasured and produces no deadline-admission claim; provide a measured execution bound when deadline admission is required. An optional wake 25us line after board admits a measured compare-wake-to-dispatch upper bound. It is an engineering input, not a value inferred from a board name. Periodic task lines may also shape their first release and use a constrained deadline:

control motor every 5ms phase 1ms deadline 4ms budget 400us
periodic imu every 10ms -> motor

phase must be below every, and deadline must not exceed it. The generator checks that execution plus blocking fits the deadline and emits the same values into build-time admission and the target dispatcher.

Generated nRF projects select nobro-hal's board-specific BASEPRI critical-section provider. Do not add Cortex-M's critical-section-single-core feature: it uses PRIMASK, conflicts with the selected provider, and would mask the admitted timebase. High-priority deadline/watchdog handlers must restrict themselves to the documented lock-free handoff.

NobroRTOS is not tied to the Arduino IDE or VS Code. The core builds from a terminal on Linux, macOS, or Windows with Rust, Python, the selected target support, and any external flash utility required by that target.

Pure CLI (recommended, any OS)

rustup target add thumbv7em-none-eabihf          # or your board's target
cd core
cargo build -p kernel-selftest --release          # build firmware
cd ..
python3 sdk/cli/nobro.py flash jlink --bin app.bin --addr 0x1000   # J-Link (nRF)
python3 sdk/cli/nobro.py flash uf2  --file app.uf2 --drive <DRIVE> # UF2-capable board
python3 sdk/cli/nobro.py flash arduino --port <PORT> --fqbn <FQBN> --build-dir <DIR>  # ESP/AVR

sdk/cli/nobro.py flash is one flashing abstraction over J-Link, UF2 drag-drop, and arduino-cli; override the J-Link path with the JLINK_EXE env var. tools/build/bin2uf2.py converts raw binaries only for its explicit nRF52840, RP2040, and RP2350-Arm family IDs.

Cross-MCU, one command

bash tools/checks/platforms/check_portability.sh   # builds the portable core for all 6 MCU families
bash tools/checks/ci_matrix.sh           # host tests + portability + port builds + validators
bash tools/checks/lint_gate.sh           # clippy -D warnings gate

Editors and IDEs (all optional)

  • Any editor + rust-analyzer (Neovim, Helix, Zed, Emacs, IntelliJ-Rust, VS Code).
  • No editor at all: the CLI above is complete.
  • Arduino IDE / PlatformIO: needed for ESP32/AVR Arduino applications (which run vendor firmware), via arduino-cli - not for the NobroRTOS Rust core.

Config-driven, no Rust knowledge

python sdk/cli/nobro.py app my_robot/app.json
python sdk/cli/nobro.py firmware my_robot/app.json --build

Declare tasks and wires once. The validator, Python host simulator, block editor, and native generator consume the same strict JSON. Provider selection is a separate typed step so hardware metadata does not become a second scheduler model.

Other OS / SDK surfaces

  • Linux/macOS/Windows: identical Cargo + Python flow; only the flashing backend differs.
  • CI: tools/checks/ci_matrix.sh is a single exit-coded gate for GitHub Actions / GitLab CI.
  • C / C++: bindings/c + bindings/cpp expose the module ABI for non-Rust codebases.
  • Web flasher / PlatformIO packaging: the SDK manifest (sdk/sdk-manifest.json, validated by tools/checks/release/check_sdk_manifest.py) declares the Arduino + PlatformIO surfaces.