Skip to main content

Module console

Module console 

Source
Expand description

Debug console — the board’s UART/semihosting/whatever, reached through crate::port::board. Replaces the old rivet::arch::debug_print; application code should use this module (or crate::print! / crate::println!) instead of talking to the port directly.

§Interrupt-driven mode (plan.md Phase 14)

By default every write is a blocking spin on the board’s polling write, exactly as before — always correct, including from the fault path (see below for why that matters). A board can opt in to interrupt-driven TX by registering its own TX-empty IRQ handler (through crate::irq) that calls tx_irq_next_byte and calling enable_irq_tx once that’s wired up; from then on, write_str/ write_bytes push into a ring buffer instead of blocking on hardware directly, and the registered ISR drains it.

Deliberately drop-on-full, not block-on-full — the same policy [crate::log] uses, and for the same reason, sharpened by a real constraint here: crate::fault::on_fault calls console::write_str from inside the trap/exception handler on a single-hart kernel, where no interrupt (including the one TX handler that would ever drain the ring) can preempt the trap handler that’s currently running. Blocking there would deadlock permanently, not just stall — dropping and counting is the only safe choice.

RX is push-only from the board’s side (on_rx_byte, called from a registered RX IRQ handler) and pull-only from the application side (try_read_byte) — genuinely additive, doesn’t touch the existing write path at all.

Functions§

enable_irq_tx
Switch write_str/write_bytes to interrupt-driven mode. Call this once the board’s TX-empty IRQ handler is registered and enabled (it must already be able to call tx_irq_next_byte and re-arm/ disable the hardware interrupt itself — this module has no MMIO access of its own).
flush_sync
Synchronously drain any bytes still queued in the TX ring, via the blocking polling write. No-op if interrupt-driven TX was never enabled (nothing can be queued there).
on_rx_byte
Called from the board’s RX ISR with one received byte.
try_read_byte
Non-blocking read of one received byte (task context). None if nothing is buffered, or interrupt-driven RX was never wired up.
tx_irq_next_byte
Called from the board’s TX-empty ISR: pull the next queued byte, if any, for the ISR to write to hardware. None means the ring is empty — the ISR should disable the TX interrupt at that point (it will be re-armed by the next dropped-into-empty-ring write, via crate::port::arch::request_reschedule-style “kick” the board’s own IRQ handler is responsible for, matching how it originally armed it).
write_bytes
write_str