More robust, self-contained UART printing in panic!

pull/37/head
Andre Richter 5 years ago
parent 0e7a3b1cd7
commit 8c2b18e8ce
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -213,6 +213,12 @@ diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
+use crate::{bsp, interface};
+use core::fmt;
+
+pub fn _print(args: fmt::Arguments) {
+ use interface::console::Write;
+
+ bsp::console().write_fmt(args).unwrap();
+}
+
+/// Prints without a newline.
+///
+/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -231,11 +237,5 @@ diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
+ $crate::print::_print(format_args_nl!($($arg)*));
+ })
+}
+
+pub fn _print(args: fmt::Arguments) {
+ use interface::console::Write;
+
+ bsp::console().write_fmt(args).unwrap();
+}
```

Binary file not shown.

Binary file not shown.

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -25,9 +31,3 @@ macro_rules! println {
$crate::print::_print(format_args_nl!($($arg)*));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -25,9 +31,3 @@ macro_rules! println {
$crate::print::_print(format_args_nl!($($arg)*));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

Binary file not shown.

Binary file not shown.

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -25,9 +31,3 @@ macro_rules! println {
$crate::print::_print(format_args_nl!($($arg)*));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

@ -22,6 +22,12 @@ console and use a real UART now. Like serious embedded hackers do!
- `BSP`s now contain a`memory_map.rs`. In the specific case, they contain the
RPi's MMIO addresses which are used to instantiate compatible device drivers
from `bsp/driver`.
- We also modify the `panic!` handler, so that it does not anymore rely on `println!`, which uses
the globally-shared instance of the `UART` that might be locked when an error is encountered (for
now this can't happen due to the `NullLock`, but with a real lock it becomes an issue).
- Instead, it creates a new UART driver instance, re-initializes the device and uses that one to
print. This increases the chances that the system is able to print a final important message
before it suspends itself.
## Boot it from SD card
@ -40,7 +46,7 @@ init_uart_clock=48000000
3. Copy the following files from the [Raspberry Pi firmware repo](https://github.com/raspberrypi/firmware/tree/master/boot) onto the SD card:
- [bootcode.bin](https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin)
- [fixup.dat](https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat)
- [start.elf](https://github.com/raspberrypi/firmware/raw/master/boot/start.elf)
- [start.elf](https://github.com/raspberrypi/firmware/raw/master/boot/start.elf)
4. Run `make` and copy the [kernel8.img](kernel8.img) onto the SD card.
### Pi 4
@ -281,7 +287,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_gpio.rs 06_drivers_gpio_uar
diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
--- 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
@@ -0,0 +1,308 @@
@@ -0,0 +1,313 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -409,7 +415,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+}
+
+/// The driver's mutex protected part.
+struct PL011UartInner {
+pub struct PL011UartInner {
+ base_addr: usize,
+ chars_written: usize,
+}
@ -433,13 +439,30 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+}
+
+impl PL011UartInner {
+ const fn new(base_addr: usize) -> PL011UartInner {
+ pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
+ PL011UartInner {
+ base_addr,
+ chars_written: 0,
+ }
+ }
+
+ /// Set up baud rate and characteristics.
+ ///
+ /// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
+ /// firmware).
+ pub fn init(&self) {
+ // Turn it off temporarily.
+ self.CR.set(0);
+
+ self.ICR.write(ICR::ALL::CLEAR);
+ self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
+ self.FBRD.write(FBRD::FBRD.val(3));
+ self.LCRH
+ .write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
+ self.CR
+ .write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
+ }
+
+ /// Return a pointer to the register block.
+ fn ptr(&self) -> *const RegisterBlock {
+ self.base_addr as *const _
@ -488,6 +511,11 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+}
+
+//--------------------------------------------------------------------------------------------------
+// Export the inner struct so that BSPs can use it for the panic handler
+//--------------------------------------------------------------------------------------------------
+pub use PL011UartInner as PanicUart;
+
+//--------------------------------------------------------------------------------------------------
+// BSP-public
+//--------------------------------------------------------------------------------------------------
+
@ -517,26 +545,9 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+ "PL011Uart"
+ }
+
+ /// Set up baud rate and characteristics
+ ///
+ /// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
+ /// firmware).
+ fn init(&self) -> interface::driver::Result {
+ let mut r = &self.inner;
+ r.lock(|inner| {
+ // Turn it off temporarily.
+ inner.CR.set(0);
+
+ inner.ICR.write(ICR::ALL::CLEAR);
+ inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
+ inner.FBRD.write(FBRD::FBRD.val(3));
+ inner
+ .LCRH
+ .write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
+ inner
+ .CR
+ .write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
+ });
+ r.lock(|inner| inner.init());
+
+ Ok(())
+ }
@ -605,7 +616,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm.rs 06_drivers_gpio_uart/src/bsp/dri
+mod bcm2xxx_pl011_uart;
+
+pub use bcm2xxx_gpio::GPIO;
+pub use bcm2xxx_pl011_uart::PL011Uart;
+pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};
diff -uNr 05_safe_globals/src/bsp/driver.rs 06_drivers_gpio_uart/src/bsp/driver.rs
--- 05_safe_globals/src/bsp/driver.rs
@ -649,16 +660,16 @@ diff -uNr 05_safe_globals/src/bsp/rpi/memory_map.rs 06_drivers_gpio_uart/src/bsp
diff -uNr 05_safe_globals/src/bsp/rpi.rs 06_drivers_gpio_uart/src/bsp/rpi.rs
--- 05_safe_globals/src/bsp/rpi.rs
+++ 06_drivers_gpio_uart/src/bsp/rpi.rs
@@ -4,114 +4,55 @@
@@ -4,114 +4,68 @@
//! Board Support Package for the Raspberry Pi.
-use crate::{arch::sync::NullLock, interface};
-use core::fmt;
+mod memory_map;
+
+use super::driver;
+use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -752,9 +763,9 @@ diff -uNr 05_safe_globals/src/bsp/rpi.rs 06_drivers_gpio_uart/src/bsp/rpi.rs
+ "Raspberry Pi 3"
}
-}
-
-impl interface::console::Read for QEMUOutput {}
-impl interface::console::Read for QEMUOutput {}
-
-impl interface::console::Statistics for QEMUOutput {
- fn chars_written(&self) -> usize {
- use interface::sync::Mutex;
@ -770,19 +781,27 @@ diff -uNr 05_safe_globals/src/bsp/rpi.rs 06_drivers_gpio_uart/src/bsp/rpi.rs
-//--------------------------------------------------------------------------------------------------
-// Global instances
-//--------------------------------------------------------------------------------------------------
-
+/// Return a reference to a `console::All` implementation.
+pub fn console() -> &'static impl interface::console::All {
+ &PL011_UART
+}
-static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new();
-
+/// In case of a panic, the panic handler uses this function to take a last shot at printing
+/// something before the system is halted.
+///
+/// # Safety
+///
+/// - Use only for printing during a panic.
+pub unsafe fn panic_console_out() -> impl fmt::Write {
+ let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
+ uart.init();
+ uart
+}
-//--------------------------------------------------------------------------------------------------
-// Implementation of the kernel's BSP calls
-//--------------------------------------------------------------------------------------------------
-
/// Return a reference to a `console::All` implementation.
pub fn console() -> &'static impl interface::console::All {
- &QEMU_OUTPUT
+ &PL011_UART
+}
+
+/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
+///
+/// # Safety
@ -791,7 +810,10 @@ diff -uNr 05_safe_globals/src/bsp/rpi.rs 06_drivers_gpio_uart/src/bsp/rpi.rs
+pub fn device_drivers() -> [&'static dyn interface::driver::DeviceDriver; 2] {
+ [&GPIO, &PL011_UART]
+}
+
-/// Return a reference to a `console::All` implementation.
-pub fn console() -> &'static impl interface::console::All {
- &QEMU_OUTPUT
+/// BSP initialization code that runs after driver init.
+pub fn post_driver_init() {
+ // Configure PL011Uart's output pins.
@ -847,7 +869,7 @@ diff -uNr 05_safe_globals/src/interface.rs 06_drivers_gpio_uart/src/interface.rs
diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs
--- 05_safe_globals/src/main.rs
+++ 06_drivers_gpio_uart/src/main.rs
@@ -41,16 +41,50 @@
@@ -41,16 +41,48 @@
/// Early init code.
///
@ -861,13 +883,11 @@ diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs
- use interface::console::Statistics;
+ for i in bsp::device_drivers().iter() {
+ if let Err(()) = i.init() {
+ // This message will only be readable if, at the time of failure, the return value of
+ // `bsp::console()` is already in functioning state.
+ panic!("Error loading driver: {}", i.compatible())
+ }
+ }
+
+ bsp::post_driver_init();
+ // println! is usable from here on.
+
+ // Transition from unsafe to safe.
+ kernel_main()
@ -904,4 +924,44 @@ diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs
+ }
}
diff -uNr 05_safe_globals/src/panic_wait.rs 06_drivers_gpio_uart/src/panic_wait.rs
--- 05_safe_globals/src/panic_wait.rs
+++ 06_drivers_gpio_uart/src/panic_wait.rs
@@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
-use crate::{arch, println};
-use core::panic::PanicInfo;
+use crate::{arch, bsp};
+use core::{fmt, panic::PanicInfo};
+
+fn _panic_print(args: fmt::Arguments) {
+ use fmt::Write;
+
+ unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
+}
+
+/// Prints with a newline - only use from the panic handler.
+///
+/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
+#[macro_export]
+macro_rules! panic_println {
+ ($($arg:tt)*) => ({
+ _panic_print(format_args_nl!($($arg)*));
+ })
+}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
- println!("Kernel panic: {}", args);
+ panic_println!("Kernel panic: {}", args);
} else {
- println!("Kernel panic!");
+ panic_println!("Kernel panic!");
}
arch::wait_forever()
```

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -125,7 +125,7 @@ pub struct RegisterBlock {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -203,6 +220,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}

