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_bytesto interrupt-driven mode. Call this once the board’s TX-empty IRQ handler is registered and enabled (it must already be able to calltx_irq_next_byteand 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).
Noneif 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.
Nonemeans 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, viacrate::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