|
| 1 | +//! Rust logging in Zephyr |
| 2 | +//! |
| 3 | +//! There are a few config settings in Zephyr that affect how logging is done. Zephyr has multiple |
| 4 | +//! choices of front ends and backends for the logging. We try to work with a few of these. |
| 5 | +//! |
| 6 | +//! There are various tradeoffs in terms of code size, and processing time that affect how logging |
| 7 | +//! is done. In addition to the tradeoffs in Zephyr, there are also tradeoffs in the Rust world, |
| 8 | +//! especially when it comes to formatting. |
| 9 | +//! |
| 10 | +//! For now, any use of logging in Rust will go through the `log` crate. This brings in the |
| 11 | +//! overhead of string formatting. For the most part, due to a semantic mismatch between how Rust |
| 12 | +//! does string formatting, and how C does it, we will not defer logging, but generate log strings |
| 13 | +//! that will be sent as full strings to the Zephyr logging system. |
| 14 | +//! |
| 15 | +//! - `CONFIG_LOG`: Global enable of logging in Zephyr. |
| 16 | +//! - `CONFIG_LOG_MODE_MINIMAL`: Indicates a minimal printk type of logging. |
| 17 | +//! |
| 18 | +//! At this time, we will provide two loggers. One is based on using the underlying printk |
| 19 | +//! mechanism, and if enabled, will send log messages directly to printk. This roughly corresponds |
| 20 | +//! to the minimal logging mode of Zephyr, but also works if logging is entirely disabled. |
| 21 | +//! |
| 22 | +//! The other log backend uses the logging infrastructure to log simple messages to the C logger. |
| 23 | +//! At this time, these require allocation for the string formatting, although the allocation will |
| 24 | +//! generally be short lived. A good future task will be to make the string formatter format |
| 25 | +//! directly into the log buffer used by Zephyr. |
| 26 | +
|
| 27 | +use log::{LevelFilter, Log, SetLoggerError}; |
| 28 | + |
| 29 | +cfg_if::cfg_if! { |
| 30 | + if #[cfg(all(CONFIG_PRINTK, |
| 31 | + any(not(CONFIG_LOG), |
| 32 | + all(CONFIG_LOG, CONFIG_LOG_MODE_MINIMAL))))] |
| 33 | + { |
| 34 | + // If we either have no logging, or it is minimal, and we have printk, we can do the printk |
| 35 | + // logging handler. |
| 36 | + mod impl_printk; |
| 37 | + pub use impl_printk::set_logger; |
| 38 | + } else if #[cfg(all(CONFIG_LOG, |
| 39 | + not(CONFIG_LOG_MODE_MINIMAL), |
| 40 | + CONFIG_RUST_ALLOC))] |
| 41 | + { |
| 42 | + // Otherwise, if we have logging and allocation, and not minimal, we can use the Zephyr |
| 43 | + // logging backend. Doing this without allocation is currently a TODO: |
| 44 | + todo!("Zephyr logging not yet supported"); |
| 45 | + } else { |
| 46 | + /// No lagging is possible, provide an empty handler that does nothing. |
| 47 | + /// |
| 48 | + /// It could be nice to print a message somewhere, but this is only available when there is |
| 49 | + /// no where we can send messages. |
| 50 | + pub unsafe fn set_logger() -> Result<(), SetLoggerError> { |
| 51 | + Ok(()) |
| 52 | + } |
| 53 | + } |
| 54 | +} |
| 55 | + |
| 56 | +// The Rust logging system has different entry points based on whether or not we are on a target |
| 57 | +// with atomic pointers. We will provide a single function for this, which will be safe or unsafe |
| 58 | +// depending on this. The safety has to do with initialization order, and as long as this is called |
| 59 | +// before any other threads run, it should be safe. |
| 60 | +// |
| 61 | +// TODO: Allow the default level to be set through Kconfig. |
| 62 | +cfg_if::cfg_if! { |
| 63 | + if #[cfg(target_has_atomic = "ptr")] { |
| 64 | + unsafe fn set_logger_internal(logger: &'static dyn Log) -> Result<(), SetLoggerError> { |
| 65 | + log::set_logger(logger)?; |
| 66 | + log::set_max_level(LevelFilter::Info); |
| 67 | + Ok(()) |
| 68 | + } |
| 69 | + } else { |
| 70 | + unsafe fn set_logger_internal(logger: &'static dyn Log) -> Result<(), SetLoggerError> { |
| 71 | + log::set_logger_racy(logger)?; |
| 72 | + log::set_max_level_racy(LevelFilter::Info); |
| 73 | + Ok(()) |
| 74 | + } |
| 75 | + } |
| 76 | +} |
0 commit comments