@ -8,6 +8,7 @@ mod memory_map;
use super::driver;
use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -25,9 +31,3 @@ macro_rules! println {
$crate::print::_print(format_args_nl!($($arg)*));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

@ -162,7 +162,7 @@ diff -uNr 06_drivers_gpio_uart/src/arch/aarch64.rs 07_uart_chainloader/src/arch/
diff -uNr 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
--- 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
@@ -272,6 +272,18 @@
@@ -277,6 +277,18 @@
let mut r = &self.inner;
r.lock(|inner| fmt::Write::write_fmt(inner, args))
}
@ -181,7 +181,7 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 07_uart_
}
impl interface::console::Read for PL011Uart {
@@ -288,14 +300,19 @@
@@ -293,14 +305,19 @@
}
// Read one character.
@ -243,7 +243,7 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/rpi/link.ld 07_uart_chainloader/src/bsp/r
diff -uNr 06_drivers_gpio_uart/src/bsp/rpi.rs 07_uart_chainloader/src/bsp/rpi.rs
--- 06_drivers_gpio_uart/src/bsp/rpi.rs
+++ 07_uart_chainloader/src/bsp/rpi.rs
@@ -12,6 +12,9 @@
@@ -13,6 +13,9 @@
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -295,7 +295,7 @@ diff -uNr 06_drivers_gpio_uart/src/main.rs 07_uart_chainloader/src/main.rs
mod runtime_init;
// Conditionally includes the selected `BSP` code.
@@ -66,25 +70,48 @@
@@ -64,25 +68,48 @@
fn kernel_main() -> ! {
use interface::console::All;

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -125,7 +125,7 @@ pub struct RegisterBlock {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -203,6 +220,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}

@ -8,6 +8,7 @@ mod memory_map;
use super::driver;
use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -45,6 +46,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -54,13 +54,11 @@ mod print;
unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -25,9 +31,3 @@ macro_rules! println {
$crate::print::_print(format_args_nl!($($arg)*));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

@ -231,7 +231,7 @@ diff -uNr 07_uart_chainloader/src/arch/aarch64.rs 08_timestamps/src/arch/aarch64
diff -uNr 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 08_timestamps/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
--- 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 08_timestamps/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
@@ -300,7 +300,14 @@
@@ -305,7 +305,14 @@
}
// Read one character.
@ -283,7 +283,7 @@ diff -uNr 07_uart_chainloader/src/bsp/rpi/link.ld 08_timestamps/src/bsp/rpi/link
diff -uNr 07_uart_chainloader/src/bsp/rpi.rs 08_timestamps/src/bsp/rpi.rs
--- 07_uart_chainloader/src/bsp/rpi.rs
+++ 08_timestamps/src/bsp/rpi.rs
@@ -12,9 +12,6 @@
@@ -13,9 +13,6 @@
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -337,7 +337,7 @@ diff -uNr 07_uart_chainloader/src/main.rs 08_timestamps/src/main.rs
mod runtime_init;
// Conditionally includes the selected `BSP` code.
@@ -68,50 +64,25 @@
@@ -66,50 +62,25 @@
/// The main function running after the early init.
fn kernel_main() -> ! {
@ -409,7 +409,7 @@ diff -uNr 07_uart_chainloader/src/main.rs 08_timestamps/src/main.rs
diff -uNr 07_uart_chainloader/src/print.rs 08_timestamps/src/print.rs
--- 07_uart_chainloader/src/print.rs
+++ 08_timestamps/src/print.rs
@@ -16,13 +16,71 @@
@@ -22,12 +22,70 @@
}
/// Prints with a newline.
@ -485,7 +485,6 @@ diff -uNr 07_uart_chainloader/src/print.rs 08_timestamps/src/print.rs
})
}
diff -uNr 07_uart_chainloader/src/relocate.rs 08_timestamps/src/relocate.rs
--- 07_uart_chainloader/src/relocate.rs
+++ 08_timestamps/src/relocate.rs

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -125,7 +125,7 @@ pub struct RegisterBlock {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -203,6 +220,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}

