Skip to main content

ove/
console.rs

1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! Low-level console I/O for oveRTOS.
8//!
9//! Provides single-character read/write access to the platform console
10//! (typically a UART). For formatted output, use the [`crate::log`] function
11//! or the `log` crate facade installed by [`crate::log::init`].
12//!
13//! For **early-boot debug** before `log::init()` runs, or for one-off
14//! prints from contexts where the `log` framework's mutexes aren't
15//! reachable, use the [`crate::printk!`] / [`crate::ove_print!`] macros
16//! which write directly via `ove_console_write` with a 256-byte
17//! stack-formatted buffer. Same shape as Zephyr's `printk!`.
18
19use crate::bindings;
20
21/// Read a single character from the console.
22///
23/// Returns `Some(c)` where `c` is in `0..=255`, or `None` if no character
24/// is currently available. The call may block until a character arrives
25/// depending on the backend.
26pub fn getchar() -> Option<i32> {
27    let c = unsafe { bindings::ove_console_getchar() };
28    if c < 0 { None } else { Some(c) }
29}
30
31/// Write a single character to the console output.
32///
33/// `c` is interpreted as an unsigned 8-bit byte (`0..=255`).
34pub fn putchar(c: i32) {
35    unsafe { bindings::ove_console_putchar(c) }
36}
37
38/// Write a byte slice to the console output (no formatting, no
39/// newline). Backs the [`crate::printk!`] / [`crate::ove_print!`]
40/// macros and is safe to call from any thread or ISR.
41pub fn write_bytes(buf: &[u8]) {
42    if buf.is_empty() {
43        return;
44    }
45    // SAFETY: pointer + length cover a valid byte slice we own.
46    unsafe {
47        bindings::ove_console_write(buf.as_ptr().cast(), buf.len() as ::core::ffi::c_uint);
48    }
49}
50
51/// Format arguments into a 256-byte stack buffer and write to the
52/// console via [`write_bytes`]. Used by the [`crate::printk!`] and
53/// [`crate::ove_print!`] macros; can also be called directly when a
54/// pre-built [`core::fmt::Arguments`] is available.
55///
56/// Output is truncated silently if the formatted result exceeds the
57/// buffer.
58pub fn print_fmt(args: ::core::fmt::Arguments<'_>) {
59    let mut buf = [0u8; 256];
60    let mut w = crate::fmt::FmtBuf::new(&mut buf);
61    let _ = ::core::fmt::Write::write_fmt(&mut w, args);
62    write_bytes(w.as_bytes());
63}
64
65/// Format + write to the console without going through the `log`
66/// framework. Useful for early-boot debug (before `log::init()`) and
67/// for ISR-adjacent contexts.
68///
69/// Equivalent to Zephyr's `printk!`. Formats into a 256-byte stack
70/// buffer and silently truncates if the result is larger.
71///
72/// ```ignore
73/// ove::printk!("boot stage {}: {} bytes free\n", stage, free);
74/// ```
75#[macro_export]
76macro_rules! printk {
77    ($($arg:tt)*) => {
78        $crate::console::print_fmt(::core::format_args!($($arg)*))
79    };
80}
81
82/// Alias for [`printk!`] using the `ove_print!` name.
83#[macro_export]
84macro_rules! ove_print {
85    ($($arg:tt)*) => {
86        $crate::console::print_fmt(::core::format_args!($($arg)*))
87    };
88}
89
90/// `printk!` variant that appends a newline.
91#[macro_export]
92macro_rules! printkln {
93    () => { $crate::console::write_bytes(b"\n") };
94    ($($arg:tt)*) => {
95        $crate::console::print_fmt(::core::format_args!("{}\n", ::core::format_args!($($arg)*)))
96    };
97}