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 crate::{bsp, interface};
+use core::fmt; +use core::fmt;
+ +
+pub fn _print(args: fmt::Arguments) {
+ use interface::console::Write;
+
+ bsp::console().write_fmt(args).unwrap();
+}
+
+/// Prints without a newline. +/// Prints without a newline.
+/// +///
+/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html +/// 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)*)); + $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 crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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)*)); $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 crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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)*)); $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 crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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)*)); $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 - `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 RPi's MMIO addresses which are used to instantiate compatible device drivers
from `bsp/driver`. 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 ## 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: 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) - [bootcode.bin](https://github.com/raspberrypi/firmware/raw/master/boot/bootcode.bin)
- [fixup.dat](https://github.com/raspberrypi/firmware/raw/master/boot/fixup.dat) - [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. 4. Run `make` and copy the [kernel8.img](kernel8.img) onto the SD card.
### Pi 4 ### 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 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 --- 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 06_drivers_gpio_uart/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 +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// 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. +/// The driver's mutex protected part.
+struct PL011UartInner { +pub struct PL011UartInner {
+ base_addr: usize, + base_addr: usize,
+ chars_written: 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 { +impl PL011UartInner {
+ const fn new(base_addr: usize) -> PL011UartInner { + pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
+ PL011UartInner { + PL011UartInner {
+ base_addr, + base_addr,
+ chars_written: 0, + 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. + /// Return a pointer to the register block.
+ fn ptr(&self) -> *const RegisterBlock { + fn ptr(&self) -> *const RegisterBlock {
+ self.base_addr as *const _ + 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 +// BSP-public
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
@ -517,26 +545,9 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs 06_drivers_gp
+ "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 { + fn init(&self) -> interface::driver::Result {
+ let mut r = &self.inner; + let mut r = &self.inner;
+ r.lock(|inner| { + r.lock(|inner| inner.init());
+ // 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);
+ });
+ +
+ Ok(()) + 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; +mod bcm2xxx_pl011_uart;
+ +
+pub use bcm2xxx_gpio::GPIO; +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 diff -uNr 05_safe_globals/src/bsp/driver.rs 06_drivers_gpio_uart/src/bsp/driver.rs
--- 05_safe_globals/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 diff -uNr 05_safe_globals/src/bsp/rpi.rs 06_drivers_gpio_uart/src/bsp/rpi.rs
--- 05_safe_globals/src/bsp/rpi.rs --- 05_safe_globals/src/bsp/rpi.rs
+++ 06_drivers_gpio_uart/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. //! Board Support Package for the Raspberry Pi.
-use crate::{arch::sync::NullLock, interface}; -use crate::{arch::sync::NullLock, interface};
-use core::fmt;
+mod memory_map; +mod memory_map;
+ +
+use super::driver; +use super::driver;
+use crate::interface; +use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; 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" + "Raspberry Pi 3"
} }
-} -}
-
-impl interface::console::Read for QEMUOutput {}
-impl interface::console::Read for QEMUOutput {}
-
-impl interface::console::Statistics for QEMUOutput { -impl interface::console::Statistics for QEMUOutput {
- fn chars_written(&self) -> usize { - fn chars_written(&self) -> usize {
- use interface::sync::Mutex; - 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 -// 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(); -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 -// 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. +/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
+/// +///
+/// # Safety +/// # 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] { +pub fn device_drivers() -> [&'static dyn interface::driver::DeviceDriver; 2] {
+ [&GPIO, &PL011_UART] + [&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. +/// BSP initialization code that runs after driver init.
+pub fn post_driver_init() { +pub fn post_driver_init() {
+ // Configure PL011Uart's output pins. + // 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 diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs
--- 05_safe_globals/src/main.rs --- 05_safe_globals/src/main.rs
+++ 06_drivers_gpio_uart/src/main.rs +++ 06_drivers_gpio_uart/src/main.rs
@@ -41,16 +41,50 @@ @@ -41,16 +41,48 @@
/// Early init code. /// 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; - use interface::console::Statistics;
+ for i in bsp::device_drivers().iter() { + for i in bsp::device_drivers().iter() {
+ if let Err(()) = i.init() { + 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()) + panic!("Error loading driver: {}", i.compatible())
+ } + }
+ } + }
+
+ bsp::post_driver_init(); + bsp::post_driver_init();
+ // println! is usable from here on.
+ +
+ // Transition from unsafe to safe. + // Transition from unsafe to safe.
+ kernel_main() + 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; mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO; 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. /// The driver's mutex protected part.
struct PL011UartInner { pub struct PL011UartInner {
base_addr: usize, base_addr: usize,
chars_written: usize, chars_written: usize,
} }
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
} }
impl PL011UartInner { impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner { pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner { PL011UartInner {
base_addr, base_addr,
chars_written: 0, 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. /// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock { fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _ 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 // BSP-public
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"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 { fn init(&self) -> interface::driver::Result {
let mut r = &self.inner; let mut r = &self.inner;
r.lock(|inner| { r.lock(|inner| inner.init());
// 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);
});
Ok(()) Ok(())
} }

@ -8,6 +8,7 @@ mod memory_map;
use super::driver; use super::driver;
use crate::interface; use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART &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. /// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
/// ///
/// # Safety /// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { 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()) panic!("Error loading driver: {}", i.compatible())
} }
} }
bsp::post_driver_init(); bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe. // Transition from unsafe to safe.
kernel_main() kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{arch, println}; use crate::{arch, bsp};
use core::panic::PanicInfo; 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] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() { if let Some(args) = info.message() {
println!("Kernel panic: {}", args); panic_println!("Kernel panic: {}", args);
} else { } else {
println!("Kernel panic!"); panic_println!("Kernel panic!");
} }
arch::wait_forever() arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface}; use crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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)*)); $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 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 --- 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 07_uart_chainloader/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; let mut r = &self.inner;
r.lock(|inner| fmt::Write::write_fmt(inner, args)) 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 { impl interface::console::Read for PL011Uart {
@@ -288,14 +300,19 @@ @@ -293,14 +305,19 @@
} }
// Read one character. // 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 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 --- 06_drivers_gpio_uart/src/bsp/rpi.rs
+++ 07_uart_chainloader/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_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; 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; mod runtime_init;
// Conditionally includes the selected `BSP` code. // Conditionally includes the selected `BSP` code.
@@ -66,25 +70,48 @@ @@ -64,25 +68,48 @@
fn kernel_main() -> ! { fn kernel_main() -> ! {
use interface::console::All; use interface::console::All;

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart; mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO; 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. /// The driver's mutex protected part.
struct PL011UartInner { pub struct PL011UartInner {
base_addr: usize, base_addr: usize,
chars_written: usize, chars_written: usize,
} }
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
} }
impl PL011UartInner { impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner { pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner { PL011UartInner {
base_addr, base_addr,
chars_written: 0, 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. /// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock { fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _ 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 // BSP-public
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"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 { fn init(&self) -> interface::driver::Result {
let mut r = &self.inner; let mut r = &self.inner;
r.lock(|inner| { r.lock(|inner| inner.init());
// 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);
});
Ok(()) Ok(())
} }

@ -8,6 +8,7 @@ mod memory_map;
use super::driver; use super::driver;
use crate::interface; use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -45,6 +46,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART &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. /// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
/// ///
/// # Safety /// # Safety

@ -54,13 +54,11 @@ mod print;
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { 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()) panic!("Error loading driver: {}", i.compatible())
} }
} }
bsp::post_driver_init(); bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe. // Transition from unsafe to safe.
kernel_main() kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{arch, println}; use crate::{arch, bsp};
use core::panic::PanicInfo; 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] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() { if let Some(args) = info.message() {
println!("Kernel panic: {}", args); panic_println!("Kernel panic: {}", args);
} else { } else {
println!("Kernel panic!"); panic_println!("Kernel panic!");
} }
arch::wait_forever() arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface}; use crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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)*)); $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 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 --- 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_pl011_uart.rs
+++ 08_timestamps/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. // 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 diff -uNr 07_uart_chainloader/src/bsp/rpi.rs 08_timestamps/src/bsp/rpi.rs
--- 07_uart_chainloader/src/bsp/rpi.rs --- 07_uart_chainloader/src/bsp/rpi.rs
+++ 08_timestamps/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_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; 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; mod runtime_init;
// Conditionally includes the selected `BSP` code. // Conditionally includes the selected `BSP` code.
@@ -68,50 +64,25 @@ @@ -66,50 +62,25 @@
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { 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 diff -uNr 07_uart_chainloader/src/print.rs 08_timestamps/src/print.rs
--- 07_uart_chainloader/src/print.rs --- 07_uart_chainloader/src/print.rs
+++ 08_timestamps/src/print.rs +++ 08_timestamps/src/print.rs
@@ -16,13 +16,71 @@ @@ -22,12 +22,70 @@
} }
/// Prints with a newline. /// 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 diff -uNr 07_uart_chainloader/src/relocate.rs 08_timestamps/src/relocate.rs
--- 07_uart_chainloader/src/relocate.rs --- 07_uart_chainloader/src/relocate.rs
+++ 08_timestamps/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; mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO; 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. /// The driver's mutex protected part.
struct PL011UartInner { pub struct PL011UartInner {
base_addr: usize, base_addr: usize,
chars_written: usize, chars_written: usize,
} }
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
} }
impl PL011UartInner { impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner { pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner { PL011UartInner {
base_addr, base_addr,
chars_written: 0, 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. /// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock { fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _ 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 // BSP-public
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"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 { fn init(&self) -> interface::driver::Result {
let mut r = &self.inner; let mut r = &self.inner;
r.lock(|inner| { r.lock(|inner| inner.init());
// 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);
});
Ok(()) Ok(())
} }

@ -8,6 +8,7 @@ mod memory_map;
use super::driver; use super::driver;
use crate::interface; use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART &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. /// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
/// ///
/// # Safety /// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { 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()) panic!("Error loading driver: {}", i.compatible())
} }
} }
bsp::post_driver_init(); bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe. // Transition from unsafe to safe.
kernel_main() kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{arch, println}; use crate::{arch, bsp};
use core::panic::PanicInfo; 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] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() { if let Some(args) = info.message() {
println!("Kernel panic: {}", args); panic_println!("Kernel panic: {}", args);
} else { } else {
println!("Kernel panic!"); panic_println!("Kernel panic!");
} }
arch::wait_forever() arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface}; use crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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; mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO; 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. /// The driver's mutex protected part.
struct PL011UartInner { pub struct PL011UartInner {
base_addr: usize, base_addr: usize,
chars_written: usize, chars_written: usize,
} }
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
} }
impl PL011UartInner { impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner { pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner { PL011UartInner {
base_addr, base_addr,
chars_written: 0, 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. /// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock { fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _ 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 // BSP-public
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"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 { fn init(&self) -> interface::driver::Result {
let mut r = &self.inner; let mut r = &self.inner;
r.lock(|inner| { r.lock(|inner| inner.init());
// 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);
});
Ok(()) Ok(())
} }

@ -8,6 +8,7 @@ mod memory_map;
use super::driver; use super::driver;
use crate::interface; use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART &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. /// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
/// ///
/// # Safety /// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { 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()) panic!("Error loading driver: {}", i.compatible())
} }
} }
bsp::post_driver_init(); bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe. // Transition from unsafe to safe.
kernel_main() kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{arch, println}; use crate::{arch, bsp};
use core::panic::PanicInfo; 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] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() { if let Some(args) = info.message() {
println!("Kernel panic: {}", args); panic_println!("Kernel panic: {}", args);
} else { } else {
println!("Kernel panic!"); panic_println!("Kernel panic!");
} }
arch::wait_forever() arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface}; use crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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 diff -uNr 09_hw_debug_JTAG/src/main.rs 10_privilege_level/src/main.rs
--- 09_hw_debug_JTAG/src/main.rs --- 09_hw_debug_JTAG/src/main.rs
+++ 10_privilege_level/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. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use core::time::Duration; use core::time::Duration;
@ -390,7 +390,7 @@ diff -uNr 09_hw_debug_JTAG/src/main.rs 10_privilege_level/src/main.rs
println!( println!(
"Architectural timer resolution: {} ns", "Architectural timer resolution: {} ns",
arch::timer().resolution().as_nanos() arch::timer().resolution().as_nanos()
@@ -78,11 +86,12 @@ @@ -76,11 +84,12 @@
println!(" {}. {}", i + 1, driver.compatible()); println!(" {}. {}", i + 1, driver.compatible());
} }

