rivet-bsp-esp32s3 0.2.0

Rivet RTOS: ESP32-S3 board port (UART0 console, watchdog disable, Xtensa CCOUNT tick) — real hardware, no QEMU model
docs.rs failed to build rivet-bsp-esp32s3-0.2.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Rivet RTOS board support: ESP32-S3 real hardware (plan.md Phases 22-24).

Implements the Group B (rivet::port::board) contract for a genuine ESP32-S3 dev board — no QEMU model exists for Xtensa in this environment, so unlike every other board in this workspace, nothing here has ever run in a simulator; every piece is validated by flashing and reading the real serial transcript.

Why no esp-hal dependency

An earlier version of this crate depended on esp-hal for its well-tested clock-tree and watchdog-disable bring-up (esp_hal:: init()). That does not coexist with Rivet owning its own preemptive- tick interrupt: esp-hal::interrupt::xtensa defines __level_N_interrupt for every level 1 through 7 as part of its own generic peripheral-interrupt dispatch, and xtensa-lx-rt only allows exactly one definition of each — confirmed as a hard multiple definition link error at two different levels tried, not assumed. Watchdog disable is instead hand-rolled directly against the esp32s3 PAC: the exact register sequence and magic unlock keys below were cross-checked against esp-hal's own source for correctness, without linking esp-hal itself.

CPU clock: not yet measured

[CPU_HZ] is a documented assumption (the boot ROM's XTAL-derived default), not something this crate independently measures or configures — tick cadence is therefore approximate for now, not exact. Correctness of scheduling itself does not depend on this being precise (every tick still fires and is handled), only real-world timing accuracy does. Tracked as a follow-up once basic preemption is proven on hardware.

This board's mask ROM needs a JTAG-assisted boot, every boot

Confirmed live on the N16R8 devkit this session (chip revision v0.2), reproduces after a full USB power cycle with no debugger ever attached — this is a real, persistent property of this chip, not a debugging artifact: on reset, before any flashed firmware (or even the 2nd-stage bootloader) ever runs, Espressif's own mask ROM main() reads the CPU's PRID special register, finds it equal to 0xabab (the value ROM treats as "running under a simulator"), and spins forever in a tight loop waiting for an external debugger to write the real boot entry point into a fixed hardware register (0x600c0004) — normal SPI-flash boot is never attempted. Nothing in this crate, rivet-arch-xtensa, or rivet itself can fix this: it happens entirely inside ROM, before any of our code is reachable. scripts/esp32s3-jtag-unblock.sh (repo root) automates the workaround — reset, halt in the spin loop, write the ELF's real entry point into that register, resume — and was verified to let the flashed app run to completion (traced via JTAG all the way to __rivet_board_exit). Needed on every boot, not just once.