@ -8,6 +8,7 @@ mod memory_map;
use super::driver;
use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -83,9 +89,3 @@ macro_rules! warn {
));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -125,7 +125,7 @@ pub struct RegisterBlock {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -203,6 +220,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}

@ -8,6 +8,7 @@ mod memory_map;
use super::driver;
use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -83,9 +89,3 @@ macro_rules! warn {
));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

@ -371,7 +371,7 @@ diff -uNr 09_hw_debug_JTAG/src/arch/aarch64.rs 10_privilege_level/src/arch/aarch
diff -uNr 09_hw_debug_JTAG/src/main.rs 10_privilege_level/src/main.rs
--- 09_hw_debug_JTAG/src/main.rs
+++ 10_privilege_level/src/main.rs
@@ -65,9 +65,17 @@
@@ -63,9 +63,17 @@
/// The main function running after the early init.
fn kernel_main() -> ! {
use core::time::Duration;
@ -390,7 +390,7 @@ diff -uNr 09_hw_debug_JTAG/src/main.rs 10_privilege_level/src/main.rs
println!(
"Architectural timer resolution: {} ns",
arch::timer().resolution().as_nanos()
@@ -78,11 +86,12 @@
@@ -76,11 +84,12 @@
println!(" {}. {}", i + 1, driver.compatible());
}

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -125,7 +125,7 @@ pub struct RegisterBlock {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -203,6 +220,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}

@ -8,6 +8,7 @@ mod memory_map;
use super::driver;
use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -83,9 +89,3 @@ macro_rules! warn {
));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

