Skip to main content

Module boot_report

Module boot_report 

Source
Expand description

phase-412 – the boot self-report, for boards with no reachable log sink. A fixed RAM record the image writes about itself, for targets where no log sink reaches a human.

§Why this exists

phase-412 derived six pool counts and the executor arena for the mr-canhubk344 island, and then could not tell whether the derived image was correct. The only available signal was the ROS graph’s node count, and one unchanged configuration produced 4, 0, 0, 4, 4 across five runs. Every other channel was already disqualified for that board:

  • The console is on lpuart0, which is not wired on the MR-CANHUBK344. lpuart2 is the zenoh serial transport and cannot carry a second protocol.
  • nros_log therefore reaches nothing. Both arena diagnostics (issue 0900) go through it, so the two messages written specifically to explain an arena failure are invisible on the one board that needed them.
  • SEGGER RTT was tried and could not discriminate: a working image and a derived image both emitted only the Zephyr banner, and a deliberate positive control produced nothing at all.
  • Semihosting halts the core until a probe answers and FAULTS with no probe attached, so an image carrying it cannot run standalone.

What all of those share is that they are STREAMS: they need the board to still be running, and they need somebody attached at the moment the interesting thing happens. The failure this campaign is trying to see is the opposite shape. An under-sized arena halts DURING entity creation, before the first spin, so issue 0900’s advisory never prints – the failure cannot report itself through any stream.

So this is not a stream. It is a fixed-size record in RAM that the image keeps up to date as it boots, read out AFTERWARDS by halting the core and dumping memory. It survives the halt because it does not depend on anything still running, and a PARTIAL record is the useful case rather than a lost one: the last stage reached and the allocation that did not fit are exactly what names the knob to change.

§Reading it

The record is a #[no_mangle] static, so it has a symbol in the ELF and a debugger can find it without the address being wired in anywhere:

pyocd commander -t s32k344 -c "halt" -c "savemem <addr> <len> report.bin"
python3 scripts/read-boot-report.py <elf> report.bin

[MAGIC] distinguishes a written record from uninitialised RAM, and [BootReport::struct_size] lets a reader refuse a layout it does not know rather than decode it wrongly.

§Cost, and why it is opt-in

Enabled by setting NROS_BOOT_REPORT=1 at build time (Zephyr: CONFIG_NROS_BOOT_REPORT=y), which makes nros-node’s build script emit cfg(nros_boot_report). With the cfg absent every function here is an empty #[inline(always)] body and the static does not exist, so an image that does not opt in is byte-identical to one built before this module – the same rule issue 0900’s arena knob and phase-403’s rx_buffer_from_type() both keep.

Enabled, it costs [BootReport::struct_size] bytes of .bss (60 on a 32-bit target) and a handful of relaxed atomic stores on paths that run once per entity at registration. Nothing here is on the spin path.

Enums§

Stage
How far boot got. Monotonic, and the single most useful field: an arena failure halts during entity creation, so the stage that was NOT reached names the phase to look at.

Constants§

MAGIC
"NRSR" – nano-ros self report. Written LAST, so a reader that finds it knows every field before it is already valid.
VERSION
Layout version. Bump on any field change; a reader refuses what it does not know rather than decoding a record it would misread.

Functions§

checkpoint
init
note_alloc
note_alloc_failed
note_arena_capacity
note_cpp_init_ret
note_error