1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2024-11-26 09:30:52 +02:00

Add example implementing logger.

This commit is contained in:
Andrew Walbran 2023-03-15 15:05:22 +00:00
parent 15518aa177
commit 31c7b283c2
7 changed files with 144 additions and 1 deletions

View File

@ -264,7 +264,8 @@
- [Multiple registers](bare-metal/aps/better-uart/registers.md)
- [Driver](bare-metal/aps/better-uart/driver.md)
- [Using it](bare-metal/aps/better-uart/using.md)
- [Logging]()
- [Logging](bare-metal/aps/logging.md)
- [Using it](bare-metal/aps/logging/using.md)
- [Other projects](bare-metal/aps/other-projects.md)
- [Useful crates]()
- [zerocopy]()

View File

@ -21,3 +21,7 @@ path = "src/main_minimal.rs"
[[bin]]
name = "improved"
path = "src/main_improved.rs"
[[bin]]
name = "logger"
path = "src/main_logger.rs"

View File

@ -21,11 +21,15 @@ minimal.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/minimal minimal.bin
improved.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/improved improved.bin
logger.bin: build
aarch64-linux-gnu-objcopy -O binary target/aarch64-unknown-none/debug/logger logger.bin
qemu_minimal: minimal.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel minimal.bin -s
qemu: improved.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel improved.bin -s
qemu_logger: logger.bin
qemu-system-aarch64 -machine virt -cpu max -serial mon:stdio -display none -kernel logger.bin -s
clean:
cargo clean

View File

@ -0,0 +1,54 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ANCHOR: main
use crate::pl011::Uart;
use core::fmt::Write;
use log::{LevelFilter, Log, Metadata, Record, SetLoggerError};
use spin::mutex::SpinMutex;
static LOGGER: Logger = Logger {
uart: SpinMutex::new(None),
};
struct Logger {
uart: SpinMutex<Option<Uart>>,
}
impl Log for Logger {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}
fn log(&self, record: &Record) {
writeln!(
self.uart.lock().as_mut().unwrap(),
"[{}] {}",
record.level(),
record.args()
)
.unwrap();
}
fn flush(&self) {}
}
/// Initialises UART logger.
pub fn init(uart: Uart, max_level: LevelFilter) -> Result<(), SetLoggerError> {
LOGGER.uart.lock().replace(uart);
log::set_logger(&LOGGER)?;
log::set_max_level(max_level);
Ok(())
}

View File

@ -0,0 +1,51 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ANCHOR: main
#![no_main]
#![no_std]
mod exceptions;
mod logger;
mod pl011;
use crate::pl011::Uart;
use core::panic::PanicInfo;
use log::{error, info, LevelFilter};
use psci::system_off;
/// Base address of the primary PL011 UART.
pub const PL011_BASE_ADDRESS: usize = 0x900_0000;
#[no_mangle]
extern "C" fn main(x0: u64, x1: u64, x2: u64, x3: u64) {
// Safe because `PL011_BASE_ADDRESS` is the base address of a PL011 device,
// and nothing else accesses that address range.
let uart = unsafe { Uart::new(PL011_BASE_ADDRESS as *mut u32) };
logger::init(uart, LevelFilter::Trace).unwrap();
info!("main({:#x}, {:#x}, {:#x}, {:#x})", x0, x1, x2, x3);
assert_eq!(x1, 42);
system_off().unwrap();
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
error!("{}", info);
system_off().unwrap();
loop {}
}
// ANCHOR_END: main

View File

@ -0,0 +1,16 @@
# Logging
It would be nice to be able to use the logging macros from the [`log`][1] crate. We can do this by
implementing the `Log` trait.
```rust,editable,compile_fail
{{#include examples/src/logger.rs:main}}
```
<details>
* The unwrap in `log` is safe because we initialise `LOGGER` before calling `set_logger`.
</details>
[1]: https://crates.io/crates/log

View File

@ -0,0 +1,13 @@
# Using it
We need to initialise the logger before we use it.
```rust,editable,compile_fail
{{#include ../examples/src/main_logger.rs:main}}
```
<details>
* Note that our panic handler can now log details of panics.
</details>