pub trait RticBoardEntry: Board {
type Pac: 'static;
type Core: 'static;
type Executor: 'static;
type Boot: 'static;
type Runtime: NodeDispatchRuntime + 'static;
const DISPATCHERS: &'static [&'static str];
// Required methods
fn init_hardware(
device: Self::Pac,
core: Self::Core,
) -> (Self::Boot, Self::Runtime);
fn open_executor(boot: Self::Boot) -> Self::Executor;
// Provided methods
fn init_hardware_with_deploy(
device: Self::Pac,
core: Self::Core,
_deploy: &DeployOverlay,
) -> (Self::Boot, Self::Runtime) { ... }
fn on_tick() { ... }
fn on_rx_irq() { ... }
fn on_interrupts_live() { ... }
}Expand description
Board-side hook for RTIC integration. The nros::main!()
proc-macro (216.B.3) generates a #[rtic::app] module that calls
Self::init_hardware from inside the framework-generated
#[init] body and wires the returned pair into RTIC #[local]
storage.
Distinct from super::BoardEntry (board-owns-spin). Its Embassy
sibling, , was retired with the EmbassyBoardEntrynros::main!
Embassy branch (issue 2134).
Required Associated Constants§
Sourceconst DISPATCHERS: &'static [&'static str]
const DISPATCHERS: &'static [&'static str]
RTIC dispatchers = [...] list, declared at the board layer
so each chip pins its own interrupt slots (e.g. &["USART1", "USART2"]). The proc-macro splices this into the generated
#[rtic::app(dispatchers = …)] attribute.
Required Associated Types§
Sourcetype Pac: 'static
type Pac: 'static
Chip Peripheral Access Crate handle (e.g.
stm32f4xx_hal::pac::Peripherals). Whatever the RTIC
#[rtic::app(device = …)] attribute expects as the device
peripheral struct.
Sourcetype Core: 'static
type Core: 'static
Core peripheral handle. Typically cortex_m::Peripherals on
Cortex-M chips but kept abstract so nros-platform doesn’t
take a transitive cortex_m dep that every POSIX / Zephyr /
RTOS consumer would inherit.
Sourcetype Executor: 'static
type Executor: 'static
Executor type the board hands back from
open_executor. Concrete board impls plug in
nros::Executor; the assoc type keeps the layering clean
(nros-platform does not depend on nros). The proc-macro drives the
opened executor’s spin loop in the __nros_run task.
Sourcetype Boot: 'static
type Boot: 'static
#178 — hardware-ready deferred-open carrier returned by
init_hardware. Holds whatever the board needs
to open the executor later (locator / domain / node-name — all
'static), but performs no blocking network I/O itself.
The split exists because Executor::open does a blocking zenoh
session open (a TCP connect driven by the platform poll loop, which
needs the timer tick + RX interrupt), and RTIC runs #[init] with
interrupts masked. The proc-macro stashes this carrier in RTIC
#[local] storage from #[init], then the __nros_run task calls
open_executor on its first poll — after init
returns and interrupts unmask.
Sourcetype Runtime: NodeDispatchRuntime + 'static
type Runtime: NodeDispatchRuntime + 'static
Dispatch sink the proc-macro wires into RTIC #[local]
storage. Required to implement
NodeDispatchRuntime so signaled callbacks queued from
RTIC tasks reach the registered Node pkgs.
Per Phase 216.A.2, NodeDispatchRuntime already carries
signal_callback + dispatch_strategy; the RTIC runtime
impl uses DispatchStrategy::Deferred and routes signals
through a heapless::spsc::Producer into an RTIC software
task (see Phase 216.B.2).
Required Methods§
Sourcefn init_hardware(
device: Self::Pac,
core: Self::Core,
) -> (Self::Boot, Self::Runtime)
fn init_hardware( device: Self::Pac, core: Self::Core, ) -> (Self::Boot, Self::Runtime)
Run from inside the proc-macro-generated #[init] body.
Brings up clock / pin / transport hardware and splits the dispatch
SPSC, then returns the (Boot, Runtime) pair the macro stashes in
RTIC #[local] storage. #178 — this must NOT open the executor (that
blocking connect is deferred to open_executor,
called from the __nros_run task where interrupts are live).
Sourcefn open_executor(boot: Self::Boot) -> Self::Executor
fn open_executor(boot: Self::Boot) -> Self::Executor
#178 — open the executor from the Boot carrier.
This performs the blocking zenoh session open (Executor::open),
so it MUST be called from the __nros_run task, NOT #[init]:
RTIC masks interrupts during #[init], which starves the platform
poll loop (no timer tick / RX IRQ) and deadlocks the TCP handshake.
The proc-macro calls this on the task’s first poll, once init has
returned and interrupts are unmasked.
Provided Methods§
Sourcefn init_hardware_with_deploy(
device: Self::Pac,
core: Self::Core,
_deploy: &DeployOverlay,
) -> (Self::Boot, Self::Runtime)
fn init_hardware_with_deploy( device: Self::Pac, core: Self::Core, _deploy: &DeployOverlay, ) -> (Self::Boot, Self::Runtime)
Like init_hardware but applies a deploy-metadata
overlay (Phase 244.D1) to the board’s compiled-in net/locator Config
before opening the executor. nros::main!() calls THIS from the
generated #[init] body, passing the
[package.metadata.nros.deploy.<board>] block.
The default ignores deploy and forwards to
init_hardware, so existing RTIC boards are
unchanged. Boards with a baked net Config (the bare-metal firmware
boards) override it so each Entry pkg can pin its own ip / locator /
gateway — required when two RTIC firmwares share one board on the same
QEMU network (e.g. the talker-rtic / listener-rtic pub/sub pair).
Sourcefn on_tick()
fn on_tick()
Phase 289 (#178 layer 3) — clear + re-arm the board’s periodic tick
IRQ. Invoked from the proc-macro-emitted
#[task(binds = <tick_irq>, priority = 2)] hardware task, whose only
job is waking the wfi inside __nros_run’s connect/poll busy-waits.
The board arms the timer itself in
init_hardware (it owns the PAC); this hook
only handles the per-interrupt acknowledge. An unacknowledged flag is
an IRQ storm that starves the priority-1 run task — always clear it.
Default: no-op, for boards whose RticBoardSpec declares no
tick_irq (the macro then emits no tick task at all).
Sourcefn on_rx_irq()
fn on_rx_irq()
phase-521 W6 (RFC-0113 D4) — the network link’s receive interrupt.
Invoked from the proc-macro-emitted #[task(binds = <rx_irq>, priority = 2)] hardware task. It masks or acknowledges the source;
the interrupt itself is what ends the run task’s park (a wfi in the
port’s wake object), so an arrival is dispatched when it lands rather
than at the next tick.
Default: no-op, for boards whose RticBoardSpec declares no rx_irq.
Sourcefn on_interrupts_live()
fn on_interrupts_live()
Phase 289 (#178 layer 2) — called once at the top of the
__nros_run task, after #[init] returned and interrupts unmasked,
BEFORE open_executor. The place to install
idle-yield hooks that require a live IRQ source (e.g. the mps2
board’s enable_wfi_idle(), which makes the zenoh connect busy-wait
wfi between iterations so host-timed slirp packets can arrive under
QEMU -icount). Installing wfi with no armed IRQ deadlocks — the
tick task exists precisely so this hook is safe to run here.
Default: no-op.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".