From 677b274a1f6e49b184c3d1408425d3a2bef00695 Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Wed, 30 Sep 2020 21:51:31 +0200 Subject: [PATCH] Add a panic version of the GPIO to panic!() --- 01_wait_forever/README.md | 2 +- 06_drivers_gpio_uart/README.md | 139 +++++++++------ .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 06_drivers_gpio_uart/src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 18 +- 07_uart_chainloader/README.md | 33 +--- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 07_uart_chainloader/src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 12 +- 08_timestamps/README.md | 33 +--- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 08_timestamps/src/bsp/raspberrypi.rs | 4 +- 08_timestamps/src/bsp/raspberrypi/console.rs | 13 +- 08_timestamps/src/bsp/raspberrypi/memory.rs | 18 +- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 09_hw_debug_JTAG/src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 18 +- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 10_privilege_level/src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 18 +- 11_virtual_memory/README.md | 26 +-- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 11_virtual_memory/src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 24 +-- .../src/bsp/raspberrypi/memory/mmu.rs | 4 +- 12_exceptions_part1_groundwork/README.md | 4 +- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- .../src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 24 +-- .../src/bsp/raspberrypi/memory/mmu.rs | 2 +- 13_integrated_testing/README.md | 3 +- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- 13_integrated_testing/src/bsp/raspberrypi.rs | 4 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 24 +-- .../src/bsp/raspberrypi/memory/mmu.rs | 2 +- 14_exceptions_part2_peripheral_IRQs/README.md | 160 ++++++++---------- .../src/bsp/device_driver/arm/gicv2.rs | 8 +- .../src/bsp/device_driver/arm/gicv2/gicc.rs | 6 +- .../src/bsp/device_driver/arm/gicv2/gicd.rs | 12 +- .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../bcm/bcm2xxx_interrupt_controller.rs | 6 +- .../peripheral_ic.rs | 8 +- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 17 +- .../src/bsp/raspberrypi.rs | 10 +- .../src/bsp/raspberrypi/console.rs | 13 +- .../src/bsp/raspberrypi/memory.rs | 32 ++-- .../src/bsp/raspberrypi/memory/mmu.rs | 2 +- X1_JTAG_boot/jtag_boot_rpi3.img | Bin 7136 -> 7272 bytes X1_JTAG_boot/jtag_boot_rpi4.img | Bin 7120 -> 7240 bytes .../src/bsp/device_driver/bcm/bcm2xxx_gpio.rs | 69 +++++--- .../device_driver/bcm/bcm2xxx_pl011_uart.rs | 12 +- X1_JTAG_boot/src/bsp/raspberrypi.rs | 4 +- X1_JTAG_boot/src/bsp/raspberrypi/console.rs | 13 +- X1_JTAG_boot/src/bsp/raspberrypi/memory.rs | 18 +- 69 files changed, 957 insertions(+), 690 deletions(-) diff --git a/01_wait_forever/README.md b/01_wait_forever/README.md index a35c499b..52f7f839 100644 --- a/01_wait_forever/README.md +++ b/01_wait_forever/README.md @@ -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]` diff --git a/06_drivers_gpio_uart/README.md b/06_drivers_gpio_uart/README.md index 857fb7f9..d07a65da 100644 --- a/06_drivers_gpio_uart/README.md +++ b/06_drivers_gpio_uart/README.md @@ -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 @@ -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, ++ inner: NullLock, +} + +//-------------------------------------------------------------------------------------------------- +// 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 diff --git a/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index ccd1341e..7beea1db 100644 --- a/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/06_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/06_drivers_gpio_uart/src/bsp/raspberrypi.rs b/06_drivers_gpio_uart/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/06_drivers_gpio_uart/src/bsp/raspberrypi.rs +++ b/06_drivers_gpio_uart/src/bsp/raspberrypi.rs @@ -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 diff --git a/06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs b/06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs +++ b/06_drivers_gpio_uart/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs b/06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs index ef9746af..0b859498 100644 --- a/06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs +++ b/06_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/07_uart_chainloader/README.md b/07_uart_chainloader/README.md index ab2b6f30..7ac6a013 100644 --- a/07_uart_chainloader/README.md +++ b/07_uart_chainloader/README.md @@ -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 } diff --git a/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index b15efad5..05e73fc0 100644 --- a/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/07_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/07_uart_chainloader/src/bsp/raspberrypi.rs b/07_uart_chainloader/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/07_uart_chainloader/src/bsp/raspberrypi.rs +++ b/07_uart_chainloader/src/bsp/raspberrypi.rs @@ -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 diff --git a/07_uart_chainloader/src/bsp/raspberrypi/console.rs b/07_uart_chainloader/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/07_uart_chainloader/src/bsp/raspberrypi/console.rs +++ b/07_uart_chainloader/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/07_uart_chainloader/src/bsp/raspberrypi/memory.rs b/07_uart_chainloader/src/bsp/raspberrypi/memory.rs index 826fd8cc..f871def3 100644 --- a/07_uart_chainloader/src/bsp/raspberrypi/memory.rs +++ b/07_uart_chainloader/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/08_timestamps/README.md b/08_timestamps/README.md index 4ddbce50..a8816109 100644 --- a/08_timestamps/README.md +++ b/08_timestamps/README.md @@ -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 } diff --git a/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/08_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/08_timestamps/src/bsp/raspberrypi.rs b/08_timestamps/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/08_timestamps/src/bsp/raspberrypi.rs +++ b/08_timestamps/src/bsp/raspberrypi.rs @@ -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 diff --git a/08_timestamps/src/bsp/raspberrypi/console.rs b/08_timestamps/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/08_timestamps/src/bsp/raspberrypi/console.rs +++ b/08_timestamps/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/08_timestamps/src/bsp/raspberrypi/memory.rs b/08_timestamps/src/bsp/raspberrypi/memory.rs index ef9746af..0b859498 100644 --- a/08_timestamps/src/bsp/raspberrypi/memory.rs +++ b/08_timestamps/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/09_hw_debug_JTAG/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/09_hw_debug_JTAG/src/bsp/raspberrypi.rs b/09_hw_debug_JTAG/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/09_hw_debug_JTAG/src/bsp/raspberrypi.rs +++ b/09_hw_debug_JTAG/src/bsp/raspberrypi.rs @@ -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 diff --git a/09_hw_debug_JTAG/src/bsp/raspberrypi/console.rs b/09_hw_debug_JTAG/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/09_hw_debug_JTAG/src/bsp/raspberrypi/console.rs +++ b/09_hw_debug_JTAG/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/09_hw_debug_JTAG/src/bsp/raspberrypi/memory.rs b/09_hw_debug_JTAG/src/bsp/raspberrypi/memory.rs index ef9746af..0b859498 100644 --- a/09_hw_debug_JTAG/src/bsp/raspberrypi/memory.rs +++ b/09_hw_debug_JTAG/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/10_privilege_level/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/10_privilege_level/src/bsp/raspberrypi.rs b/10_privilege_level/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/10_privilege_level/src/bsp/raspberrypi.rs +++ b/10_privilege_level/src/bsp/raspberrypi.rs @@ -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 diff --git a/10_privilege_level/src/bsp/raspberrypi/console.rs b/10_privilege_level/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/10_privilege_level/src/bsp/raspberrypi/console.rs +++ b/10_privilege_level/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/10_privilege_level/src/bsp/raspberrypi/memory.rs b/10_privilege_level/src/bsp/raspberrypi/memory.rs index ef9746af..0b859498 100644 --- a/10_privilege_level/src/bsp/raspberrypi/memory.rs +++ b/10_privilege_level/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/11_virtual_memory/README.md b/11_virtual_memory/README.md index 7f7aab12..fc828c73 100644 --- a/11_virtual_memory/README.md +++ b/11_virtual_memory/README.md @@ -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 { -+ 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; } } diff --git a/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/11_virtual_memory/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/11_virtual_memory/src/bsp/raspberrypi.rs b/11_virtual_memory/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/11_virtual_memory/src/bsp/raspberrypi.rs +++ b/11_virtual_memory/src/bsp/raspberrypi.rs @@ -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 diff --git a/11_virtual_memory/src/bsp/raspberrypi/console.rs b/11_virtual_memory/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/11_virtual_memory/src/bsp/raspberrypi/console.rs +++ b/11_virtual_memory/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/11_virtual_memory/src/bsp/raspberrypi/memory.rs b/11_virtual_memory/src/bsp/raspberrypi/memory.rs index 8f0b0104..9d4d3065 100644 --- a/11_virtual_memory/src/bsp/raspberrypi/memory.rs +++ b/11_virtual_memory/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs b/11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs index ab100089..00990c7e 100644 --- a/11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs +++ b/11_virtual_memory/src/bsp/raspberrypi/memory/mmu.rs @@ -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 { } fn mmio_range_inclusive() -> RangeInclusive { - RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) + RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE) } //-------------------------------------------------------------------------------------------------- diff --git a/12_exceptions_part1_groundwork/README.md b/12_exceptions_part1_groundwork/README.md index 9227c081..660601bd 100644 --- a/12_exceptions_part1_groundwork/README.md +++ b/12_exceptions_part1_groundwork/README.md @@ -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 { - RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) + RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE) } diff -uNr 11_virtual_memory/src/bsp.rs 12_exceptions_part1_groundwork/src/bsp.rs diff --git a/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/12_exceptions_part1_groundwork/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/12_exceptions_part1_groundwork/src/bsp/raspberrypi.rs b/12_exceptions_part1_groundwork/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/12_exceptions_part1_groundwork/src/bsp/raspberrypi.rs +++ b/12_exceptions_part1_groundwork/src/bsp/raspberrypi.rs @@ -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 diff --git a/12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs b/12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs +++ b/12_exceptions_part1_groundwork/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory.rs b/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory.rs index 8f0b0104..9d4d3065 100644 --- a/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory.rs +++ b/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs b/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs index 1f702192..5658ddb6 100644 --- a/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs +++ b/12_exceptions_part1_groundwork/src/bsp/raspberrypi/memory/mmu.rs @@ -55,7 +55,7 @@ fn ro_range_inclusive() -> RangeInclusive { } fn mmio_range_inclusive() -> RangeInclusive { - RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) + RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE) } //-------------------------------------------------------------------------------------------------- diff --git a/13_integrated_testing/README.md b/13_integrated_testing/README.md index 997df3f7..94a52ebf 100644 --- a/13_integrated_testing/README.md +++ b/13_integrated_testing/README.md @@ -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 } diff --git a/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 77fd5d91..0b01db4b 100644 --- a/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/13_integrated_testing/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/13_integrated_testing/src/bsp/raspberrypi.rs b/13_integrated_testing/src/bsp/raspberrypi.rs index c976cc29..10888d37 100644 --- a/13_integrated_testing/src/bsp/raspberrypi.rs +++ b/13_integrated_testing/src/bsp/raspberrypi.rs @@ -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 diff --git a/13_integrated_testing/src/bsp/raspberrypi/console.rs b/13_integrated_testing/src/bsp/raspberrypi/console.rs index 90011da6..16b2f59b 100644 --- a/13_integrated_testing/src/bsp/raspberrypi/console.rs +++ b/13_integrated_testing/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/13_integrated_testing/src/bsp/raspberrypi/memory.rs b/13_integrated_testing/src/bsp/raspberrypi/memory.rs index 8f0b0104..9d4d3065 100644 --- a/13_integrated_testing/src/bsp/raspberrypi/memory.rs +++ b/13_integrated_testing/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/13_integrated_testing/src/bsp/raspberrypi/memory/mmu.rs b/13_integrated_testing/src/bsp/raspberrypi/memory/mmu.rs index 97130c60..d5078b5a 100644 --- a/13_integrated_testing/src/bsp/raspberrypi/memory/mmu.rs +++ b/13_integrated_testing/src/bsp/raspberrypi/memory/mmu.rs @@ -55,7 +55,7 @@ fn ro_range_inclusive() -> RangeInclusive { } fn mmio_range_inclusive() -> RangeInclusive { - RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) + RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE) } //-------------------------------------------------------------------------------------------------- diff --git a/14_exceptions_part2_peripheral_IRQs/README.md b/14_exceptions_part2_peripheral_IRQs/README.md index 013ec600..41486728 100644 --- a/14_exceptions_part2_peripheral_IRQs/README.md +++ b/14_exceptions_part2_peripheral_IRQs/README.md @@ -524,7 +524,7 @@ impl interface::ReadWriteEx for &InitStateLock { fn write(&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; 31]), (0x108 => _reserved2), (0x820 => ITARGETSR: [ReadWrite; 248]), - (0xBFC => @END), + (0x824 => @END), } } @@ -631,7 +631,7 @@ register_structs! { (0x100 => ISENABLER: ReadWrite), (0x104 => _reserved2), (0x800 => ITARGETSR: [ReadOnly; 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; 31]), + (0x108 => _reserved2), + (0x820 => ITARGETSR: [ReadWrite; 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), + (0x104 => _reserved2), + (0x800 => ITARGETSR: [ReadOnly; 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: IRQSafeNullLock, +- inner: NullLock, ++ inner: IRQSafeNullLock, } //-------------------------------------------------------------------------------------------------- -@@ -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) +}; //-------------------------------------------------------------------------------------------------- diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2.rs index 18654e6f..28d4d4e1 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2.rs @@ -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]), } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicc.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicc.rs index 0c877f32..c6708cdc 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicc.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicc.rs @@ -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), } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicd.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicd.rs index b0d18215..33efd049 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicd.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/arm/gicv2/gicd.rs @@ -48,7 +48,7 @@ register_structs! { (0x104 => ISENABLER: [ReadWrite; 31]), (0x108 => _reserved2), (0x820 => ITARGETSR: [ReadWrite; 248]), - (0xBFC => @END), + (0x824 => @END), } } @@ -59,7 +59,7 @@ register_structs! { (0x100 => ISENABLER: ReadWrite), (0x104 => _reserved2), (0x800 => ITARGETSR: [ReadOnly; 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), } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs index 5b9f6aee..761dea0b 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs @@ -79,24 +79,31 @@ type Registers = MMIODerefWrapper; // 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, + inner: IRQSafeNullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs index 52708b2d..6b11224b 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs @@ -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), } } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs index 000d959e..571cc0af 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs @@ -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]), } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 045d323f..cef085f3 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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, } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs index aa395411..25af58d6 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi.rs @@ -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) }; //-------------------------------------------------------------------------------------------------- diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/console.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/console.rs index 90011da6..16b2f59b 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/console.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs index b4338a51..7a4078c7 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory.rs @@ -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; } } diff --git a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs index 97130c60..d5078b5a 100644 --- a/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs +++ b/14_exceptions_part2_peripheral_IRQs/src/bsp/raspberrypi/memory/mmu.rs @@ -55,7 +55,7 @@ fn ro_range_inclusive() -> RangeInclusive { } fn mmio_range_inclusive() -> RangeInclusive { - RangeInclusive::new(memory_map::mmio::BASE, memory_map::mmio::END_INCLUSIVE) + RangeInclusive::new(memory_map::mmio::START, memory_map::mmio::END_INCLUSIVE) } //-------------------------------------------------------------------------------------------------- diff --git a/X1_JTAG_boot/jtag_boot_rpi3.img b/X1_JTAG_boot/jtag_boot_rpi3.img index b577cbc43c961c7e73883d1cc62425c91c919970..ffb8a905b9c3b9d5aa92b9e54eb09eafa5795ac2 100755 GIT binary patch delta 1626 zcmb7DU1%It6h3!mXEVF`DT$l?O**sr+w3H@jj>Hg#NBK{OZ?an}>?VCkq0+9Pl*ldtSp9E(Kz=ixTK*O0Jy(R+vX}L#eB0@aG#>6Lt%Ps5! zG5IJ_=>}r?DyPo(hZmb@ei&#m;?PGSliY|%x(of$LWmk^K`*ruy(AJ^Y8CZC0%uiF zzX!x&wS|te!;VpJ&waEG9kT1nf*Cl}L%%*&%ieRe2!&?$jbp#Ju#=WTP(Jv_li!u_ z=z|yQLP(KyNr7|&ri>HVJE4j{7>42FsRf=s6QyA>lT1LAUWL2IiikNl9&e@7&_<`E zO!CFmHk3=~1$*DBIPs&5dtPy5lCJjsWlf6bo@(^;Y7*qGG-Q%)^i7=-n6jz(wK~QORN!c`L_w} z98xZIPU6Prl}lY~xJI0-;++vKMCgq^C>v=9c7>=HTd`}pB>mbt&@3;#^X@geY!Rg$ zQ05~3OF+6({{N|fv*#*ee;0s+{!IYy1$hd|S6SqXU7~LKvXL|`rY!}hxq{z~2YCZl znoMn{)A@G0$vP-k>bIK=AYL8^@W^d(9h+|{FUm^=(Y5rY03M!$V7Xzklk$7diwa`O z5??DAhq#BYSKnkSRf;zopw$>rgWtw5(37VF^wlAaZB`u-!WtWtwK{xad=SVA0L^AB)~J?B*fzmF|=k310fSs)TH$FObVt(jxQwrvwed@Sf&(dH#9 z%=!at&mP%Ywb}E$#Fhdbq0uJGJ?XdRqqaTgm)RG-z2p`ne&4PUo9Jw6diSZ+iJ52a zPtEdk)qoX+Wj99y{&%sje7(VLr-j%6R9Ji2f`6wlA7CH*J4QdZ<9FEG+=q^*W{y9t zo|>9DF+HHVi~qoH+xB+0#PDJDk)sF3m>LL^AWH=Lj%g5qLFfl3n1vfqt<-bDd--hJ wc(vx}x65Li6}}J2ED?OT{#!d-wec-RgSP`)AuDOf_CAJJTaW84mJP-J0_~8(egFUf delta 1437 zcmY*YOKclO82)E>9j|SY%8}z&-0nJV<3}OJ6q+a;>LzM&(mcTGffH$zKpQHhC_#do zZ3N;e)X}8kAr6TuL^mK3a8kt*LNU2eA<;%WA|Vc&!ohZOXb%W19?L)8wW^LZGy6a0 z|GxRZ*-D?@dpShTe{s+t9e+r$Kmb9+15vgjW=D2I zw1zR=-lFmR@VOw>2Z2_il9qvdwidN%4)n*D0@TO}S~Wtnsz_)xB5DBw3o58T0>&X7 zrDZlMWxQ@TZ9|9bxbb1*U^q#?Pr2BqQkSsQ$!DCTzh#VZrg9;fqwzwLo*?qxHvnfF^tt^S{Kb7+ zhH>_iVZ6t|`9WigZ2xx*>Te>@q6BLdyo|Hul`NjS?EL+cxp+B5&y-13eq-rg_hcl)L1iS9z_Sh{!vQ%MC&Dq19IYOJx`qUm90DoG z#&J^Fh$9gv5^*632l{!N0LppV_O1??D8K7bN?P)>OZKI%d~58$i~0=@W@kG>O*v3Yq+AThQj zC))7I@(lhTTqFthw|v|~Vl=)K!_I!K>2{*&7#d}#9Gk+`Lq)suI%!jTDBjS+ALl^6 zr}&-gI1#p^Y^U`gQ(M=Ca^yA+c zV^MFnp!cwG?+{z`KJ6a!Vq0-|8!NyxbNCeD4KGXh#vWO8)MC~Efdzf zY}t36-SR(7-e)A>>-(z1tUfXJ@7+UYeX~*1;o-e)eUcTe#(CzXT4ccdWt(8f5_t%Wg7eYA{R!Y#`X1 zvNA^OCKYo9Xzm}`%&*U^eZX8C7kr=NXUy~K8cDR;)IrCP}sSfKMya)G%+K3wCW6aNFNM}@Tj diff --git a/X1_JTAG_boot/jtag_boot_rpi4.img b/X1_JTAG_boot/jtag_boot_rpi4.img index 3c21930e23e7702176a0a3e9debe18f2ec4e6651..81d366b000b6275f95181f48debd2cd1afe62d44 100755 GIT binary patch delta 1471 zcmbVMUuaup6hGg+`E!%CUDM@HleEiCnh$#K)5S32wNHeZ-Ho z6$5lDVv@HIw&V4&te;s;0Z#|5jsQ&%SQJ6L4v0Xii;lC$OydKaZS>b9$WhzIlI`B; zHR-kQ-k0tjxfU(j{aOmrOn?dzA^15d)Xb+U|wZJkP)E{ERZ5_ za6;s7D2n3I3V}p9j2SLOX^<~uDsUf()h@~-Hd*MVCe)`>AuUhVT*!Q4+*{=*eh?6| zxt^}a%&GD@Qz3K0dPY@cn`{Ijz%6K z*h_7gPePp}!tJjB#&_&9a98!MV~S&n@{ZapHBMP4-~ZVU^(Evq4~2~I^_RJ23w(M@ zZ}Y;~W`I^BAltT+v=$+j7v8*tWUd1oyy;1Jem)CsiUd#ft5}C*n+j!ebh^L;e{srY9l~T2EFvH zHHqD{KF1X$77=1Cxa{hU8jomkKbsH+oJEOBPsFg5SLCXdU`3#hGFe#V=ETxT+hx+S z+N08SYD+A}OFg>=2=|J_hMGIs>88)PDXBEn{IQ8UBeC0#8W((srJd*5sXZTX%M#n; zOrWQfb|#2wo^yq{LY$RcPrdDa(Q(C%Z9{QuC%|`iyNPxR;*R@S83uyNX& zgbdp-A>?6p&*j*>Sr5}sfQAM^|7$h$yqPU|!~ST8?oPGqI&Rp<+XeQy=OFo+ZF@Wi z;s(#T++@#eZhGeBhjVjUU9TR6{nn%n&jaiWPrt9jq9XrFD&8K-UN(4;FvI&qVjhrY!SeP}1Ow1Rt) z+={}`2|YU<{@ETfHepe4mB`lYVN0yw1QF*{5JYbD!KM@I=z|8F@jLh4YEGftmlwdq{|FNuvd>h@c`uHvyJY1Rl+* z;&-i9%V!d$c2fb*9IQS_2Sh#n5!T!np->TX`Km%Cw6E!^iIa2a>9_2`2FqCfZA*EJ9C?yG0k{+mBL?MxJWi&w8+0$ zy5Bt)igBSBPAsFK#tvvIh^?T25(2cWUKvv=Yr0o(woW){G0wj0sq9}YERj#TAMNl(vs z-1}n=sPI_wG*rIm(bEc!Kk9%xHS9RX*>y+IiD~6ss4%}P?v48>Hg{z^?u`kc$B2)f ztZOXmIwI6GcF7g%!aK<;Hbl(UqU=}Kh`XlIXfA@c`&!9xl9GX`BP=dgg=hN9Tk>Vn zW$fjj;x_MEYPfu5+XxY;#x}QqBP?>Wt86?#CE=XL7J4>>@mM+AJ4S@6#?H9M&}G@) z)9eM$`#jR?9TJMe?11+WHq%;6_fGA6+-vz>JD6b&uR@M9*?08eqMbtx<~nctIAwEP zuzlNw3tsky?=oBQKSWNjy5E<$=&`^T=JWgJ=BH<08lGR^#oc}@j_op64?g$eJ~;7| z`ozUB#_fuP(~@F60owMY!+JYw+k}(N_=gHBeO7obVA)mMf5-M?puqu1KnGY&8&fTw zKkU5C3T+=pYp%1ljCQ^)xM;_xXP; // 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, + inner: NullLock, } //-------------------------------------------------------------------------------------------------- // 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()) } } diff --git a/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs b/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs index 4fa3b134..fe3be402 100644 --- a/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ b/X1_JTAG_boot/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs @@ -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)), } } } diff --git a/X1_JTAG_boot/src/bsp/raspberrypi.rs b/X1_JTAG_boot/src/bsp/raspberrypi.rs index 36943734..a4a81232 100644 --- a/X1_JTAG_boot/src/bsp/raspberrypi.rs +++ b/X1_JTAG_boot/src/bsp/raspberrypi.rs @@ -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) }; diff --git a/X1_JTAG_boot/src/bsp/raspberrypi/console.rs b/X1_JTAG_boot/src/bsp/raspberrypi/console.rs index 73dd8916..d1b60dd8 100644 --- a/X1_JTAG_boot/src/bsp/raspberrypi/console.rs +++ b/X1_JTAG_boot/src/bsp/raspberrypi/console.rs @@ -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. diff --git a/X1_JTAG_boot/src/bsp/raspberrypi/memory.rs b/X1_JTAG_boot/src/bsp/raspberrypi/memory.rs index ef9746af..0b859498 100644 --- a/X1_JTAG_boot/src/bsp/raspberrypi/memory.rs +++ b/X1_JTAG_boot/src/bsp/raspberrypi/memory.rs @@ -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; } }