rivet-rtos 0.1.0

Rivet RTOS: zero-allocation async RTOS kernel — arch/board-independent, see docs/porting.md
Documentation

Rivet RTOS — zero-allocation, dual-tier RTOS for microcontrollers.

Architecture

Two tiers of concurrency, unified under one priority scheduler:

  • Preemptive tier (#[rivet::ptask] / [spawn_ptask!]): each task gets its own stack. The timer tick can suspend a running task at any point (not just at a yield/await) and resume a higher-priority one instead — real priority preemption, with priority inheritance on [preempt::PriorityMutex] to avoid priority inversion.
  • Cooperative tier (#[rivet::task]): async fn tasks compiled to Future state machines, polled on a single shared stack — zero per-task stack cost, ideal for I/O-bound/event-driven logic. This tier runs as an ordinary preemptive task at the lowest priority, so any real preemptive task immediately preempts it; it fills otherwise idle CPU time and only calls WFI when nothing anywhere is ready.

Targets

  • ARM Cortex-M (M0+/M3/M4/M7/M33) — via the arch-cortex-m feature
  • RISC-V (RV32) — via the arch-riscv feature

Example

use rivet::sync::Semaphore;

static SEM: Semaphore<1> = Semaphore::new(0);

// Cooperative: fine for I/O-bound logic.
#[rivet::task(priority = 0)]
async fn background() {
    loop {
        SEM.acquire().await;
    }
}

// Preemptive: genuinely can't be starved by a lower/equal priority
// task that never yields.
static CFG: u32 = 42;
fn critical_task(cfg: &'static u32) -> ! {
    loop {
        // real work, no .await required anywhere
    }
}

fn main() -> ! {
    rivet::init();
    rivet::spawn_ptask!(stack = 2048, priority = 5, entry = critical_task, arg = CFG);
    rivet::run();
}