@ -239,25 +239,24 @@ make chainbot
### finished sending
[ML] Loaded! Executing the payload now
[ 5.732854] Booting on: Raspberry Pi 3
[ 5.792441] MMU online
[ 5.793306] Special memory regions:
[ 5.796778] 0x00080000 - 0x0008FFFF | 64 KiB | C RO PX | Kernel code and RO data
[ 5.805026] 0x1FFF0000 - 0x1FFFFFFF | 64 KiB | Dev RW PXN | Remapped Device MMIO
[ 5.813014] 0x3F000000 - 0x3FFFFFFF | 16 MiB | Dev RW PXN | Device MMIO
[ 5.820220] Current privilege level: EL1
[ 5.824127] Exception handling state:
[ 5.827774] Debug: Masked
[ 5.830986] SError: Masked
[ 5.834199] IRQ: Masked
[ 5.837412] FIQ: Masked
[ 5.840624] Architectural timer resolution: 52 ns
[ 5.845312] Drivers loaded:
[ 5.848091] 1. GPIO
[ 5.850695] 2. PL011Uart
[ 5.853734] Timer test, spinning for 1 second
[ 5.791515] Booting on: Raspberry Pi 3
[ 5.793767] MMU online. Special regions:
[ 5.797674] 0x00080000 - 0x0008FFFF | 64 KiB | C RO PX | Kernel code and RO data
[ 5.805922] 0x1FFF0000 - 0x1FFFFFFF | 64 KiB | Dev RW PXN | Remapped Device MMIO
[ 5.813910] 0x3F000000 - 0x3FFFFFFF | 16 MiB | Dev RW PXN | Device MMIO
[ 5.821117] Current privilege level: EL1
[ 5.825024] Exception handling state:
[ 5.828670] Debug: Masked
[ 5.831883] SError: Masked
[ 5.835095] IRQ: Masked
[ 5.838308] FIQ: Masked
[ 5.841520] Architectural timer resolution: 52 ns
[ 5.846209] Drivers loaded:
[ 5.848987] 1. GPIO
[ 5.851592] 2. PL011Uart
[ 5.854630] Timer test, spinning for 1 second
[ !!! ] Writing through the remapped UART at 0x1FFF_1000
[ 6.862236] Echoing input now
[ 6.863133] Echoing input now
```
## Diff to previous
@ -547,7 +546,7 @@ diff -uNr 10_privilege_level/src/arch/aarch64/mmu.rs 11_virtual_memory/src/arch/
+pub unsafe fn init() -> Result<(), &'static str> {
+ // Fail early if translation granule is not supported. Both RPis support it, though.
+ if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) {
+ return Err("MMU does not support 64 KiB translation granule");
+ return Err("64 KiB translation granule not supported");
+ }
+
+ // Prepare the memory attribute indirection register.
@ -730,10 +729,10 @@ diff -uNr 10_privilege_level/src/bsp/rpi.rs 11_virtual_memory/src/bsp/rpi.rs
use super::driver;
-use crate::interface;
+use crate::{interface, memory::KernelVirtualLayout};
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@@ -56,3 +57,13 @@
@@ -69,3 +70,13 @@
// Configure PL011Uart's output pins.
GPIO.map_pl011_uart();
}
@ -781,38 +780,35 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
mod panic_wait;
mod print;
@@ -48,6 +51,7 @@
@@ -46,8 +49,16 @@
/// # Safety
///
/// - Only a single core must be active and running this function.
/// - The init calls in this function must appear in the correct order.
-/// - The init calls in this function must appear in the correct order.
+/// - The init calls in this function must appear in the correct order:
+/// - Virtual memory must be activated first.
+/// - Without it, any atomic operations, e.g. the yet-to-be-introduced spinlocks in the device
+/// drivers (which currently employ NullLocks instead of spinlocks), will fail to work on
+/// the RPi SoCs.
unsafe fn kernel_init() -> ! {
+ // Bring up device drivers first, so that eventual MMU errors can be printed.
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
@@ -58,6 +62,13 @@
bsp::post_driver_init();
+ println!("Booting on: {}", bsp::board_name());
+
+ if let Err(string) = arch::mmu::init() {
+ panic!("MMU: {}", string);
+ }
+ println!("MMU online");
+
// Transition from unsafe to safe.
kernel_main()
}
@@ -67,7 +78,7 @@
use core::time::Duration;
use interface::{console::All, time::Timer};
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
panic!("Error loading driver: {}", i.compatible())
@@ -67,6 +78,9 @@
- println!("Booting on: {}", bsp::board_name());
+ bsp::virt_mem_layout().print_layout();
println!("Booting on: {}", bsp::board_name());
+ println!("MMU online. Special regions:");
+ bsp::virt_mem_layout().print_layout();
+
println!(
"Current privilege level: {}",
@@ -89,6 +100,13 @@
arch::state::current_privilege_level()
@@ -87,6 +101,13 @@
println!("Timer test, spinning for 1 second");
arch::timer().spin_for(Duration::from_secs(1));
@ -830,7 +826,7 @@ diff -uNr 10_privilege_level/src/main.rs 11_virtual_memory/src/main.rs
diff -uNr 10_privilege_level/src/memory.rs 11_virtual_memory/src/memory.rs
--- 10_privilege_level/src/memory.rs
+++ 11_virtual_memory/src/memory.rs
@@ -0,0 +1,149 @@
@@ -0,0 +1,147 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
@ -973,8 +969,6 @@ diff -uNr 10_privilege_level/src/memory.rs 11_virtual_memory/src/memory.rs
+ pub fn print_layout(&self) {
+ use crate::println;
+
+ println!("Special memory regions:");
+
+ for i in self.inner.iter() {
+ println!("{}", i);
+ }

Binary file not shown.

Binary file not shown.

@ -278,7 +278,7 @@ fn configure_translation_control() {
pub unsafe fn init() -> Result<(), &'static str> {
// Fail early if translation granule is not supported. Both RPis support it, though.
if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) {
return Err("MMU does not support 64 KiB translation granule");
return Err("64 KiB translation granule not supported");
}
// Prepare the memory attribute indirection register.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO;
pub use bcm2xxx_pl011_uart::PL011Uart;
pub use bcm2xxx_pl011_uart::{PL011Uart, PanicUart};

@ -125,7 +125,7 @@ pub struct RegisterBlock {
}
/// The driver's mutex protected part.
struct PL011UartInner {
pub struct PL011UartInner {
base_addr: usize,
chars_written: usize,
}
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
}
impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner {
pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner {
base_addr,
chars_written: 0,
}
}
/// Set up baud rate and characteristics.
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
pub fn init(&self) {
// Turn it off temporarily.
self.CR.set(0);
self.ICR.write(ICR::ALL::CLEAR);
self.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
self.FBRD.write(FBRD::FBRD.val(3));
self.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
self.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
}
/// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
@ -203,6 +220,11 @@ impl fmt::Write for PL011UartInner {
}
}
//--------------------------------------------------------------------------------------------------
// Export the inner struct so that BSPs can use it for the panic handler
//--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart;
//--------------------------------------------------------------------------------------------------
// BSP-public
//--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"PL011Uart"
}
/// Set up baud rate and characteristics
///
/// Results in 8N1 and 115200 baud (if the clk has been previously set to 4 MHz by the
/// firmware).
fn init(&self) -> interface::driver::Result {
let mut r = &self.inner;
r.lock(|inner| {
// Turn it off temporarily.
inner.CR.set(0);
inner.ICR.write(ICR::ALL::CLEAR);
inner.IBRD.write(IBRD::IBRD.val(26)); // Results in 115200 baud for UART Clk of 48 MHz.
inner.FBRD.write(FBRD::FBRD.val(3));
inner
.LCRH
.write(LCRH::WLEN::EightBit + LCRH::FEN::FifosEnabled); // 8N1 + Fifo on
inner
.CR
.write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled);
});
r.lock(|inner| inner.init());
Ok(())
}

@ -9,6 +9,7 @@ mod virt_mem_layout;
use super::driver;
use crate::{interface, memory::KernelVirtualLayout};
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -43,6 +44,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART
}
/// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted.
///
/// # Safety
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let uart = driver::PanicUart::new(memory_map::mmio::PL011_UART_BASE);
uart.init();
uart
}
/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
///
/// # Safety

@ -49,25 +49,23 @@ mod print;
/// # Safety
///
/// - Only a single core must be active and running this function.
/// - The init calls in this function must appear in the correct order.
/// - The init calls in this function must appear in the correct order:
/// - Virtual memory must be activated first.
/// - Without it, any atomic operations, e.g. the yet-to-be-introduced spinlocks in the device
/// drivers (which currently employ NullLocks instead of spinlocks), will fail to work on
/// the RPi SoCs.
unsafe fn kernel_init() -> ! {
// Bring up device drivers first, so that eventual MMU errors can be printed.
if let Err(string) = arch::mmu::init() {
panic!("MMU: {}", string);
}
for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() {
// This message will only be readable if, at the time of failure, the return value of
// `bsp::console()` is already in functioning state.
panic!("Error loading driver: {}", i.compatible())
}
}
bsp::post_driver_init();
println!("Booting on: {}", bsp::board_name());
if let Err(string) = arch::mmu::init() {
panic!("MMU: {}", string);
}
println!("MMU online");
// println! is usable from here on.
// Transition from unsafe to safe.
kernel_main()
@ -78,6 +76,9 @@ fn kernel_main() -> ! {
use core::time::Duration;
use interface::{console::All, time::Timer};
println!("Booting on: {}", bsp::board_name());
println!("MMU online. Special regions:");
bsp::virt_mem_layout().print_layout();
println!(

@ -140,8 +140,6 @@ impl<const NUM_SPECIAL_RANGES: usize> KernelVirtualLayout<{ NUM_SPECIAL_RANGES }
pub fn print_layout(&self) {
use crate::println;
println!("Special memory regions:");
for i in self.inner.iter() {
println!("{}", i);
}

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits.
use crate::{arch, println};
use core::panic::PanicInfo;
use crate::{arch, bsp};
use core::{fmt, panic::PanicInfo};
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
#[panic_handler]
fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() {
println!("Kernel panic: {}", args);
panic_println!("Kernel panic: {}", args);
} else {
println!("Kernel panic!");
panic_println!("Kernel panic!");
}
arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface};
use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline.
///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html
@ -83,9 +89,3 @@ macro_rules! warn {
));
})
}
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}

Loading…
Cancel
Save