Add a panic version of the GPIO to panic!()

pull/84/head
Andre Richter 4 years ago
parent 95c67afda2
commit 677b274a1f
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -19,7 +19,7 @@ executing the kernel code.
## Code to look at ## Code to look at
- Custom `link.ld` linker script. - Custom `link.ld` linker script.
- Load address at `0x80_000` - Load address at `0x8_0000`
- Only `.text` section. - Only `.text` section.
- `main.rs`: Important [inner attributes]: - `main.rs`: Important [inner attributes]:
- `#![no_std]`, `#![no_main]` - `#![no_std]`, `#![no_main]`

@ -133,7 +133,7 @@ diff -uNr 05_safe_globals/src/_arch/aarch64/cpu.rs 06_drivers_gpio_uart/src/_arc
diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
--- 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs --- 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
+++ 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ 06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
@@ -0,0 +1,138 @@ @@ -0,0 +1,161 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
@ -215,24 +215,31 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+// Public Definitions +// Public Definitions
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
+pub struct GPIOInner {
+ registers: Registers,
+}
+
+// Export the inner struct so that BSPs can use it for the panic handler.
+pub use GPIOInner as PanicGPIO;
+
+/// Representation of the GPIO HW. +/// Representation of the GPIO HW.
+pub struct GPIO { +pub struct GPIO {
+ registers: NullLock<Registers>, + inner: NullLock<GPIOInner>,
+} +}
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Public Code +// Public Code
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
+impl GPIO { +impl GPIOInner {
+ /// Create an instance. + /// Create an instance.
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(base_addr: usize) -> Self { + pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ registers: NullLock::new(Registers::new(base_addr)), + registers: Registers::new(mmio_start_addr),
+ } + }
+ } + }
+ +
@ -240,25 +247,41 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_drivers_g
+ /// + ///
+ /// TX to pin 14 + /// TX to pin 14
+ /// RX to pin 15 + /// RX to pin 15
+ pub fn map_pl011_uart(&self) { + pub fn map_pl011_uart(&mut self) {
+ let mut r = &self.registers;
+ r.lock(|registers| {
+ // Map to pins. + // Map to pins.
+ registers + self.registers
+ .GPFSEL1 + .GPFSEL1
+ .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); + .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
+ +
+ // Enable pins 14 and 15. + // Enable pins 14 and 15.
+ registers.GPPUD.set(0); + self.registers.GPPUD.set(0);
+ cpu::spin_for_cycles(150); + cpu::spin_for_cycles(150);
+ +
+ registers + self.registers
+ .GPPUDCLK0 + .GPPUDCLK0
+ .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); + .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
+ cpu::spin_for_cycles(150); + cpu::spin_for_cycles(150);
+ +
+ registers.GPPUDCLK0.set(0); + self.registers.GPPUDCLK0.set(0);
+ }) + }
+}
+
+impl GPIO {
+ /// Create an instance.
+ ///
+ /// # Safety
+ ///
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self {
+ inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
+ }
+ }
+
+ /// Concurrency safe version of `GPIOInner.map_pl011_uart()`
+ pub fn map_pl011_uart(&self) {
+ let mut r = &self.inner;
+ r.lock(|inner| inner.map_pl011_uart())
+ } + }
+} +}
+ +
@ -442,10 +465,10 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 06_dri
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(base_addr: usize) -> Self { + pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ registers: Registers::new(base_addr), + registers: Registers::new(mmio_start_addr),
+ chars_written: 0, + chars_written: 0,
+ chars_read: 0, + chars_read: 0,
+ } + }
@ -510,10 +533,10 @@ diff -uNr 05_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 06_dri
+impl PL011Uart { +impl PL011Uart {
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(base_addr: usize) -> Self { + pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ inner: NullLock::new(PL011UartInner::new(base_addr)), + inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
+ } + }
+ } + }
+} +}
@ -668,7 +691,7 @@ diff -uNr 05_safe_globals/src/bsp/device_driver.rs 06_drivers_gpio_uart/src/bsp/
diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs
--- 05_safe_globals/src/bsp/raspberrypi/console.rs --- 05_safe_globals/src/bsp/raspberrypi/console.rs
+++ 06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs +++ 06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs
@@ -4,115 +4,27 @@ @@ -4,115 +4,34 @@
//! BSP console facilities. //! BSP console facilities.
@ -679,10 +702,13 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/sr
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
-// Private Definitions -// Private Definitions
-//-------------------------------------------------------------------------------------------------- +// Public Code
- //--------------------------------------------------------------------------------------------------
-/// A mystical, magical device for generating QEMU output out of the void. -/// A mystical, magical device for generating QEMU output out of the void.
-/// +/// In case of a panic, the panic handler uses this function to take a last shot at printing
+/// something before the system is halted.
///
-/// The mutex protected part. -/// The mutex protected part.
-struct QEMUOutputInner { -struct QEMUOutputInner {
- chars_written: usize, - chars_written: usize,
@ -705,9 +731,8 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/sr
- -
-//-------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------
-// Private Code -// Private Code
+// Public Code -//--------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------- -
-impl QEMUOutputInner { -impl QEMUOutputInner {
- const fn new() -> QEMUOutputInner { - const fn new() -> QEMUOutputInner {
- QEMUOutputInner { chars_written: 0 } - QEMUOutputInner { chars_written: 0 }
@ -726,8 +751,9 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/sr
-/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are -/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
-/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, -/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
-/// we get `write_fmt()` automatically. -/// we get `write_fmt()` automatically.
+/// In case of a panic, the panic handler uses this function to take a last shot at printing +/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
+/// something before the system is halted. +/// with synchronization primitives, which increases chances that we get to print something, even
+/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
/// ///
-/// The function takes an `&mut self`, so it must be implemented for the inner struct. -/// The function takes an `&mut self`, so it must be implemented for the inner struct.
+/// # Safety +/// # Safety
@ -763,9 +789,12 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/sr
- } - }
+/// - Use only for printing during a panic. +/// - Use only for printing during a panic.
+pub unsafe fn panic_console_out() -> impl fmt::Write { +pub unsafe fn panic_console_out() -> impl fmt::Write {
+ let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); + let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
+ uart.init(); + let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
+ uart +
+ panic_gpio.map_pl011_uart();
+ panic_uart.init();
+ panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.
@ -854,12 +883,10 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/driver.rs 06_drivers_gpio_uart/src
diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
--- 05_safe_globals/src/bsp/raspberrypi/memory.rs --- 05_safe_globals/src/bsp/raspberrypi/memory.rs
+++ 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs +++ 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
@@ -23,7 +23,30 @@ @@ -24,6 +24,29 @@
/// The board's memory map.
#[rustfmt::skip] #[rustfmt::skip]
pub(super) mod map { pub(super) mod map {
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000; pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ +
+ pub const GPIO_OFFSET: usize = 0x0020_0000; + pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000; + pub const UART_OFFSET: usize = 0x0020_1000;
@ -869,9 +896,9 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src
+ pub mod mmio { + pub mod mmio {
+ use super::*; + use super::*;
+ +
+ pub const BASE: usize = 0x3F00_0000; + pub const START: usize = 0x3F00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; + pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; + pub const PL011_UART_START: usize = START + UART_OFFSET;
+ } + }
+ +
+ /// Physical devices. + /// Physical devices.
@ -879,9 +906,9 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src
+ pub mod mmio { + pub mod mmio {
+ use super::*; + use super::*;
+ +
+ pub const BASE: usize = 0xFE00_0000; + pub const START: usize = 0xFE00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; + pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; + pub const PL011_UART_START: usize = START + UART_OFFSET;
+ } + }
} }
@ -903,10 +930,10 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi.rs 06_drivers_gpio_uart/src/bsp/ra
+use super::device_driver; +use super::device_driver;
+ +
+static GPIO: device_driver::GPIO = +static GPIO: device_driver::GPIO =
+ unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; + unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
+ +
+static PL011_UART: device_driver::PL011Uart = +static PL011_UART: device_driver::PL011Uart =
+ unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; + unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Public Code +// Public Code

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -33,9 +33,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
/// Physical devices. /// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
} }

@ -281,7 +281,7 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/link.ld 07_uart_chainloader/s
diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader/src/bsp/raspberrypi/memory.rs diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
--- 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs --- 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
+++ 07_uart_chainloader/src/bsp/raspberrypi/memory.rs +++ 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
@@ -23,19 +23,21 @@ @@ -23,10 +23,12 @@
/// The board's memory map. /// The board's memory map.
#[rustfmt::skip] #[rustfmt::skip]
pub(super) mod map { pub(super) mod map {
@ -297,31 +297,6 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader
/// Physical devices. /// Physical devices.
#[cfg(feature = "bsp_rpi3")] #[cfg(feature = "bsp_rpi3")]
pub mod mmio {
use super::*;
- pub const BASE: usize = 0x3F00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0x3F00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
/// Physical devices.
@@ -43,9 +45,9 @@
pub mod mmio {
use super::*;
- pub const BASE: usize = 0xFE00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0xFE00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
@@ -59,6 +61,12 @@ @@ -59,6 +61,12 @@
map::BOOT_CORE_STACK_END map::BOOT_CORE_STACK_END
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -35,9 +35,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
/// Physical devices. /// Physical devices.
@ -45,9 +45,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
} }

@ -280,7 +280,7 @@ diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/link.ld 08_timestamps/src/bsp/
diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bsp/raspberrypi/memory.rs diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bsp/raspberrypi/memory.rs
--- 07_uart_chainloader/src/bsp/raspberrypi/memory.rs --- 07_uart_chainloader/src/bsp/raspberrypi/memory.rs
+++ 08_timestamps/src/bsp/raspberrypi/memory.rs +++ 08_timestamps/src/bsp/raspberrypi/memory.rs
@@ -23,21 +23,19 @@ @@ -23,12 +23,10 @@
/// The board's memory map. /// The board's memory map.
#[rustfmt::skip] #[rustfmt::skip]
pub(super) mod map { pub(super) mod map {
@ -296,31 +296,6 @@ diff -uNr 07_uart_chainloader/src/bsp/raspberrypi/memory.rs 08_timestamps/src/bs
/// Physical devices. /// Physical devices.
#[cfg(feature = "bsp_rpi3")] #[cfg(feature = "bsp_rpi3")]
pub mod mmio {
use super::*;
- pub const BASE: usize = 0x3F00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0x3F00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
/// Physical devices.
@@ -45,9 +43,9 @@
pub mod mmio {
use super::*;
- pub const BASE: usize = 0xFE00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const BASE: usize = 0xFE00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
}
}
@@ -61,12 +59,6 @@ @@ -61,12 +59,6 @@
map::BOOT_CORE_STACK_END map::BOOT_CORE_STACK_END
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -33,9 +33,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
/// Physical devices. /// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -33,9 +33,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
/// Physical devices. /// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -33,9 +33,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
/// Physical devices. /// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
} }

@ -696,7 +696,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_memory
+ TranslationDescriptor { + TranslationDescriptor {
+ name: "Remapped Device MMIO", + name: "Remapped Device MMIO",
+ virtual_range: remapped_mmio_range_inclusive, + virtual_range: remapped_mmio_range_inclusive,
+ physical_range_translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000), + physical_range_translation: Translation::Offset(memory_map::mmio::START + 0x20_0000),
+ attribute_fields: AttributeFields { + attribute_fields: AttributeFields {
+ mem_attributes: MemAttributes::Device, + mem_attributes: MemAttributes::Device,
+ acc_perms: AccessPermissions::ReadWrite, + acc_perms: AccessPermissions::ReadWrite,
@ -732,7 +732,7 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory/mmu.rs 11_virtual_memory
+} +}
+ +
+fn mmio_range_inclusive() -> RangeInclusive<usize> { +fn mmio_range_inclusive() -> RangeInclusive<usize> {
+ RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) + RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
+} +}
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
@ -780,17 +780,17 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
pub const GPIO_OFFSET: usize = 0x0020_0000; pub const GPIO_OFFSET: usize = 0x0020_0000;
@@ -36,6 +42,7 @@ @@ -36,6 +42,7 @@
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const END_INCLUSIVE: usize = 0x4000_FFFF; + pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
/// Physical devices. /// Physical devices.
@@ -46,10 +53,35 @@ @@ -46,10 +53,35 @@
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const END_INCLUSIVE: usize = 0xFF84_FFFF; + pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
} }
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -39,9 +39,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0x4000_FFFF; pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
@ -50,9 +50,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF; pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
} }
} }

