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
- Custom `link.ld` linker script.
- Load address at `0x80_000`
- Load address at `0x8_0000`
- Only `.text` section.
- `main.rs`: Important [inner attributes]:
- `#![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
--- 05_safe_globals/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
+//
+// 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
+//--------------------------------------------------------------------------------------------------
+
+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.
+pub struct GPIO {
+ registers: NullLock<Registers>,
+ inner: NullLock<GPIOInner>,
+}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+impl GPIO {
+impl GPIOInner {
+ /// Create an instance.
+ ///
+ /// # Safety
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(mmio_start_addr: usize) -> 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
+ /// RX to pin 15
+ pub fn map_pl011_uart(&mut self) {
+ // Map to pins.
+ self.registers
+ .GPFSEL1
+ .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
+
+ // Enable pins 14 and 15.
+ self.registers.GPPUD.set(0);
+ cpu::spin_for_cycles(150);
+
+ self.registers
+ .GPPUDCLK0
+ .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
+ cpu::spin_for_cycles(150);
+
+ 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.registers;
+ r.lock(|registers| {
+ // Map to pins.
+ registers
+ .GPFSEL1
+ .modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
+
+ // Enable pins 14 and 15.
+ registers.GPPUD.set(0);
+ cpu::spin_for_cycles(150);
+
+ registers
+ .GPPUDCLK0
+ .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
+ cpu::spin_for_cycles(150);
+
+ registers.GPPUDCLK0.set(0);
+ })
+ 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
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self {
+ registers: Registers::new(base_addr),
+ registers: Registers::new(mmio_start_addr),
+ chars_written: 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 {
+ /// # Safety
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ /// - 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(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
--- 05_safe_globals/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.
@ -679,10 +702,13 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/sr
//--------------------------------------------------------------------------------------------------
-// Private Definitions
-//--------------------------------------------------------------------------------------------------
-
+// Public Code
//--------------------------------------------------------------------------------------------------
-/// 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.
-struct QEMUOutputInner {
- chars_written: usize,
@ -705,9 +731,8 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/console.rs 06_drivers_gpio_uart/sr
-
-//--------------------------------------------------------------------------------------------------
-// Private Code
+// Public Code
//--------------------------------------------------------------------------------------------------
-//--------------------------------------------------------------------------------------------------
-
-impl QEMUOutputInner {
- const fn new() -> QEMUOutputInner {
- 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
-/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
-/// we get `write_fmt()` automatically.
+/// In case of a panic, the panic handler uses this function to take a last shot at printing
+/// 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.
///
-/// The function takes an `&mut self`, so it must be implemented for the inner struct.
+/// # 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.
+pub unsafe fn panic_console_out() -> impl fmt::Write {
+ let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
+ uart.init();
+ uart
+ let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
+ let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
+
+ panic_gpio.map_pl011_uart();
+ panic_uart.init();
+ panic_uart
}
/// Return a reference to the console.
@ -854,24 +883,22 @@ 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
--- 05_safe_globals/src/bsp/raspberrypi/memory.rs
+++ 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
@@ -23,7 +23,30 @@
/// The board's memory map.
@@ -24,6 +24,29 @@
#[rustfmt::skip]
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 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 {
+ 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 START: usize = 0x3F00_0000;
+ pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_START: usize = START + UART_OFFSET;
+ }
+
+ /// Physical devices.
@ -879,9 +906,9 @@ diff -uNr 05_safe_globals/src/bsp/raspberrypi/memory.rs 06_drivers_gpio_uart/src
+ 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 START: usize = 0xFE00_0000;
+ pub const GPIO_START: usize = START + GPIO_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;
+
+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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
+ unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
+
+//--------------------------------------------------------------------------------------------------
+// Public Code

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -23,19 +23,19 @@ extern "C" {
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
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 {
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 START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
/// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
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 START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
}

@ -281,15 +281,15 @@ 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
--- 06_drivers_gpio_uart/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.
#[rustfmt::skip]
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 UART_OFFSET: usize = 0x0020_1000;
- pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
+
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
@ -297,31 +297,6 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 07_uart_chainloader
/// Physical devices.
#[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 @@
map::BOOT_CORE_STACK_END
}

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -35,9 +35,9 @@ pub(super) mod map {
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 START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
/// Physical devices.
@ -45,9 +45,9 @@ pub(super) mod map {
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 START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
}

@ -280,47 +280,22 @@ 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
--- 07_uart_chainloader/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.
#[rustfmt::skip]
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 BOARD_DEFAULT_LOAD_ADDRESS: 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;
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[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 @@
map::BOOT_CORE_STACK_END
}

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -23,19 +23,19 @@ extern "C" {
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
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 {
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 START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
/// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
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 START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
}

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -23,19 +23,19 @@ extern "C" {
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
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 {
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 START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
/// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
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 START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
}

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -23,19 +23,19 @@ extern "C" {
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
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 {
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 START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
/// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
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 START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_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 {
+ name: "Remapped Device MMIO",
+ 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 {
+ mem_attributes: MemAttributes::Device,
+ 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> {
+ RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE)
+ RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE)
+}
+
+//--------------------------------------------------------------------------------------------------
@ -774,24 +774,24 @@ diff -uNr 10_privilege_level/src/bsp/raspberrypi/memory.rs 11_virtual_memory/src
/// 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 GPIO_OFFSET: usize = 0x0020_0000;
@@ -36,6 +42,7 @@
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 END_INCLUSIVE: usize = 0x4000_FFFF;
pub const START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const END_INCLUSIVE: usize = 0x4000_FFFF;
}
/// Physical devices.
@@ -46,10 +53,35 @@
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 END_INCLUSIVE: usize = 0xFF84_FFFF;
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -27,22 +27,22 @@ extern "C" {
/// 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 {
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 END_INCLUSIVE: usize = 0x4000_FFFF;
pub const START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0x4000_FFFF;
}
/// Physical devices.
@ -50,10 +50,10 @@ pub(super) mod map {
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 END_INCLUSIVE: usize = 0xFF84_FFFF;
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}

@ -34,7 +34,7 @@ pub static LAYOUT: KernelVirtualLayout<{ NUM_MEM_RANGES }> = KernelVirtualLayout
TranslationDescriptor {
name: "Remapped Device MMIO",
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 {
mem_attributes: MemAttributes::Device,
acc_perms: AccessPermissions::ReadWrite,
@ -70,7 +70,7 @@ fn remapped_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 {
- name: "Remapped Device MMIO",
- 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 {
- mem_attributes: MemAttributes::Device,
- 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> {
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

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -27,22 +27,22 @@ extern "C" {
/// 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 {
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 END_INCLUSIVE: usize = 0x4000_FFFF;
pub const START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0x4000_FFFF;
}
/// Physical devices.
@ -50,10 +50,10 @@ pub(super) mod map {
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 END_INCLUSIVE: usize = 0xFF84_FFFF;
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}

@ -55,7 +55,7 @@ fn ro_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
// Testing
#![cfg_attr(test, no_main)]
#![cfg_attr(test, feature(slice_ptr_range))]
#![feature(custom_test_frameworks)]
#![reexport_test_harness_main = "test_main"]
#![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
--- 12_exceptions_part1_groundwork/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 {
&super::PL011_UART
}

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,10 +15,10 @@ pub mod memory;
use super::device_driver;
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 { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_BASE) };
unsafe { device_driver::PL011Uart::new(memory::map::mmio::PL011_UART_START) };
//--------------------------------------------------------------------------------------------------
// 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -27,22 +27,22 @@ extern "C" {
/// 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 {
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 END_INCLUSIVE: usize = 0x4000_FFFF;
pub const START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0x4000_FFFF;
}
/// Physical devices.
@ -50,10 +50,10 @@ pub(super) mod map {
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 END_INCLUSIVE: usize = 0xFF84_FFFF;
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}

@ -55,7 +55,7 @@ fn ro_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 {
assert!(
state::state_manager().state() == state::State::Init,
state::state_manager().is_init(),
"InitStateLock::write called after kernel init phase"
);
assert!(
@ -620,7 +620,7 @@ register_structs! {
(0x104 => ISENABLER: [ReadWrite<u32>; 31]),
(0x108 => _reserved2),
(0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]),
(0xBFC => @END),
(0x824 => @END),
}
}
@ -631,7 +631,7 @@ register_structs! {
(0x100 => ISENABLER: ReadWrite<u32>),
(0x104 => _reserved2),
(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
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(mmio_start_addr: usize) -> 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]),
+ (0x108 => _reserved2),
+ (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>),
+ (0x104 => _reserved2),
+ (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
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self {
+ shared_registers: IRQSafeNullLock::new(SharedRegisters::new(base_addr)),
+ banked_registers: BankedRegisters::new(base_addr),
+ shared_registers: IRQSafeNullLock::new(SharedRegisters::new(mmio_start_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
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(gicd_base_addr: usize, gicc_base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(gicd_mmio_start_addr: usize, gicc_mmio_start_addr: usize) -> Self {
+ Self {
+ gicd: gicd::GICD::new(gicd_base_addr),
+ gicc: gicc::GICC::new(gicc_base_addr),
+ gicd: gicd::GICD::new(gicd_mmio_start_addr),
+ gicc: gicc::GICC::new(gicc_mmio_start_addr),
+ 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};
@@ -81,7 +81,7 @@
@@ -88,7 +88,7 @@
/// Representation of the GPIO HW.
pub struct GPIO {
- registers: NullLock<Registers>,
+ registers: IRQSafeNullLock<Registers>,
- inner: NullLock<GPIOInner>,
+ inner: IRQSafeNullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
@@ -96,7 +96,7 @@
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
@@ -138,7 +138,7 @@
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
- registers: NullLock::new(Registers::new(base_addr)),
+ registers: IRQSafeNullLock::new(Registers::new(base_addr)),
- inner: NullLock::new(GPIOInner::new(mmio_start_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
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ Self {
+ wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(base_addr)),
+ ro_registers: ReadOnlyRegisters::new(base_addr),
+ wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)),
+ ro_registers: ReadOnlyRegisters::new(mmio_start_addr),
+ 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
+ ///
+ /// - The user must ensure to provide the correct `base_addr`.
+ pub const unsafe fn new(_local_base_addr: usize, periph_base_addr: usize) -> Self {
+ /// - The user must ensure to provide a correct MMIO start address.
+ pub const unsafe fn new(_local_mmio_start_addr: usize, periph_mmio_start_addr: usize) -> 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
@@ -232,9 +317,10 @@
@@ -229,12 +314,18 @@
}
impl PL011Uart {
+ /// Create an instance.
+ ///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
- pub const unsafe fn new(base_addr: usize) -> Self {
+ pub const unsafe fn new(base_addr: usize, irq_number: bsp::device_driver::IRQNumber) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
- pub const unsafe fn new(mmio_start_addr: usize) -> Self {
+ pub const unsafe fn new(
+ mmio_start_addr: usize,
+ irq_number: bsp::device_driver::IRQNumber,
+ ) -> Self {
Self {
- inner: NullLock::new(PL011UartInner::new(base_addr)),
+ inner: IRQSafeNullLock::new(PL011UartInner::new(base_addr)),
- inner: NullLock::new(PL011UartInner::new(mmio_start_addr)),
+ inner: IRQSafeNullLock::new(PL011UartInner::new(mmio_start_addr)),
+ irq_number,
}
}
}
@@ -255,6 +341,21 @@
@@ -255,6 +346,21 @@
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 {
@@ -286,25 +387,7 @@
@@ -286,25 +392,7 @@
impl console::interface::Read for PL011Uart {
fn read_char(&self) -> char {
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) {
@@ -329,3 +412,25 @@
@@ -329,3 +417,25 @@
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
--- 13_integrated_testing/src/bsp/raspberrypi/memory.rs
+++ 14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs
@@ -27,22 +27,24 @@
/// 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")]
@@ -39,10 +39,12 @@
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 END_INCLUSIVE: usize = 0x4000_FFFF;
+ pub const BASE: usize = 0x3F00_0000;
+ pub const PERIPHERAL_INTERRUPT_CONTROLLER_BASE: usize = BASE + 0x0000_B200;
+ pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
+ pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
+ pub const LOCAL_INTERRUPT_CONTROLLER_BASE: usize = 0x4000_0000;
+ pub const END_INCLUSIVE: usize = 0x4000_FFFF;
- pub const START: usize = 0x3F00_0000;
- pub const GPIO_START: usize = START + GPIO_OFFSET;
- pub const PL011_UART_START: usize = START + UART_OFFSET;
- pub const END_INCLUSIVE: usize = 0x4000_FFFF;
+ pub const START: usize = 0x3F00_0000;
+ pub const PERIPHERAL_INTERRUPT_CONTROLLER_START: usize = START + 0x0000_B200;
+ pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const LOCAL_INTERRUPT_CONTROLLER_START: usize = 0x4000_0000;
+ pub const END_INCLUSIVE: usize = 0x4000_FFFF;
}
/// Physical devices.
@@ -50,10 +52,12 @@
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 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;
@@ -53,6 +55,8 @@
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
+ pub const GICD_START: usize = 0xFF84_1000;
+ pub const GICC_START: 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
--- 13_integrated_testing/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 @@
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 { 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 {
+ device_driver::PL011Uart::new(
+ memory::map::mmio::PL011_UART_BASE,
+ memory::map::mmio::PL011_UART_START,
+ 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")]
+static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe {
+ device_driver::InterruptController::new(
+ memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_BASE,
+ memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_BASE,
+ memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_START,
+ memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_START,
+ )
+};
+
+#[cfg(feature = "bsp_rpi4")]
+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
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(gicd_base_addr: usize, gicc_base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(gicd_mmio_start_addr: usize, gicc_mmio_start_addr: usize) -> Self {
Self {
gicd: gicd::GICD::new(gicd_base_addr),
gicc: gicc::GICC::new(gicc_base_addr),
gicd: gicd::GICD::new(gicd_mmio_start_addr),
gicc: gicc::GICC::new(gicc_mmio_start_addr),
handler_table: InitStateLock::new([None; Self::NUM_IRQS]),
}
}

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

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

@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper<RegisterBlock>;
// 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.
pub struct GPIO {
registers: IRQSafeNullLock<Registers>,
inner: IRQSafeNullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

@ -78,10 +78,10 @@ impl InterruptController {
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(_local_base_addr: usize, periph_base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(_local_mmio_start_addr: usize, periph_mmio_start_addr: usize) -> 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
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> Self {
Self {
wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(base_addr)),
ro_registers: ReadOnlyRegisters::new(base_addr),
wo_registers: IRQSafeNullLock::new(WriteOnlyRegisters::new(mmio_start_addr)),
ro_registers: ReadOnlyRegisters::new(mmio_start_addr),
handler_table: InitStateLock::new([None; InterruptController::NUM_PERIPHERAL_IRQS]),
}
}

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

@ -16,11 +16,11 @@ pub mod memory;
use super::device_driver;
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 {
device_driver::PL011Uart::new(
memory::map::mmio::PL011_UART_BASE,
memory::map::mmio::PL011_UART_START,
exception::asynchronous::irq_map::PL011_UART,
)
};
@ -28,14 +28,14 @@ static PL011_UART: device_driver::PL011Uart = unsafe {
#[cfg(feature = "bsp_rpi3")]
static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe {
device_driver::InterruptController::new(
memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_BASE,
memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_BASE,
memory::map::mmio::LOCAL_INTERRUPT_CONTROLLER_START,
memory::map::mmio::PERIPHERAL_INTERRUPT_CONTROLLER_START,
)
};
#[cfg(feature = "bsp_rpi4")]
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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -27,24 +27,24 @@ extern "C" {
/// 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 {
use super::*;
pub const BASE: usize = 0x3F00_0000;
pub const PERIPHERAL_INTERRUPT_CONTROLLER_BASE: usize = BASE + 0x0000_B200;
pub const GPIO_BASE: usize = BASE + GPIO_OFFSET;
pub const PL011_UART_BASE: usize = BASE + UART_OFFSET;
pub const LOCAL_INTERRUPT_CONTROLLER_BASE: usize = 0x4000_0000;
pub const END_INCLUSIVE: usize = 0x4000_FFFF;
pub const START: usize = 0x3F00_0000;
pub const PERIPHERAL_INTERRUPT_CONTROLLER_START: usize = START + 0x0000_B200;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const LOCAL_INTERRUPT_CONTROLLER_START: usize = 0x4000_0000;
pub const END_INCLUSIVE: usize = 0x4000_FFFF;
}
/// Physical devices.
@ -52,12 +52,12 @@ pub(super) mod map {
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 GICD_BASE: usize = 0xFF84_1000;
pub const GICC_BASE: usize = 0xFF84_2000;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
pub const GICD_START: usize = 0xFF84_1000;
pub const GICC_START: usize = 0xFF84_2000;
pub const END_INCLUSIVE: usize = 0xFF84_FFFF;
}
}

@ -55,7 +55,7 @@ fn ro_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
//--------------------------------------------------------------------------------------------------
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.
pub struct GPIO {
registers: NullLock<Registers>,
inner: NullLock<GPIOInner>,
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO {
impl GPIOInner {
/// Create an instance.
///
/// # Safety
///
/// - The user must ensure to provide the correct `base_addr`.
pub const unsafe fn new(base_addr: usize) -> Self {
/// - The user must ensure to provide a correct MMIO start address.
pub const unsafe fn new(mmio_start_addr: usize) -> 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
/// RX to pin 15
pub fn map_pl011_uart(&mut self) {
// Map to pins.
self.registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
self.registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
self.registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
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.registers;
r.lock(|registers| {
// Map to pins.
registers
.GPFSEL1
.modify(GPFSEL1::FSEL14::AltFunc0 + GPFSEL1::FSEL15::AltFunc0);
// Enable pins 14 and 15.
registers.GPPUD.set(0);
cpu::spin_for_cycles(150);
registers
.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
cpu::spin_for_cycles(150);
registers.GPPUDCLK0.set(0);
})
let mut r = &self.inner;
r.lock(|inner| inner.map_pl011_uart())
}
}

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

@ -15,7 +15,7 @@ pub mod memory;
use super::device_driver;
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 { 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
/// 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
///
/// - Use only for printing during a panic.
pub unsafe fn panic_console_out() -> impl fmt::Write {
let mut uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_BASE);
uart.init();
uart
let mut panic_gpio = device_driver::PanicGPIO::new(memory::map::mmio::GPIO_START);
let mut panic_uart = device_driver::PanicUart::new(memory::map::mmio::PL011_UART_START);
panic_gpio.map_pl011_uart();
panic_uart.init();
panic_uart
}
/// Return a reference to the console.

@ -23,19 +23,19 @@ extern "C" {
/// The board's memory map.
#[rustfmt::skip]
pub(super) mod map {
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 {
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 START: usize = 0x3F00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
/// Physical devices.
@ -43,9 +43,9 @@ pub(super) mod map {
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 START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET;
}
}

Loading…
Cancel
Save