Binary file not shown.

Binary file not shown.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart; mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO; 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. /// The driver's mutex protected part.
struct PL011UartInner { pub struct PL011UartInner {
base_addr: usize, base_addr: usize,
chars_written: usize, chars_written: usize,
} }
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
} }
impl PL011UartInner { impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner { pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner { PL011UartInner {
base_addr, base_addr,
chars_written: 0, 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. /// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock { fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _ 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 // BSP-public
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"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 { fn init(&self) -> interface::driver::Result {
let mut r = &self.inner; let mut r = &self.inner;
r.lock(|inner| { r.lock(|inner| inner.init());
// 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);
});
Ok(()) Ok(())
} }

@ -8,6 +8,7 @@ mod memory_map;
use super::driver; use super::driver;
use crate::interface; use crate::interface;
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -42,6 +43,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART &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. /// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
/// ///
/// # Safety /// # Safety

@ -50,13 +50,11 @@ mod print;
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
for i in bsp::device_drivers().iter() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { 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()) panic!("Error loading driver: {}", i.compatible())
} }
} }
bsp::post_driver_init(); bsp::post_driver_init();
// println! is usable from here on.
// Transition from unsafe to safe. // Transition from unsafe to safe.
kernel_main() kernel_main()

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{arch, println}; use crate::{arch, bsp};
use core::panic::PanicInfo; 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] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() { if let Some(args) = info.message() {
println!("Kernel panic: {}", args); panic_println!("Kernel panic: {}", args);
} else { } else {
println!("Kernel panic!"); panic_println!("Kernel panic!");
} }
arch::wait_forever() arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface}; use crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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 ### finished sending
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 5.732854] Booting on: Raspberry Pi 3 [ 5.791515] Booting on: Raspberry Pi 3
[ 5.792441] MMU online [ 5.793767] MMU online. Special regions:
[ 5.793306] Special memory regions: [ 5.797674] 0x00080000 - 0x0008FFFF | 64 KiB | C RO PX | Kernel code and RO data
[ 5.796778] 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.805026] 0x1FFF0000 - 0x1FFFFFFF | 64 KiB | Dev RW PXN | Remapped Device MMIO [ 5.813910] 0x3F000000 - 0x3FFFFFFF | 16 MiB | Dev RW PXN | Device MMIO
[ 5.813014] 0x3F000000 - 0x3FFFFFFF | 16 MiB | Dev RW PXN | Device MMIO [ 5.821117] Current privilege level: EL1
[ 5.820220] Current privilege level: EL1 [ 5.825024] Exception handling state:
[ 5.824127] Exception handling state: [ 5.828670] Debug: Masked
[ 5.827774] Debug: Masked [ 5.831883] SError: Masked
[ 5.830986] SError: Masked [ 5.835095] IRQ: Masked
[ 5.834199] IRQ: Masked [ 5.838308] FIQ: Masked
[ 5.837412] FIQ: Masked [ 5.841520] Architectural timer resolution: 52 ns
[ 5.840624] Architectural timer resolution: 52 ns [ 5.846209] Drivers loaded:
[ 5.845312] Drivers loaded: [ 5.848987] 1. GPIO
[ 5.848091] 1. GPIO [ 5.851592] 2. PL011Uart
[ 5.850695] 2. PL011Uart [ 5.854630] Timer test, spinning for 1 second
[ 5.853734] Timer test, spinning for 1 second
[ !!! ] Writing through the remapped UART at 0x1FFF_1000 [ !!! ] Writing through the remapped UART at 0x1FFF_1000
[ 6.862236] Echoing input now [ 6.863133] Echoing input now
``` ```
## Diff to previous ## 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> { +pub unsafe fn init() -> Result<(), &'static str> {
+ // Fail early if translation granule is not supported. Both RPis support it, though. + // Fail early if translation granule is not supported. Both RPis support it, though.
+ if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) { + 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. + // 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 super::driver;
-use crate::interface; -use crate::interface;
+use crate::{interface, memory::KernelVirtualLayout}; +use crate::{interface, memory::KernelVirtualLayout};
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; @@ -69,3 +70,13 @@
@@ -56,3 +57,13 @@
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
GPIO.map_pl011_uart(); 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 panic_wait;
mod print; mod print;
@@ -48,6 +51,7 @@ @@ -46,8 +49,16 @@
/// # Safety
///
/// - Only a single core must be active and running this function. /// - 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() -> ! { 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() { + if let Err(string) = arch::mmu::init() {
+ panic!("MMU: {}", string); + panic!("MMU: {}", string);
+ } + }
+ println!("MMU online");
+ +
// Transition from unsafe to safe. for i in bsp::device_drivers().iter() {
kernel_main() if let Err(()) = i.init() {
} panic!("Error loading driver: {}", i.compatible())
@@ -67,7 +78,7 @@ @@ -67,6 +78,9 @@
use core::time::Duration;
use interface::{console::All, time::Timer};
- println!("Booting on: {}", bsp::board_name()); println!("Booting on: {}", bsp::board_name());
+ bsp::virt_mem_layout().print_layout();
+ println!("MMU online. Special regions:");
+ bsp::virt_mem_layout().print_layout();
+
println!( println!(
"Current privilege level: {}", "Current privilege level: {}",
@@ -89,6 +100,13 @@ arch::state::current_privilege_level()
@@ -87,6 +101,13 @@
println!("Timer test, spinning for 1 second"); println!("Timer test, spinning for 1 second");
arch::timer().spin_for(Duration::from_secs(1)); 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 diff -uNr 10_privilege_level/src/memory.rs 11_virtual_memory/src/memory.rs
--- 10_privilege_level/src/memory.rs --- 10_privilege_level/src/memory.rs
+++ 11_virtual_memory/src/memory.rs +++ 11_virtual_memory/src/memory.rs
@@ -0,0 +1,149 @@ @@ -0,0 +1,147 @@
+// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT
+// +//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com> +// 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) { + pub fn print_layout(&self) {
+ use crate::println; + use crate::println;
+ +
+ println!("Special memory regions:");
+
+ for i in self.inner.iter() { + for i in self.inner.iter() {
+ println!("{}", i); + 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> { pub unsafe fn init() -> Result<(), &'static str> {
// Fail early if translation granule is not supported. Both RPis support it, though. // Fail early if translation granule is not supported. Both RPis support it, though.
if !ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran64::Supported) { 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. // Prepare the memory attribute indirection register.

@ -8,4 +8,4 @@ mod bcm2xxx_gpio;
mod bcm2xxx_pl011_uart; mod bcm2xxx_pl011_uart;
pub use bcm2xxx_gpio::GPIO; 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. /// The driver's mutex protected part.
struct PL011UartInner { pub struct PL011UartInner {
base_addr: usize, base_addr: usize,
chars_written: usize, chars_written: usize,
} }
@ -149,13 +149,30 @@ impl ops::Deref for PL011UartInner {
} }
impl PL011UartInner { impl PL011UartInner {
const fn new(base_addr: usize) -> PL011UartInner { pub const unsafe fn new(base_addr: usize) -> PL011UartInner {
PL011UartInner { PL011UartInner {
base_addr, base_addr,
chars_written: 0, 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. /// Return a pointer to the register block.
fn ptr(&self) -> *const RegisterBlock { fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _ 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 // BSP-public
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -233,26 +255,9 @@ impl interface::driver::DeviceDriver for PL011Uart {
"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 { fn init(&self) -> interface::driver::Result {
let mut r = &self.inner; let mut r = &self.inner;
r.lock(|inner| { r.lock(|inner| inner.init());
// 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);
});
Ok(()) Ok(())
} }

@ -9,6 +9,7 @@ mod virt_mem_layout;
use super::driver; use super::driver;
use crate::{interface, memory::KernelVirtualLayout}; use crate::{interface, memory::KernelVirtualLayout};
use core::fmt;
pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000; pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
@ -43,6 +44,18 @@ pub fn console() -> &'static impl interface::console::All {
&PL011_UART &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. /// Return an array of references to all `DeviceDriver` compatible `BSP` drivers.
/// ///
/// # Safety /// # Safety

@ -49,25 +49,23 @@ mod print;
/// # Safety /// # Safety
/// ///
/// - Only a single core must be active and running this function. /// - 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() -> ! { 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() { for i in bsp::device_drivers().iter() {
if let Err(()) = i.init() { 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()) panic!("Error loading driver: {}", i.compatible())
} }
} }
bsp::post_driver_init(); bsp::post_driver_init();
// println! is usable from here on.
println!("Booting on: {}", bsp::board_name());
if let Err(string) = arch::mmu::init() {
panic!("MMU: {}", string);
}
println!("MMU online");
// Transition from unsafe to safe. // Transition from unsafe to safe.
kernel_main() kernel_main()
@ -78,6 +76,9 @@ fn kernel_main() -> ! {
use core::time::Duration; use core::time::Duration;
use interface::{console::All, time::Timer}; use interface::{console::All, time::Timer};
println!("Booting on: {}", bsp::board_name());
println!("MMU online. Special regions:");
bsp::virt_mem_layout().print_layout(); bsp::virt_mem_layout().print_layout();
println!( println!(

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

@ -4,15 +4,31 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{arch, println}; use crate::{arch, bsp};
use core::panic::PanicInfo; 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] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
if let Some(args) = info.message() { if let Some(args) = info.message() {
println!("Kernel panic: {}", args); panic_println!("Kernel panic: {}", args);
} else { } else {
println!("Kernel panic!"); panic_println!("Kernel panic!");
} }
arch::wait_forever() arch::wait_forever()

@ -7,6 +7,12 @@
use crate::{bsp, interface}; use crate::{bsp, interface};
use core::fmt; use core::fmt;
pub fn _print(args: fmt::Arguments) {
use interface::console::Write;
bsp::console().write_fmt(args).unwrap();
}
/// Prints without a newline. /// Prints without a newline.
/// ///
/// Carbon copy from https://doc.rust-lang.org/src/std/macros.rs.html /// 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