@ -34,7 +34,7 @@ pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout
TranslationDescriptor { TranslationDescriptor {
name: "Remapped Device MMIO", name: "Remapped Device MMIO",
virtual_range: remapped_mmio_range_inclusive, virtual_range: remapped_mmio_range_inclusive,
physical_range_translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000), physical_range_translation: Translation::Offset(memory_map::mmio::START + 0x20_0000),
attribute_fields: AttributeFields { attribute_fields: AttributeFields {
mem_attributes: MemAttributes::Device, mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite, acc_perms: AccessPermissions::ReadWrite,
@ -70,7 +70,7 @@ fn remapped_mmio_range_inclusive() -> RangeInclusive<usize> {
} }
fn mmio_range_inclusive() -> RangeInclusive<usize> { fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -917,7 +917,7 @@ diff -uNr 11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs 12_exceptions_part
TranslationDescriptor { TranslationDescriptor {
- name: "Remapped Device MMIO", - name: "Remapped Device MMIO",
- virtual_range: remapped_mmio_range_inclusive, - virtual_range: remapped_mmio_range_inclusive,
- physical_range_translation: Translation::Offset(memory_map::mmio::BASE + 0x20_0000), - physical_range_translation: Translation::Offset(memory_map::mmio::START + 0x20_0000),
- attribute_fields: AttributeFields { - attribute_fields: AttributeFields {
- mem_attributes: MemAttributes::Device, - mem_attributes: MemAttributes::Device,
- acc_perms: AccessPermissions::ReadWrite, - acc_perms: AccessPermissions::ReadWrite,
@ -938,7 +938,7 @@ diff -uNr 11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs 12_exceptions_part
-} -}
- -
fn mmio_range_inclusive() -> RangeInclusive<usize> { fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
} }
diff -uNr 11_virtual_memory/src/bsp.rs 12_exceptions_part1_groundwork/src/bsp.rs diff -uNr 11_virtual_memory/src/bsp.rs 12_exceptions_part1_groundwork/src/bsp.rs

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -39,9 +39,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0x4000_FFFF; pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
@ -50,9 +50,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF; pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
} }
} }

@ -55,7 +55,7 @@ fn ro_range_inclusive() -> RangeInclusive<usize> {
} }
fn mmio_range_inclusive() -> RangeInclusive<usize> { fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -138,6 +138,7 @@ In `lib.rs`, we add the following headers to get started with `custom_test_frame
```rust ```rust
// Testing // Testing
#![cfg_attr(test, no_main)] #![cfg_attr(test, no_main)]
#![cfg_attr(test, feature(slice_ptr_range))]
#![feature(custom_test_frameworks)] #![feature(custom_test_frameworks)]
#![reexport_test_harness_main = "test_main"] #![reexport_test_harness_main = "test_main"]
#![test_runner(crate::test_runner)] #![test_runner(crate::test_runner)]
@ -1000,7 +1001,7 @@ diff -uNr 12_exceptions_part1_groundwork/src/_arch/aarch64/exception.rs 13_integ
diff -uNr 12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs 13_integrated_testing/src/bsp/raspberrypi/console.rs diff -uNr 12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs 13_integrated_testing/src/bsp/raspberrypi/console.rs
--- 12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs --- 12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs
+++ 13_integrated_testing/src/bsp/raspberrypi/console.rs +++ 13_integrated_testing/src/bsp/raspberrypi/console.rs
@@ -28,3 +28,13 @@ @@ -35,3 +35,13 @@
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static impl console::interface::All {
&super::PL011_UART &super::PL011_UART
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -39,9 +39,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0x4000_FFFF; pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
@ -50,9 +50,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF; pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
} }
} }

@ -55,7 +55,7 @@ fn ro_range_inclusive() -> RangeInclusive<usize> {
} }
fn mmio_range_inclusive() -> RangeInclusive<usize> { fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -524,7 +524,7 @@ impl<T> interface::ReadWriteEx for &InitStateLock<T> {
fn write<R>(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { fn write<R>(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R {
assert!( assert!(
state::state_manager().state() == state::State::Init, state::state_manager().is_init(),
"InitStateLock::write called after kernel init phase" "InitStateLock::write called after kernel init phase"
); );
assert!( assert!(
@ -620,7 +620,7 @@ register_structs! {
(0x104 => ISENABLER: [ReadWrite<u32>; 31]), (0x104 => ISENABLER: [ReadWrite<u32>; 31]),
(0x108 => _reserved2), (0x108 => _reserved2),
(0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]), (0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]),
(0xBFC => @END), (0x824 => @END),
} }
} }
@ -631,7 +631,7 @@ register_structs! {
(0x100 => ISENABLER: ReadWrite<u32>), (0x100 => ISENABLER: ReadWrite<u32>),
(0x104 => _reserved2), (0x104 => _reserved2),
(0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]), (0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]),
(0xBFC => @END), (0x804 => @END),
} }
} }
``` ```
@ -945,10 +945,10 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/arm/gicv2/gicc.rs 14_excep
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(base_addr: usize) -> Self { + pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ registers: Registers::new(base_addr), + registers: Registers::new(mmio_start_addr),
+ } + }
+ } + }
+ +
@ -1067,7 +1067,7 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/arm/gicv2/gicd.rs 14_excep
+ (0x104 => ISENABLER: [ReadWrite<u32>; 31]), + (0x104 => ISENABLER: [ReadWrite<u32>; 31]),
+ (0x108 => _reserved2), + (0x108 => _reserved2),
+ (0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]), + (0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]),
+ (0xBFC => @END), + (0x824 => @END),
+ } + }
+} +}
+ +
@ -1078,7 +1078,7 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/arm/gicv2/gicd.rs 14_excep
+ (0x100 => ISENABLER: ReadWrite<u32>), + (0x100 => ISENABLER: ReadWrite<u32>),
+ (0x104 => _reserved2), + (0x104 => _reserved2),
+ (0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]), + (0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]),
+ (0xBFC => @END), + (0x804 => @END),
+ } + }
+} +}
+ +
@ -1142,11 +1142,11 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/arm/gicv2/gicd.rs 14_excep
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(base_addr: usize) -> Self { + pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ shared_registers: IRQSafeNullLock::new(SharedRegisters::new(base_addr)), + shared_registers: IRQSafeNullLock::new(SharedRegisters::new(mmio_start_addr)),
+ banked_registers: BankedRegisters::new(base_addr), + banked_registers: BankedRegisters::new(mmio_start_addr),
+ } + }
+ } + }
+ +
@ -1339,11 +1339,11 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/arm/gicv2.rs 14_exceptions
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(gicd_base_addr: usize, gicc_base_addr: usize) -> Self { + pub const unsafe fn new(gicd_mmio_start_addr: usize, gicc_mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ gicd: gicd::GICD::new(gicd_base_addr), + gicd: gicd::GICD::new(gicd_mmio_start_addr),
+ gicc: gicc::GICC::new(gicc_base_addr), + gicc: gicc::GICC::new(gicc_mmio_start_addr),
+ handler_table: InitStateLock::new([None; Self::NUM_IRQS]), + handler_table: InitStateLock::new([None; Self::NUM_IRQS]),
+ } + }
+ } + }
@ -1468,21 +1468,21 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 14_exc
}; };
use register::{mmio::*, register_bitfields, register_structs}; use register::{mmio::*, register_bitfields, register_structs};
@@ -81,7 +81,7 @@ @@ -88,7 +88,7 @@
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
- registers: NullLock<Registers>, - inner: NullLock<GPIOInner>,
+ registers: IRQSafeNullLock<Registers>, + inner: IRQSafeNullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -96,7 +96,7 @@ @@ -138,7 +138,7 @@
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
- registers: NullLock::new(Registers::new(base_addr)), - inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
+ registers: IRQSafeNullLock::new(Registers::new(base_addr)), + inner: IRQSafeNullLock::new(GPIOInner::new(mmio_start_addr)),
} }
} }
@ -1563,11 +1563,11 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_interrupt_cont
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(base_addr: usize) -> Self { + pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(base_addr)), + wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)),
+ ro_registers: ReadOnlyRegisters::new(base_addr), + ro_registers: ReadOnlyRegisters::new(mmio_start_addr),
+ handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), + handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]),
+ } + }
+ } + }
@ -1743,10 +1743,10 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_interrupt_cont
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide the correct `base_addr`. + /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(_local_base_addr: usize, periph_base_addr: usize) -> Self { + pub const unsafe fn new(_local_mmio_start_addr: usize, periph_mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ periph: peripheral_ic::PeripheralIC::new(periph_base_addr), + periph: peripheral_ic::PeripheralIC::new(periph_mmio_start_addr),
+ } + }
+ } + }
+} +}
@ -1940,20 +1940,28 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
} }
/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are /// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
@@ -232,9 +317,10 @@ @@ -229,12 +314,18 @@
}
impl PL011Uart {
+ /// Create an instance.
+ ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
- pub const unsafe fn new(base_addr: usize) -> Self { - pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ pub const unsafe fn new(base_addr: usize, irq_number: bsp::device_driver::IRQNumber) -> Self { + pub const unsafe fn new(
+ mmio_start_addr: usize,
+ irq_number: bsp::device_driver::IRQNumber,
+ ) -> Self {
Self { Self {
- inner: NullLock::new(PL011UartInner::new(base_addr)), - inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
+ inner: IRQSafeNullLock::new(PL011UartInner::new(base_addr)), + inner: IRQSafeNullLock::new(PL011UartInner::new(mmio_start_addr)),
+ irq_number, + irq_number,
} }
} }
} }
@@ -255,6 +341,21 @@ @@ -255,6 +346,21 @@
Ok(()) Ok(())
} }
@ -1975,7 +1983,7 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
} }
impl console::interface::Write for PL011Uart { impl console::interface::Write for PL011Uart {
@@ -286,25 +387,7 @@ @@ -286,25 +392,7 @@
impl console::interface::Read for PL011Uart { impl console::interface::Read for PL011Uart {
fn read_char(&self) -> char { fn read_char(&self) -> char {
let mut r = &self.inner; let mut r = &self.inner;
@ -2002,7 +2010,7 @@ diff -uNr 13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
} }
fn clear(&self) { fn clear(&self) {
@@ -329,3 +412,25 @@ @@ -329,3 +417,25 @@
r.lock(|inner| inner.chars_read) r.lock(|inner| inner.chars_read)
} }
} }
@ -2145,57 +2153,33 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi/exception.rs 14_exceptions_p
diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs diff -uNr 13_integrated_testing/src/bsp/raspberrypi/memory.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
--- 13_integrated_testing/src/bsp/raspberrypi/memory.rs --- 13_integrated_testing/src/bsp/raspberrypi/memory.rs
+++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs +++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
@@ -27,22 +27,24 @@ @@ -39,10 +39,12 @@
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
- pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
+ pub const END_INCLUSIVE: usize = 0xFFFF_FFFF;
- pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
+ pub const BOOT_CORE_STACK_END: usize = 0x8_0000;
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
pub mod mmio { pub mod mmio {
use super::*; use super::*;
- pub const BASE: usize = 0x3F00_0000; - pub const START: usize = 0x3F00_0000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; - pub const GPIO_START: usize = START + GPIO_OFFSET;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; - pub const PL011_UART_START: usize = START + UART_OFFSET;
- pub const END_INCLUSIVE: usize = 0x4000_FFFF; - pub const END_INCLUSIVE: usize = 0x4000_FFFF;
+ pub const BASE: usize = 0x3F00_0000; + pub const START: usize = 0x3F00_0000;
+ pub const PERIPHERAL_INTERRUPT_CONTROLLER_BASE: usize = BASE + 0x0000_B200; + pub const PERIPHERAL_INTERRUPT_CONTROLLER_START: usize = START + 0x0000_B200;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; + pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; + pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const LOCAL_INTERRUPT_CONTROLLER_BASE: usize = 0x4000_0000; + pub const LOCAL_INTERRUPT_CONTROLLER_START: usize = 0x4000_0000;
+ pub const END_INCLUSIVE: usize = 0x4000_FFFF; + pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
/// Physical devices. /// Physical devices.
@@ -50,10 +52,12 @@ @@ -53,6 +55,8 @@
pub mod mmio { pub const START: usize = 0xFE00_0000;
use super::*; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
- pub const BASE: usize = 0xFE00_0000; + pub const GICD_START: usize = 0xFF84_1000;
- pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; + pub const GICC_START: usize = 0xFF84_2000;
- pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
- pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
+ pub const BASE: usize = 0xFE00_0000;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const GICD_BASE: usize = 0xFF84_1000;
+ pub const GICC_BASE: usize = 0xFF84_2000;
+ pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
} }
} }
diff -uNr 13_integrated_testing/src/bsp/raspberrypi.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs diff -uNr 13_integrated_testing/src/bsp/raspberrypi.rs 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs
--- 13_integrated_testing/src/bsp/raspberrypi.rs --- 13_integrated_testing/src/bsp/raspberrypi.rs
+++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs +++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs
@ -2209,13 +2193,13 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi.rs 14_exceptions_part2_perip
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -17,8 +18,25 @@ @@ -17,8 +18,25 @@
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
-static PL011_UART: device_driver::PL011Uart = -static PL011_UART: device_driver::PL011Uart =
- unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; - unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
+static PL011_UART: device_driver::PL011Uart = unsafe { +static PL011_UART: device_driver::PL011Uart = unsafe {
+ device_driver::PL011Uart::new( + device_driver::PL011Uart::new(
+ memory::map::mmio::PL011_UART_BASE, + memory::map::mmio::PL011_UART_START,
+ exception::asynchronous::irq_map::PL011_UART, + exception::asynchronous::irq_map::PL011_UART,
+ ) + )
+}; +};
@ -2223,14 +2207,14 @@ diff -uNr 13_integrated_testing/src/bsp/raspberrypi.rs 14_exceptions_part2_perip
+#[cfg(feature = "bsp_rpi3")] +#[cfg(feature = "bsp_rpi3")]
+static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe { +static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe {
+ device_driver::InterruptController::new( + device_driver::InterruptController::new(
+ memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_BASE, + memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_START,
+ memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_BASE, + memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_START,
+ ) + )
+}; +};
+ +
+#[cfg(feature = "bsp_rpi4")] +#[cfg(feature = "bsp_rpi4")]
+static INTERRUPT_CONTROLLER: device_driver::GICv2 = unsafe { +static INTERRUPT_CONTROLLER: device_driver::GICv2 = unsafe {
+ device_driver::GICv2::new(memory::map::mmio::GICD_BASE, memory::map::mmio::GICC_BASE) + device_driver::GICv2::new(memory::map::mmio::GICD_START, memory::map::mmio::GICC_START)
+}; +};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -118,11 +118,11 @@ impl GICv2 {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(gicd_base_addr: usize, gicc_base_addr: usize) -> Self { pub const unsafe fn new(gicd_mmio_start_addr: usize, gicc_mmio_start_addr: usize) -> Self {
Self { Self {
gicd: gicd::GICD::new(gicd_base_addr), gicd: gicd::GICD::new(gicd_mmio_start_addr),
gicc: gicc::GICC::new(gicc_base_addr), gicc: gicc::GICC::new(gicc_mmio_start_addr),
handler_table: InitStateLock::new([None; Self::NUM_IRQS]), handler_table: InitStateLock::new([None; Self::NUM_IRQS]),
} }
} }

@ -68,10 +68,10 @@ impl GICC {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
} }
} }

@ -48,7 +48,7 @@ register_structs! {
(0x104 => ISENABLER: [ReadWrite<u32>; 31]), (0x104 => ISENABLER: [ReadWrite<u32>; 31]),
(0x108 => _reserved2), (0x108 => _reserved2),
(0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]), (0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]),
(0xBFC => @END), (0x824 => @END),
} }
} }
@ -59,7 +59,7 @@ register_structs! {
(0x100 => ISENABLER: ReadWrite<u32>), (0x100 => ISENABLER: ReadWrite<u32>),
(0x104 => _reserved2), (0x104 => _reserved2),
(0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]), (0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]),
(0xBFC => @END), (0x804 => @END),
} }
} }
@ -123,11 +123,11 @@ impl GICD {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
shared_registers: IRQSafeNullLock::new(SharedRegisters::new(base_addr)), shared_registers: IRQSafeNullLock::new(SharedRegisters::new(mmio_start_addr)),
banked_registers: BankedRegisters::new(base_addr), banked_registers: BankedRegisters::new(mmio_start_addr),
} }
} }

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: IRQSafeNullLock<Registers>, inner: IRQSafeNullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: IRQSafeNullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: IRQSafeNullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -78,10 +78,10 @@ impl InterruptController {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(_local_base_addr: usize, periph_base_addr: usize) -> Self { pub const unsafe fn new(_local_mmio_start_addr: usize, periph_mmio_start_addr: usize) -> Self {
Self { Self {
periph: peripheral_ic::PeripheralIC::new(periph_base_addr), periph: peripheral_ic::PeripheralIC::new(periph_mmio_start_addr),
} }
} }
} }

@ -70,11 +70,11 @@ impl PeripheralIC {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(base_addr)), wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)),
ro_registers: ReadOnlyRegisters::new(base_addr), ro_registers: ReadOnlyRegisters::new(mmio_start_addr),
handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]), handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]),
} }
} }

@ -215,10 +215,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -314,12 +314,17 @@ impl fmt::Write for PL011UartInner {
} }
impl PL011Uart { impl PL011Uart {
/// Create an instance.
///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize, irq_number: bsp::device_driver::IRQNumber) -> Self { pub const unsafe fn new(
mmio_start_addr: usize,
irq_number: bsp::device_driver::IRQNumber,
) -> Self {
Self { Self {
inner: IRQSafeNullLock::new(PL011UartInner::new(base_addr)), inner: IRQSafeNullLock::new(PL011UartInner::new(mmio_start_addr)),
irq_number, irq_number,
} }
} }

@ -16,11 +16,11 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = unsafe { static PL011_UART: device_driver::PL011Uart = unsafe {
device_driver::PL011Uart::new( device_driver::PL011Uart::new(
memory::map::mmio::PL011_UART_BASE, memory::map::mmio::PL011_UART_START,
exception::asynchronous::irq_map::PL011_UART, exception::asynchronous::irq_map::PL011_UART,
) )
}; };
@ -28,14 +28,14 @@ static PL011_UART: device_driver::PL011Uart = unsafe {
#[cfg(feature = "bsp_rpi3")] #[cfg(feature = "bsp_rpi3")]
static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe { static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe {
device_driver::InterruptController::new( device_driver::InterruptController::new(
memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_BASE, memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_START,
memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_BASE, memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_START,
) )
}; };
#[cfg(feature = "bsp_rpi4")] #[cfg(feature = "bsp_rpi4")]
static INTERRUPT_CONTROLLER: device_driver::GICv2 = unsafe { static INTERRUPT_CONTROLLER: device_driver::GICv2 = unsafe {
device_driver::GICv2::new(memory::map::mmio::GICD_BASE, memory::map::mmio::GICC_BASE) device_driver::GICv2::new(memory::map::mmio::GICD_START, memory::map::mmio::GICC_START)
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -39,11 +39,11 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const PERIPHERAL_INTERRUPT_CONTROLLER_BASE: usize = BASE + 0x0000_B200; pub const PERIPHERAL_INTERRUPT_CONTROLLER_START: usize = START + 0x0000_B200;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const LOCAL_INTERRUPT_CONTROLLER_BASE: usize = 0x4000_0000; pub const LOCAL_INTERRUPT_CONTROLLER_START: usize = 0x4000_0000;
pub const END_INCLUSIVE: usize = 0x4000_FFFF; pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
@ -52,11 +52,11 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const GICD_BASE: usize = 0xFF84_1000; pub const GICD_START: usize = 0xFF84_1000;
pub const GICC_BASE: usize = 0xFF84_2000; pub const GICC_START: usize = 0xFF84_2000;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF; pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
} }
} }

@ -55,7 +55,7 @@ fn ro_range_inclusive() -> RangeInclusive<usize> {
} }
fn mmio_range_inclusive() -> RangeInclusive<usize> { fn mmio_range_inclusive() -> RangeInclusive<usize> {
RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

Binary file not shown.

Binary file not shown.

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers,
}
// Export the inner struct so that BSPs can use it for the panic handler.
pub use GPIOInner as PanicGPIO;
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
registers: NullLock<Registers>, inner: NullLock<GPIOInner>,
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIOInner {
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: NullLock::new(Registers::new(base_addr)), registers: Registers::new(mmio_start_addr),
} }
} }
@ -104,25 +111,41 @@ impl GPIO {
/// ///
/// TX to pin 14 /// TX to pin 14
/// RX to pin 15 /// RX to pin 15
pub fn map_pl011_uart(&self) { pub fn map_pl011_uart(&mut self) {
let mut r = &self.registers;
r.lock(|registers| {
// Map to pins. // Map to pins.
registers self.registers
.GPFSEL1 .GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0); .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15. // Enable pins 14 and 15.
registers.GPPUD.set(0); self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers self.registers
.GPPUDCLK0 .GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock); .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150); cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0); self.registers.GPPUDCLK0.set(0);
}) }
}
impl GPIO {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
inner: NullLock::new(GPIOInner::new(mmio_start_addr)),
}
}
/// Concurrency safe version of `GPIOInner.map_pl011_uart()`
pub fn map_pl011_uart(&self) {
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
} }
} }

@ -163,10 +163,10 @@ impl PL011UartInner {
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
registers: Registers::new(base_addr), registers: Registers::new(mmio_start_addr),
chars_written: 0, chars_written: 0,
chars_read: 0, chars_read: 0,
} }
@ -231,10 +231,10 @@ impl fmt::Write for PL011UartInner {
impl PL011Uart { impl PL011Uart {
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide the correct `base_addr`. /// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(base_addr: usize) -> Self { pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self { Self {
inner: NullLock::new(PL011UartInner::new(base_addr)), inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
} }
} }
} }

@ -15,7 +15,7 @@ pub mod memory;
use super::device_driver; use super::device_driver;
static GPIO: device_driver::GPIO = static GPIO: device_driver::GPIO =
unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_BASE) }; unsafe { device_driver::GPIO::new(memory::map::mmio::GPIO_START) };
static PL011_UART: device_driver::PL011Uart = static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) }; unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };

@ -15,13 +15,20 @@ use core::fmt;
/// In case of a panic, the panic handler uses this function to take a last shot at printing /// In case of a panic, the panic handler uses this function to take a last shot at printing
/// something before the system is halted. /// something before the system is halted.
/// ///
/// We try to init panic-versions of the GPIO and the UART. The panic versions are not protected
/// with synchronization primitives, which increases chances that we get to print something, even
/// when the kernel's default GPIO or UART instances happen to be locked at the time of the panic.
///
/// # Safety /// # Safety
/// ///
/// - Use only for printing during a panic. /// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write { pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE); let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
uart.init(); let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
uart
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
} }
/// Return a reference to the console. /// Return a reference to the console.

@ -33,9 +33,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0x3F00_0000; pub const START: usize = 0x3F00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
/// Physical devices. /// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
pub mod mmio { pub mod mmio {
use super::*; use super::*;
pub const BASE: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
} }

Loading…
Cancel
Save