Rework driver subsystem

- Remove the panic version of the GPIO and UART driver. While they were a neat
  idea, it proved tedious to drag them along different tutorials where the
  virtual memory situation kept on changing. Actually, not much is lost, since
  the benefit was only of theoretical nature until now, since everything is
  still single-threaded with NullLocks. It is still possible to re-introduce
  them later.

- Refactor driver bringup starting with tutorial 14. Instantiating the drivers
  only when we are already capable of using the remapped MMIO address makes the
  kernel a lot more robust, and the drivers need not care whether their MMIO
  addresses are good to use already or not.

- Use console and irq_manager references from the generic kernel code. This
  improves decoupling from the BSP, and is needed as a basis for tutorial 14.
pull/165/head
Andre Richter 2 years ago
parent 4ab609ba39
commit fec4f9b6f2
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

3
.gitignore vendored

@ -3,7 +3,8 @@
**/kernel8.img **/kernel8.img
node_modules node_modules
.bundle
.vendor .vendor
Gemfile.lock Gemfile.lock
package-lock.json package*.json

@ -188,13 +188,15 @@ diff -uNr 02_runtime_init/src/bsp/raspberrypi.rs 03_hacky_hello_world/src/bsp/ra
diff -uNr 02_runtime_init/src/console.rs 03_hacky_hello_world/src/console.rs diff -uNr 02_runtime_init/src/console.rs 03_hacky_hello_world/src/console.rs
--- 02_runtime_init/src/console.rs --- 02_runtime_init/src/console.rs
+++ 03_hacky_hello_world/src/console.rs +++ 03_hacky_hello_world/src/console.rs
@@ -0,0 +1,19 @@ @@ -0,0 +1,32 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
+ +
+//! System console. +//! System console.
+ +
+use crate::bsp;
+
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Public Definitions +// Public Definitions
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
@ -208,6 +210,17 @@ diff -uNr 02_runtime_init/src/console.rs 03_hacky_hello_world/src/console.rs
+ /// intention. + /// intention.
+ pub use core::fmt::Write; + pub use core::fmt::Write;
+} +}
+
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+/// Return a reference to the console.
+///
+/// This is the global console used by all printing macros.
+pub fn console() -> impl interface::Write {
+ bsp::console::console()
+}
diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs
--- 02_runtime_init/src/main.rs --- 02_runtime_init/src/main.rs
@ -317,7 +330,7 @@ diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
+ +
+//! Printing. +//! Printing.
+ +
+use crate::{bsp, console}; +use crate::console;
+use core::fmt; +use core::fmt;
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
@ -328,7 +341,7 @@ diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
+pub fn _print(args: fmt::Arguments) { +pub fn _print(args: fmt::Arguments) {
+ use console::interface::Write; + use console::interface::Write;
+ +
+ bsp::console::console().write_fmt(args).unwrap(); + console::console().write_fmt(args).unwrap();
+} +}
+ +
+/// Prints without a newline. +/// Prints without a newline.

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -17,3 +19,14 @@ pub mod interface {
/// intention. /// intention.
pub use core::fmt::Write; pub use core::fmt::Write;
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> impl interface::Write {
bsp::console::console()
}

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -15,7 +15,7 @@ use core::fmt;
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; use console::interface::Write;
bsp::console::console().write_fmt(args).unwrap(); console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -148,7 +148,7 @@ diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/console.rs 04_safe_globals/sr
} }
Ok(()) Ok(())
@@ -41,7 +80,37 @@ @@ -41,7 +80,39 @@
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -164,9 +164,9 @@ diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/console.rs 04_safe_globals/sr
/// Return a reference to the console. /// Return a reference to the console.
-pub fn console() -> impl console::interface::Write { -pub fn console() -> impl console::interface::Write {
- QEMUOutput {} - QEMUOutput {}
+pub fn console() -> &'static impl console::interface::All { +pub fn console() -> &'static dyn console::interface::All {
+ &QEMU_OUTPUT + &QEMU_OUTPUT
+} }
+ +
+//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------
+// OS Interface Code +// OS Interface Code
@ -187,12 +187,14 @@ diff -uNr 03_hacky_hello_world/src/bsp/raspberrypi/console.rs 04_safe_globals/sr
+ fn chars_written(&self) -> usize { + fn chars_written(&self) -> usize {
+ self.inner.lock(|inner| inner.chars_written) + self.inner.lock(|inner| inner.chars_written)
+ } + }
} +}
+
+impl console::interface::All for QEMUOutput {}
diff -uNr 03_hacky_hello_world/src/console.rs 04_safe_globals/src/console.rs diff -uNr 03_hacky_hello_world/src/console.rs 04_safe_globals/src/console.rs
--- 03_hacky_hello_world/src/console.rs --- 03_hacky_hello_world/src/console.rs
+++ 04_safe_globals/src/console.rs +++ 04_safe_globals/src/console.rs
@@ -10,10 +10,22 @@ @@ -12,12 +12,24 @@
/// Console interfaces. /// Console interfaces.
pub mod interface { pub mod interface {
@ -218,7 +220,17 @@ diff -uNr 03_hacky_hello_world/src/console.rs 04_safe_globals/src/console.rs
+ } + }
+ +
+ /// Trait alias for a full-fledged console. + /// Trait alias for a full-fledged console.
+ pub trait All = Write + Statistics; + pub trait All: Write + Statistics {}
}
//--------------------------------------------------------------------------------------------------
@@ -27,6 +39,6 @@
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
-pub fn console() -> impl interface::Write {
+pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }
diff -uNr 03_hacky_hello_world/src/main.rs 04_safe_globals/src/main.rs diff -uNr 03_hacky_hello_world/src/main.rs 04_safe_globals/src/main.rs
@ -240,25 +252,35 @@ diff -uNr 03_hacky_hello_world/src/main.rs 04_safe_globals/src/main.rs
/// Early init code. /// Early init code.
/// ///
@@ -124,7 +126,15 @@ @@ -124,7 +126,12 @@
/// ///
/// - Only a single core must be active and running this function. /// - Only a single core must be active and running this function.
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
- println!("Hello from Rust!"); - println!("Hello from Rust!");
+ use console::interface::Statistics; + use console::console;
- panic!("Stopping here.") - panic!("Stopping here.")
+ println!("[0] Hello from Rust!"); + println!("[0] Hello from Rust!");
+ +
+ println!( + println!("[1] Chars written: {}", console().chars_written());
+ "[1] Chars written: {}",
+ bsp::console::console().chars_written()
+ );
+ +
+ println!("[2] Stopping here."); + println!("[2] Stopping here.");
+ cpu::wait_forever() + cpu::wait_forever()
} }
diff -uNr 03_hacky_hello_world/src/print.rs 04_safe_globals/src/print.rs
--- 03_hacky_hello_world/src/print.rs
+++ 04_safe_globals/src/print.rs
@@ -13,8 +13,6 @@
#[doc(hidden)]
pub fn _print(args: fmt::Arguments) {
- use console::interface::Write;
-
console::console().write_fmt(args).unwrap();
}
diff -uNr 03_hacky_hello_world/src/synchronization.rs 04_safe_globals/src/synchronization.rs diff -uNr 03_hacky_hello_world/src/synchronization.rs 04_safe_globals/src/synchronization.rs
--- 03_hacky_hello_world/src/synchronization.rs --- 03_hacky_hello_world/src/synchronization.rs
+++ 04_safe_globals/src/synchronization.rs +++ 04_safe_globals/src/synchronization.rs

@ -90,7 +90,7 @@ impl QEMUOutput {
} }
/// Return a reference to the console. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&QEMU_OUTPUT &QEMU_OUTPUT
} }
@ -114,3 +114,5 @@ impl console::interface::Statistics for QEMUOutput {
self.inner.lock(|inner| inner.chars_written) self.inner.lock(|inner| inner.chars_written)
} }
} }
impl console::interface::All for QEMUOutput {}

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -27,5 +29,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Statistics; pub trait All: Write + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -126,14 +126,11 @@ mod synchronization;
/// ///
/// - Only a single core must be active and running this function. /// - Only a single core must be active and running this function.
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use console::interface::Statistics; use console::console;
println!("[0] Hello from Rust!"); println!("[0] Hello from Rust!");
println!( println!("[1] Chars written: {}", console().chars_written());
"[1] Chars written: {}",
bsp::console::console().chars_written()
);
println!("[2] Stopping here."); println!("[2] Stopping here.");
cpu::wait_forever() cpu::wait_forever()

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -27,12 +27,6 @@
- `BSP`s now contain a memory map in `src/bsp/raspberrypi/memory.rs`. In the specific case, they - `BSP`s now contain a memory map in `src/bsp/raspberrypi/memory.rs`. In the specific case, they
contain the Raspberry's `MMIO` addresses which are used to instantiate the respective device contain the Raspberry's `MMIO` addresses which are used to instantiate the respective device
drivers. drivers.
- We also modify the `panic!` handler, so that it does not anymore rely on `println!`, which uses
the globally-shared instance of the `UART` that might be locked when an error is encountered (for
now, this can't happen due to the `NullLock`, but with a real lock it becomes an issue).
- Instead, it creates a new UART driver instance, re-initializes the device and uses that one to
print. This increases the chances that the system is able to print a final important message
before it suspends itself.
## Boot it from SD card ## Boot it from SD card
@ -98,8 +92,8 @@ Miniterm 1.0
[0] mingo version 0.5.0 [0] mingo version 0.5.0
[1] Booting on: Raspberry Pi 3 [1] Booting on: Raspberry Pi 3
[2] Drivers loaded: [2] Drivers loaded:
1. BCM GPIO 1. BCM PL011 UART
2. BCM PL011 UART 2. BCM GPIO
[3] Chars written: 117 [3] Chars written: 117
[4] Echoing input now [4] Echoing input now
``` ```
@ -234,7 +228,7 @@ diff -uNr 04_safe_globals/src/_arch/aarch64/cpu.rs 05_drivers_gpio_uart/src/_arc
diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
--- 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs --- 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
+++ 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
@@ -0,0 +1,225 @@ @@ -0,0 +1,228 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
@ -345,16 +339,13 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_g
+/// Abstraction for the associated MMIO registers. +/// Abstraction for the associated MMIO registers.
+type Registers = MMIODerefWrapper<RegisterBlock>; +type Registers = MMIODerefWrapper<RegisterBlock>;
+ +
+//-------------------------------------------------------------------------------------------------- +struct GPIOInner {
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+pub struct GPIOInner {
+ registers: Registers, + registers: Registers,
+} +}
+ +
+// Export the inner struct so that BSPs can use it for the panic handler. +//--------------------------------------------------------------------------------------------------
+pub use GPIOInner as PanicGPIO; +// Public Definitions
+//--------------------------------------------------------------------------------------------------
+ +
+/// Representation of the GPIO HW. +/// Representation of the GPIO HW.
+pub struct GPIO { +pub struct GPIO {
@ -362,7 +353,7 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_g
+} +}
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Public Code +// Private Code
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
+impl GPIOInner { +impl GPIOInner {
@ -385,7 +376,7 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_g
+ // Make an educated guess for a good delay value (Sequence described in the BCM2837 + // Make an educated guess for a good delay value (Sequence described in the BCM2837
+ // peripherals PDF). + // peripherals PDF).
+ // + //
+ // - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz. + // - According to Wikipedia, the fastest RPi4 clocks around 1.5 GHz.
+ // - The Linux 2837 GPIO driver waits 1 µs between the steps. + // - The Linux 2837 GPIO driver waits 1 µs between the steps.
+ // + //
+ // So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs + // So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
@ -432,7 +423,13 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_g
+ } + }
+} +}
+ +
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+impl GPIO { +impl GPIO {
+ pub const COMPATIBLE: &'static str = "BCM GPIO";
+
+ /// Create an instance. + /// Create an instance.
+ /// + ///
+ /// # Safety + /// # Safety
@ -457,14 +454,14 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 05_drivers_g
+ +
+impl driver::interface::DeviceDriver for GPIO { +impl driver::interface::DeviceDriver for GPIO {
+ fn compatible(&self) -> &'static str { + fn compatible(&self) -> &'static str {
+ "BCM GPIO" + Self::COMPATIBLE
+ } + }
+} +}
diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
--- 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs --- 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
+++ 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
@@ -0,0 +1,402 @@ @@ -0,0 +1,407 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
@ -634,18 +631,15 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_dri
+ NonBlocking, + NonBlocking,
+} +}
+ +
+//-------------------------------------------------------------------------------------------------- +struct PL011UartInner {
+// Public Definitions
+//--------------------------------------------------------------------------------------------------
+
+pub struct PL011UartInner {
+ registers: Registers, + registers: Registers,
+ chars_written: usize, + chars_written: usize,
+ chars_read: usize, + chars_read: usize,
+} +}
+ +
+// Export the inner struct so that BSPs can use it for the panic handler. +//--------------------------------------------------------------------------------------------------
+pub use PL011UartInner as PanicUart; +// Public Definitions
+//--------------------------------------------------------------------------------------------------
+ +
+/// Representation of the UART. +/// Representation of the UART.
+pub struct PL011Uart { +pub struct PL011Uart {
@ -653,7 +647,7 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_dri
+} +}
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Public Code +// Private Code
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
+impl PL011UartInner { +impl PL011UartInner {
@ -793,7 +787,13 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_dri
+ } + }
+} +}
+ +
+//--------------------------------------------------------------------------------------------------
+// Public Code
+//--------------------------------------------------------------------------------------------------
+
+impl PL011Uart { +impl PL011Uart {
+ pub const COMPATIBLE: &'static str = "BCM PL011 UART";
+
+ /// Create an instance. + /// Create an instance.
+ /// + ///
+ /// # Safety + /// # Safety
@ -813,7 +813,7 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_dri
+ +
+impl driver::interface::DeviceDriver for PL011Uart { +impl driver::interface::DeviceDriver for PL011Uart {
+ fn compatible(&self) -> &'static str { + fn compatible(&self) -> &'static str {
+ "BCM PL011 UART" + Self::COMPATIBLE
+ } + }
+ +
+ unsafe fn init(&self) -> Result<(), &'static str> { + unsafe fn init(&self) -> Result<(), &'static str> {
@ -867,6 +867,8 @@ diff -uNr 04_safe_globals/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 05_dri
+ self.inner.lock(|inner| inner.chars_read) + self.inner.lock(|inner| inner.chars_read)
+ } + }
+} +}
+
+impl console::interface::All for PL011Uart {}
diff -uNr 04_safe_globals/src/bsp/device_driver/bcm.rs 05_drivers_gpio_uart/src/bsp/device_driver/bcm.rs diff -uNr 04_safe_globals/src/bsp/device_driver/bcm.rs 05_drivers_gpio_uart/src/bsp/device_driver/bcm.rs
--- 04_safe_globals/src/bsp/device_driver/bcm.rs --- 04_safe_globals/src/bsp/device_driver/bcm.rs
@ -947,24 +949,19 @@ diff -uNr 04_safe_globals/src/bsp/device_driver.rs 05_drivers_gpio_uart/src/bsp/
diff -uNr 04_safe_globals/src/bsp/raspberrypi/console.rs 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs diff -uNr 04_safe_globals/src/bsp/raspberrypi/console.rs 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs
--- 04_safe_globals/src/bsp/raspberrypi/console.rs --- 04_safe_globals/src/bsp/raspberrypi/console.rs
+++ 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs +++ 05_drivers_gpio_uart/src/bsp/raspberrypi/console.rs
@@ -4,113 +4,34 @@ @@ -4,115 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
-use crate::{console, synchronization, synchronization::NullLock}; -use crate::{console, synchronization, synchronization::NullLock};
+use super::memory; -use core::fmt;
+use crate::{bsp::device_driver, console}; -
use core::fmt; -//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
-// Private Definitions -// Private Definitions
+// Public Code -//--------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------- -
-/// A mystical, magical device for generating QEMU output out of the void. -/// A mystical, magical device for generating QEMU output out of the void.
+/// In case of a panic, the panic handler uses this function to take a last shot at printing -///
+/// something before the system is halted.
///
-/// The mutex protected part. -/// The mutex protected part.
-struct QEMUOutputInner { -struct QEMUOutputInner {
- chars_written: usize, - chars_written: usize,
@ -1007,13 +1004,9 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/console.rs 05_drivers_gpio_uart/sr
-/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are -/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are
-/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, -/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`,
-/// we get `write_fmt()` automatically. -/// we get `write_fmt()` automatically.
+/// 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. -/// The function takes an `&mut self`, so it must be implemented for the inner struct.
+/// # Safety -///
///
-/// See [`src/print.rs`]. -/// See [`src/print.rs`].
-/// -///
-/// [`src/print.rs`]: ../../print/index.html -/// [`src/print.rs`]: ../../print/index.html
@ -1031,11 +1024,12 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/console.rs 05_drivers_gpio_uart/sr
- Ok(()) - Ok(())
- } - }
-} -}
- +use crate::console;
-//--------------------------------------------------------------------------------------------------
-// Public Code //--------------------------------------------------------------------------------------------------
-//-------------------------------------------------------------------------------------------------- // Public Code
- //--------------------------------------------------------------------------------------------------
-impl QEMUOutput { -impl QEMUOutput {
- /// Create a new instance. - /// Create a new instance.
- pub const fn new() -> QEMUOutput { - pub const fn new() -> QEMUOutput {
@ -1043,18 +1037,10 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/console.rs 05_drivers_gpio_uart/sr
- inner: NullLock::new(QEMUOutputInner::new()), - inner: NullLock::new(QEMUOutputInner::new()),
- } - }
- } - }
+/// - Use only for printing during a panic. -}
+pub unsafe fn panic_console_out() -> impl fmt::Write { -
+ 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
- &QEMU_OUTPUT - &QEMU_OUTPUT
-} -}
- -
@ -1077,20 +1063,23 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/console.rs 05_drivers_gpio_uart/sr
- fn chars_written(&self) -> usize { - fn chars_written(&self) -> usize {
- self.inner.lock(|inner| inner.chars_written) - self.inner.lock(|inner| inner.chars_written)
- } - }
+ &super::PL011_UART + &super::driver::PL011_UART
} }
-
-impl console::interface::All for QEMUOutput {}
diff -uNr 04_safe_globals/src/bsp/raspberrypi/driver.rs 05_drivers_gpio_uart/src/bsp/raspberrypi/driver.rs diff -uNr 04_safe_globals/src/bsp/raspberrypi/driver.rs 05_drivers_gpio_uart/src/bsp/raspberrypi/driver.rs
--- 04_safe_globals/src/bsp/raspberrypi/driver.rs --- 04_safe_globals/src/bsp/raspberrypi/driver.rs
+++ 05_drivers_gpio_uart/src/bsp/raspberrypi/driver.rs +++ 05_drivers_gpio_uart/src/bsp/raspberrypi/driver.rs
@@ -0,0 +1,49 @@ @@ -0,0 +1,55 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2018-2022 Andre Richter <andre.o.richter@gmail.com>
+ +
+//! BSP driver support. +//! BSP driver support.
+ +
+use crate::driver; +use super::memory::map::mmio;
+use crate::{bsp::device_driver, driver};
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Private Definitions +// Private Definitions
@ -1105,8 +1094,13 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/driver.rs 05_drivers_gpio_uart/src
+// Global instances +// Global instances
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
+pub(super) static PL011_UART: device_driver::PL011Uart =
+ unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
+
+static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
+
+static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { +static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
+ device_drivers: [&super::GPIO, &super::PL011_UART], + device_drivers: [&PL011_UART, &GPIO],
+}; +};
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
@ -1130,7 +1124,7 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/driver.rs 05_drivers_gpio_uart/src
+ +
+ fn post_device_driver_init(&self) { + fn post_device_driver_init(&self) {
+ // Configure PL011Uart's output pins. + // Configure PL011Uart's output pins.
+ super::GPIO.map_pl011_uart(); + GPIO.map_pl011_uart();
+ } + }
+} +}
@ -1179,7 +1173,7 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi/memory.rs 05_drivers_gpio_uart/src
diff -uNr 04_safe_globals/src/bsp/raspberrypi.rs 05_drivers_gpio_uart/src/bsp/raspberrypi.rs diff -uNr 04_safe_globals/src/bsp/raspberrypi.rs 05_drivers_gpio_uart/src/bsp/raspberrypi.rs
--- 04_safe_globals/src/bsp/raspberrypi.rs --- 04_safe_globals/src/bsp/raspberrypi.rs
+++ 05_drivers_gpio_uart/src/bsp/raspberrypi.rs +++ 05_drivers_gpio_uart/src/bsp/raspberrypi.rs
@@ -6,3 +6,33 @@ @@ -6,3 +6,22 @@
pub mod console; pub mod console;
pub mod cpu; pub mod cpu;
@ -1187,17 +1181,6 @@ diff -uNr 04_safe_globals/src/bsp/raspberrypi.rs 05_drivers_gpio_uart/src/bsp/ra
+pub mod memory; +pub mod memory;
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Global instances
+//--------------------------------------------------------------------------------------------------
+use super::device_driver;
+
+static GPIO: device_driver::GPIO =
+ 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_START) };
+
+//--------------------------------------------------------------------------------------------------
+// Public Code +// Public Code
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+ +
@ -1230,7 +1213,7 @@ diff -uNr 04_safe_globals/src/bsp.rs 05_drivers_gpio_uart/src/bsp.rs
diff -uNr 04_safe_globals/src/console.rs 05_drivers_gpio_uart/src/console.rs diff -uNr 04_safe_globals/src/console.rs 05_drivers_gpio_uart/src/console.rs
--- 04_safe_globals/src/console.rs --- 04_safe_globals/src/console.rs
+++ 05_drivers_gpio_uart/src/console.rs +++ 05_drivers_gpio_uart/src/console.rs
@@ -14,8 +14,25 @@ @@ -16,8 +16,25 @@
/// Console write functions. /// Console write functions.
pub trait Write { pub trait Write {
@ -1256,7 +1239,7 @@ diff -uNr 04_safe_globals/src/console.rs 05_drivers_gpio_uart/src/console.rs
} }
/// Console statistics. /// Console statistics.
@@ -24,8 +41,13 @@ @@ -26,10 +43,15 @@
fn chars_written(&self) -> usize { fn chars_written(&self) -> usize {
0 0
} }
@ -1268,10 +1251,12 @@ diff -uNr 04_safe_globals/src/console.rs 05_drivers_gpio_uart/src/console.rs
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
- pub trait All = Write + Statistics; - pub trait All: Write + Statistics {}
+ pub trait All = Write + Read + Statistics; + pub trait All: Write + Read + Statistics {}
} }
//--------------------------------------------------------------------------------------------------
diff -uNr 04_safe_globals/src/cpu.rs 05_drivers_gpio_uart/src/cpu.rs diff -uNr 04_safe_globals/src/cpu.rs 05_drivers_gpio_uart/src/cpu.rs
--- 04_safe_globals/src/cpu.rs --- 04_safe_globals/src/cpu.rs
+++ 05_drivers_gpio_uart/src/cpu.rs +++ 05_drivers_gpio_uart/src/cpu.rs
@ -1353,16 +1338,15 @@ diff -uNr 04_safe_globals/src/main.rs 05_drivers_gpio_uart/src/main.rs
mod panic_wait; mod panic_wait;
mod print; mod print;
mod synchronization; mod synchronization;
@@ -125,16 +127,54 @@ @@ -125,13 +127,50 @@
/// # Safety /// # Safety
/// ///
/// - Only a single core must be active and running this function. /// - Only a single core must be active and running this function.
+/// - The init calls in this function must appear in the correct order. +/// - The init calls in this function must appear in the correct order.
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
- use console::interface::Statistics; - use console::console;
+ use driver::interface::DriverManager; + use driver::interface::DriverManager;
+
- println!("[0] Hello from Rust!");
+ for i in bsp::driver::driver_manager().all_device_drivers().iter() { + for i in bsp::driver::driver_manager().all_device_drivers().iter() {
+ if let Err(x) = i.init() { + if let Err(x) = i.init() {
+ panic!("Error loading driver: {}: {}", i.compatible(), x); + panic!("Error loading driver: {}: {}", i.compatible(), x);
@ -1370,17 +1354,20 @@ diff -uNr 04_safe_globals/src/main.rs 05_drivers_gpio_uart/src/main.rs
+ } + }
+ bsp::driver::driver_manager().post_device_driver_init(); + bsp::driver::driver_manager().post_device_driver_init();
+ // println! is usable from here on. + // println! is usable from here on.
+
- println!("[0] Hello from Rust!");
+ // Transition from unsafe to safe. + // Transition from unsafe to safe.
+ kernel_main() + kernel_main()
+} +}
+
- println!("[1] Chars written: {}", console().chars_written());
+/// The main function running after the early init. +/// The main function running after the early init.
+fn kernel_main() -> ! { +fn kernel_main() -> ! {
+ use bsp::console::console; + use console::console;
+ use console::interface::All;
+ use driver::interface::DriverManager; + use driver::interface::DriverManager;
+
- println!("[2] Stopping here.");
- cpu::wait_forever()
+ println!( + println!(
+ "[0] {} version {}", + "[0] {} version {}",
+ env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_NAME"),
@ -1396,69 +1383,18 @@ diff -uNr 04_safe_globals/src/main.rs 05_drivers_gpio_uart/src/main.rs
+ { + {
+ println!(" {}. {}", i + 1, driver.compatible()); + println!(" {}. {}", i + 1, driver.compatible());
+ } + }
+
println!( + println!("[3] Chars written: {}", console().chars_written());
- "[1] Chars written: {}",
+ "[3] Chars written: {}",
bsp::console::console().chars_written()
);
+ println!("[4] Echoing input now"); + println!("[4] Echoing input now");
+
- println!("[2] Stopping here.");
- cpu::wait_forever()
+ // Discard any spurious received characters before going into echo mode. + // Discard any spurious received characters before going into echo mode.
+ console().clear_rx(); + console().clear_rx();
+ loop { + loop {
+ let c = bsp::console::console().read_char(); + let c = console().read_char();
+ bsp::console::console().write_char(c); + console().write_char(c);
+ } + }
} }
diff -uNr 04_safe_globals/src/panic_wait.rs 05_drivers_gpio_uart/src/panic_wait.rs
--- 04_safe_globals/src/panic_wait.rs
+++ 05_drivers_gpio_uart/src/panic_wait.rs
@@ -4,13 +4,29 @@
//! A panic handler that infinitely waits.
-use crate::{cpu, println};
-use core::panic::PanicInfo;
+use crate::{bsp, cpu};
+use core::{fmt, panic::PanicInfo};
//--------------------------------------------------------------------------------------------------
// Private Code
//--------------------------------------------------------------------------------------------------
+fn _panic_print(args: fmt::Arguments) {
+ use fmt::Write;
+
+ unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
+}
+
+/// Prints with a newline - only use from the panic handler.
+///
+/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
+#[macro_export]
+macro_rules! panic_println {
+ ($($arg:tt)*) => ({
+ _panic_print(format_args_nl!($($arg)*));
+ })
+}
+
/// Stop immediately if called a second time.
///
/// # Note
@@ -50,7 +66,7 @@
_ => ("???", 0, 0),
};
- println!(
+ panic_println!(
"Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\
{}",
diff -uNr 04_safe_globals/tests/boot_test_string.rb 05_drivers_gpio_uart/tests/boot_test_string.rb diff -uNr 04_safe_globals/tests/boot_test_string.rb 05_drivers_gpio_uart/tests/boot_test_string.rb
--- 04_safe_globals/tests/boot_test_string.rb --- 04_safe_globals/tests/boot_test_string.rb
+++ 05_drivers_gpio_uart/tests/boot_test_string.rb +++ 05_drivers_gpio_uart/tests/boot_test_string.rb

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -148,7 +145,7 @@ impl GPIOInner {
// Make an educated guess for a good delay value (Sequence described in the BCM2837 // Make an educated guess for a good delay value (Sequence described in the BCM2837
// peripherals PDF). // peripherals PDF).
// //
// - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz. // - According to Wikipedia, the fastest RPi4 clocks around 1.5 GHz.
// - The Linux 2837 GPIO driver waits 1 µs between the steps. // - The Linux 2837 GPIO driver waits 1 µs between the steps.
// //
// So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs // So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
@ -195,7 +192,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -220,6 +223,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -145,8 +145,7 @@ unsafe fn kernel_init() -> ! {
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::console;
use console::interface::All;
use driver::interface::DriverManager; use driver::interface::DriverManager;
println!( println!(
@ -165,16 +164,13 @@ fn kernel_main() -> ! {
println!(" {}. {}", i + 1, driver.compatible()); println!(" {}. {}", i + 1, driver.compatible());
} }
println!( println!("[3] Chars written: {}", console().chars_written());
"[3] Chars written: {}",
bsp::console::console().chars_written()
);
println!("[4] Echoing input now"); println!("[4] Echoing input now");
// Discard any spurious received characters before going into echo mode. // Discard any spurious received characters before going into echo mode.
console().clear_rx(); console().clear_rx();
loop { loop {
let c = bsp::console::console().read_char(); let c = console().read_char();
bsp::console::console().write_char(c); console().write_char(c);
} }
} }

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -66,7 +50,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"Kernel panic!\n\n\ "Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -66,6 +66,7 @@ Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0 [MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected [MP] ✅ Serial connected
[MP] 🔌 Please power the target now [MP] 🔌 Please power the target now
__ __ _ _ _ _ __ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| | | \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` | | |\/| | | ' \| | |__/ _ \/ _` / _` |
@ -74,14 +75,14 @@ Minipush 1.0
Raspberry Pi 3 Raspberry Pi 3
[ML] Requesting binary [ML] Requesting binary
[MP] ⏩ Pushing 6 KiB ==========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 7 KiB ==========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[0] mingo version 0.5.0 [0] mingo version 0.5.0
[1] Booting on: Raspberry Pi 3 [1] Booting on: Raspberry Pi 3
[2] Drivers loaded: [2] Drivers loaded:
1. BCM GPIO 1. BCM PL011 UART
2. BCM PL011 UART 2. BCM GPIO
[3] Chars written: 117 [3] Chars written: 117
[4] Echoing input now [4] Echoing input now
``` ```
@ -324,23 +325,10 @@ diff -uNr 05_drivers_gpio_uart/src/_arch/aarch64/cpu/boot.s 06_uart_chainloader/
// Infinitely wait for events (aka "park the core"). // Infinitely wait for events (aka "park the core").
.L_parking_loop: .L_parking_loop:
diff -uNr 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
--- 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
+++ 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
@@ -148,7 +148,7 @@
// Make an educated guess for a good delay value (Sequence described in the BCM2837
// peripherals PDF).
//
- // - According to Wikipedia, the fastest Pi3 clocks around 1.4 GHz.
+ // - According to Wikipedia, the fastest RPi4 clocks around 1.5 GHz.
// - The Linux 2837 GPIO driver waits 1 µs between the steps.
//
// So lets try to be on the safe side and default to 2000 cycles, which would equal 1 µs
diff -uNr 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs diff -uNr 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
--- 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs --- 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
+++ 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
@@ -278,7 +278,7 @@ @@ -275,7 +275,7 @@
} }
/// Retrieve a character. /// Retrieve a character.
@ -349,7 +337,7 @@ diff -uNr 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 0
// If RX FIFO is empty, // If RX FIFO is empty,
if self.registers.FR.matches_all(FR::RXFE::SET) { if self.registers.FR.matches_all(FR::RXFE::SET) {
// immediately return in non-blocking mode. // immediately return in non-blocking mode.
@@ -293,12 +293,7 @@ @@ -290,12 +290,7 @@
} }
// Read one character. // Read one character.
@ -363,7 +351,7 @@ diff -uNr 05_drivers_gpio_uart/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 0
// Update statistics. // Update statistics.
self.chars_read += 1; self.chars_read += 1;
@@ -378,14 +373,14 @@ @@ -381,14 +376,14 @@
impl console::interface::Read for PL011Uart { impl console::interface::Read for PL011Uart {
fn read_char(&self) -> char { fn read_char(&self) -> char {
self.inner self.inner
@ -426,19 +414,14 @@ diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/kernel.ld 06_uart_chainloader
diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 06_uart_chainloader/src/bsp/raspberrypi/memory.rs diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 06_uart_chainloader/src/bsp/raspberrypi/memory.rs
--- 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs --- 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs
+++ 06_uart_chainloader/src/bsp/raspberrypi/memory.rs +++ 06_uart_chainloader/src/bsp/raspberrypi/memory.rs
@@ -11,9 +11,10 @@ @@ -11,6 +11,7 @@
/// The board's physical memory map. /// The board's physical memory map.
#[rustfmt::skip] #[rustfmt::skip]
pub(super) mod map { pub(super) mod map {
+ pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000; + pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
- pub const GPIO_OFFSET: usize = 0x0020_0000; pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000; pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
@@ -35,3 +36,13 @@ @@ -35,3 +36,13 @@
pub const PL011_UART_START: usize = START + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
@ -457,7 +440,7 @@ diff -uNr 05_drivers_gpio_uart/src/bsp/raspberrypi/memory.rs 06_uart_chainloader
diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs
--- 05_drivers_gpio_uart/src/main.rs --- 05_drivers_gpio_uart/src/main.rs
+++ 06_uart_chainloader/src/main.rs +++ 06_uart_chainloader/src/main.rs
@@ -143,38 +143,56 @@ @@ -143,34 +143,55 @@
kernel_main() kernel_main()
} }
@ -470,8 +453,7 @@ diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs
+ +
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::console;
use console::interface::All;
- use driver::interface::DriverManager; - use driver::interface::DriverManager;
- println!( - println!(
@ -502,10 +484,7 @@ diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs
+ console().write_char(3 as char); + console().write_char(3 as char);
} }
- println!( - println!("[3] Chars written: {}", console().chars_written());
- "[3] Chars written: {}",
- bsp::console::console().chars_written()
- );
- println!("[4] Echoing input now"); - println!("[4] Echoing input now");
+ // Read the binary's size. + // Read the binary's size.
+ let mut size: u32 = u32::from(console().read_char() as u8); + let mut size: u32 = u32::from(console().read_char() as u8);
@ -516,8 +495,8 @@ diff -uNr 05_drivers_gpio_uart/src/main.rs 06_uart_chainloader/src/main.rs
- // Discard any spurious received characters before going into echo mode. - // Discard any spurious received characters before going into echo mode.
- console().clear_rx(); - console().clear_rx();
- loop { - loop {
- let c = bsp::console::console().read_char(); - let c = console().read_char();
- bsp::console::console().write_char(c); - console().write_char(c);
+ // Trust it's not too big. + // Trust it's not too big.
+ console().write_char('O'); + console().write_char('O');
+ console().write_char('K'); + console().write_char('K');

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -195,7 +192,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -220,6 +223,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -321,7 +318,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -341,7 +344,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -395,3 +398,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -13,8 +13,8 @@
pub(super) mod map { pub(super) mod map {
pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000; pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
pub const GPIO_OFFSET: usize = 0x0020_0000; pub const GPIO_OFFSET: usize = 0x0020_0000;
pub const UART_OFFSET: usize = 0x0020_1000; pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices. /// Physical devices.
#[cfg(feature = "bsp_rpi3")] #[cfg(feature = "bsp_rpi3")]

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -152,8 +152,7 @@ const MINILOAD_LOGO: &str = r#"
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::console;
use console::interface::All;
println!("{}", MINILOAD_LOGO); println!("{}", MINILOAD_LOGO);
println!("{:^37}", bsp::board_name()); println!("{:^37}", bsp::board_name());

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -66,7 +50,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"Kernel panic!\n\n\ "Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -19,6 +19,7 @@ Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0 [MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected [MP] ✅ Serial connected
[MP] 🔌 Please power the target now [MP] 🔌 Please power the target now
__ __ _ _ _ _ __ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| | | \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` | | |\/| | | ' \| | |__/ _ \/ _` / _` |
@ -30,16 +31,16 @@ Minipush 1.0
[MP] ⏩ Pushing 12 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 12 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 0.140431] mingo version 0.7.0 [ 0.143123] mingo version 0.7.0
[ 0.140630] Booting on: Raspberry Pi 3 [ 0.143323] Booting on: Raspberry Pi 3
[ 0.141085] Architectural timer resolution: 52 ns [ 0.143778] Architectural timer resolution: 52 ns
[ 0.141660] Drivers loaded: [ 0.144352] Drivers loaded:
[ 0.141995] 1. BCM GPIO [ 0.144688] 1. BCM PL011 UART
[ 0.142353] 2. BCM PL011 UART [ 0.145110] 2. BCM GPIO
[W 0.142777] Spin duration smaller than architecturally supported, skipping [W 0.145469] Spin duration smaller than architecturally supported, skipping
[ 0.143621] Spinning for 1 second [ 0.146313] Spinning for 1 second
[ 1.144023] Spinning for 1 second [ 1.146715] Spinning for 1 second
[ 2.144245] Spinning for 1 second [ 2.146938] Spinning for 1 second
``` ```
## Diff to previous ## Diff to previous
@ -374,7 +375,7 @@ diff -uNr 06_uart_chainloader/src/_arch/aarch64/time.rs 07_timestamps/src/_arch/
diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
--- 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs --- 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
+++ 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs +++ 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
@@ -143,25 +143,19 @@ @@ -140,25 +140,19 @@
/// Disable pull-up/down on pins 14 and 15. /// Disable pull-up/down on pins 14 and 15.
#[cfg(feature = "bsp_rpi3")] #[cfg(feature = "bsp_rpi3")]
fn disable_pud_14_15_bcm2837(&mut self) { fn disable_pud_14_15_bcm2837(&mut self) {
@ -410,7 +411,7 @@ diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs 07_times
diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
--- 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs --- 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
+++ 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs +++ 07_timestamps/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs
@@ -278,7 +278,7 @@ @@ -275,7 +275,7 @@
} }
/// Retrieve a character. /// Retrieve a character.
@ -419,7 +420,7 @@ diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 07
// If RX FIFO is empty, // If RX FIFO is empty,
if self.registers.FR.matches_all(FR::RXFE::SET) { if self.registers.FR.matches_all(FR::RXFE::SET) {
// immediately return in non-blocking mode. // immediately return in non-blocking mode.
@@ -293,7 +293,12 @@ @@ -290,7 +290,12 @@
} }
// Read one character. // Read one character.
@ -433,7 +434,7 @@ diff -uNr 06_uart_chainloader/src/bsp/device_driver/bcm/bcm2xxx_pl011_uart.rs 07
// Update statistics. // Update statistics.
self.chars_read += 1; self.chars_read += 1;
@@ -373,14 +378,14 @@ @@ -376,14 +381,14 @@
impl console::interface::Read for PL011Uart { impl console::interface::Read for PL011Uart {
fn read_char(&self) -> char { fn read_char(&self) -> char {
self.inner self.inner
@ -496,19 +497,14 @@ diff -uNr 06_uart_chainloader/src/bsp/raspberrypi/kernel.ld 07_timestamps/src/bs
diff -uNr 06_uart_chainloader/src/bsp/raspberrypi/memory.rs 07_timestamps/src/bsp/raspberrypi/memory.rs diff -uNr 06_uart_chainloader/src/bsp/raspberrypi/memory.rs 07_timestamps/src/bsp/raspberrypi/memory.rs
--- 06_uart_chainloader/src/bsp/raspberrypi/memory.rs --- 06_uart_chainloader/src/bsp/raspberrypi/memory.rs
+++ 07_timestamps/src/bsp/raspberrypi/memory.rs +++ 07_timestamps/src/bsp/raspberrypi/memory.rs
@@ -11,10 +11,9 @@ @@ -11,7 +11,6 @@
/// The board's physical memory map. /// The board's physical memory map.
#[rustfmt::skip] #[rustfmt::skip]
pub(super) mod map { pub(super) mod map {
- pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000; - pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x8_0000;
- pub const GPIO_OFFSET: usize = 0x0020_0000; pub const GPIO_OFFSET: usize = 0x0020_0000;
- pub const UART_OFFSET: usize = 0x0020_1000; pub const UART_OFFSET: usize = 0x0020_1000;
+ pub const GPIO_OFFSET: usize = 0x0020_0000;
+ pub const UART_OFFSET: usize = 0x0020_1000;
/// Physical devices.
#[cfg(feature = "bsp_rpi3")]
@@ -36,13 +35,3 @@ @@ -36,13 +35,3 @@
pub const PL011_UART_START: usize = START + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
} }
@ -546,7 +542,7 @@ diff -uNr 06_uart_chainloader/src/main.rs 07_timestamps/src/main.rs
/// Early init code. /// Early init code.
/// ///
@@ -143,56 +144,38 @@ @@ -143,55 +144,38 @@
kernel_main() kernel_main()
} }
@ -559,8 +555,7 @@ diff -uNr 06_uart_chainloader/src/main.rs 07_timestamps/src/main.rs
- -
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
- use bsp::console::console; - use console::console;
- use console::interface::All;
+ use core::time::Duration; + use core::time::Duration;
+ use driver::interface::DriverManager; + use driver::interface::DriverManager;
+ use time::interface::TimeManager; + use time::interface::TimeManager;
@ -635,7 +630,7 @@ diff -uNr 06_uart_chainloader/src/main.rs 07_timestamps/src/main.rs
diff -uNr 06_uart_chainloader/src/panic_wait.rs 07_timestamps/src/panic_wait.rs diff -uNr 06_uart_chainloader/src/panic_wait.rs 07_timestamps/src/panic_wait.rs
--- 06_uart_chainloader/src/panic_wait.rs --- 06_uart_chainloader/src/panic_wait.rs
+++ 07_timestamps/src/panic_wait.rs +++ 07_timestamps/src/panic_wait.rs
@@ -58,18 +58,23 @@ @@ -42,18 +42,23 @@
#[panic_handler] #[panic_handler]
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
@ -650,7 +645,7 @@ diff -uNr 06_uart_chainloader/src/panic_wait.rs 07_timestamps/src/panic_wait.rs
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
- "Kernel panic!\n\n\ - "Kernel panic!\n\n\
+ "[ {:>3}.{:06}] Kernel panic!\n\n\ + "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
@ -664,7 +659,7 @@ diff -uNr 06_uart_chainloader/src/panic_wait.rs 07_timestamps/src/panic_wait.rs
diff -uNr 06_uart_chainloader/src/print.rs 07_timestamps/src/print.rs diff -uNr 06_uart_chainloader/src/print.rs 07_timestamps/src/print.rs
--- 06_uart_chainloader/src/print.rs --- 06_uart_chainloader/src/print.rs
+++ 07_timestamps/src/print.rs +++ 07_timestamps/src/print.rs
@@ -36,3 +36,59 @@ @@ -34,3 +34,59 @@
$crate::print::_print(format_args_nl!($($arg)*)); $crate::print::_print(format_args_nl!($($arg)*));
}) })
} }

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -69,7 +53,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"[ {:>3}.{:06}] Kernel panic!\n\n\ "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -69,7 +53,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"[ {:>3}.{:06}] Kernel panic!\n\n\ "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -166,6 +166,7 @@ Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0 [MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected [MP] ✅ Serial connected
[MP] 🔌 Please power the target now [MP] 🔌 Please power the target now
__ __ _ _ _ _ __ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| | | \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` | | |\/| | | ' \| | |__/ _ \/ _` / _` |
@ -177,20 +178,20 @@ Minipush 1.0
[MP] ⏩ Pushing 14 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 14 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 0.165757] mingo version 0.9.0 [ 0.162546] mingo version 0.9.0
[ 0.165957] Booting on: Raspberry Pi 3 [ 0.162745] Booting on: Raspberry Pi 3
[ 0.166412] Current privilege level: EL1 [ 0.163201] Current privilege level: EL1
[ 0.166888] Exception handling state: [ 0.163677] Exception handling state:
[ 0.167333] Debug: Masked [ 0.164122] Debug: Masked
[ 0.167723] SError: Masked [ 0.164511] SError: Masked
[ 0.168112] IRQ: Masked [ 0.164901] IRQ: Masked
[ 0.168502] FIQ: Masked [ 0.165291] FIQ: Masked
[ 0.168893] Architectural timer resolution: 52 ns [ 0.165681] Architectural timer resolution: 52 ns
[ 0.169467] Drivers loaded: [ 0.166255] Drivers loaded:
[ 0.169803] 1. BCM GPIO [ 0.166592] 1. BCM PL011 UART
[ 0.170160] 2. BCM PL011 UART [ 0.167014] 2. BCM GPIO
[ 0.170583] Timer test, spinning for 1 second [ 0.167371] Timer test, spinning for 1 second
[ 1.171115] Echoing input now [ 1.167904] Echoing input now
``` ```
## Diff to previous ## Diff to previous
@ -505,16 +506,15 @@ diff -uNr 08_hw_debug_JTAG/src/main.rs 09_privilege_level/src/main.rs
mod panic_wait; mod panic_wait;
mod print; mod print;
mod synchronization; mod synchronization;
@@ -146,6 +147,8 @@ @@ -146,6 +147,7 @@
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
+ use bsp::console::console; + use console::console;
+ use console::interface::All;
use core::time::Duration; use core::time::Duration;
use driver::interface::DriverManager; use driver::interface::DriverManager;
use time::interface::TimeManager; use time::interface::TimeManager;
@@ -157,6 +160,12 @@ @@ -157,6 +159,12 @@
); );
info!("Booting on: {}", bsp::board_name()); info!("Booting on: {}", bsp::board_name());
@ -527,7 +527,7 @@ diff -uNr 08_hw_debug_JTAG/src/main.rs 09_privilege_level/src/main.rs
info!( info!(
"Architectural timer resolution: {} ns", "Architectural timer resolution: {} ns",
time::time_manager().resolution().as_nanos() time::time_manager().resolution().as_nanos()
@@ -171,11 +180,15 @@ @@ -171,11 +179,15 @@
info!(" {}. {}", i + 1, driver.compatible()); info!(" {}. {}", i + 1, driver.compatible());
} }
@ -543,8 +543,8 @@ diff -uNr 08_hw_debug_JTAG/src/main.rs 09_privilege_level/src/main.rs
loop { loop {
- info!("Spinning for 1 second"); - info!("Spinning for 1 second");
- time::time_manager().spin_for(Duration::from_secs(1)); - time::time_manager().spin_for(Duration::from_secs(1));
+ let c = bsp::console::console().read_char(); + let c = console().read_char();
+ bsp::console::console().write_char(c); + console().write_char(c);
} }
} }

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -147,8 +147,7 @@ unsafe fn kernel_init() -> ! {
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::console;
use console::interface::All;
use core::time::Duration; use core::time::Duration;
use driver::interface::DriverManager; use driver::interface::DriverManager;
use time::interface::TimeManager; use time::interface::TimeManager;
@ -188,7 +187,7 @@ fn kernel_main() -> ! {
// Discard any spurious received characters before going into echo mode. // Discard any spurious received characters before going into echo mode.
console().clear_rx(); console().clear_rx();
loop { loop {
let c = bsp::console::console().read_char(); let c = console().read_char();
bsp::console::console().write_char(c); console().write_char(c);
} }
} }

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -69,7 +53,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"[ {:>3}.{:06}] Kernel panic!\n\n\ "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -314,6 +314,7 @@ Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0 [MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected [MP] ✅ Serial connected
[MP] 🔌 Please power the target now [MP] 🔌 Please power the target now
__ __ _ _ _ _ __ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| | | \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` | | |\/| | | ' \| | |__/ _ \/ _` / _` |
@ -325,25 +326,25 @@ Minipush 1.0
[MP] ⏩ Pushing 64 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 64 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 1.034062] mingo version 0.10.0 [ 0.811167] mingo version 0.10.0
[ 1.034270] Booting on: Raspberry Pi 3 [ 0.811374] Booting on: Raspberry Pi 3
[ 1.034725] MMU online. Special regions: [ 0.811829] MMU online. Special regions:
[ 1.035201] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data [ 0.812306] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data
[ 1.036220] 0x1fff0000 - 0x1fffffff | 64 KiB | Dev RW PXN | Remapped Device MMIO [ 0.813324] 0x1fff0000 - 0x1fffffff | 64 KiB | Dev RW PXN | Remapped Device MMIO
[ 1.037205] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO [ 0.814310] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO
[ 1.038094] Current privilege level: EL1 [ 0.815198] Current privilege level: EL1
[ 1.038570] Exception handling state: [ 0.815675] Exception handling state:
[ 1.039015] Debug: Masked [ 0.816119] Debug: Masked
[ 1.039405] SError: Masked [ 0.816509] SError: Masked
[ 1.039794] IRQ: Masked [ 0.816899] IRQ: Masked
[ 1.040184] FIQ: Masked [ 0.817289] FIQ: Masked
[ 1.040575] Architectural timer resolution: 52 ns [ 0.817679] Architectural timer resolution: 52 ns
[ 1.041148] Drivers loaded: [ 0.818253] Drivers loaded:
[ 1.041484] 1. BCM GPIO [ 0.818589] 1. BCM PL011 UART
[ 1.041842] 2. BCM PL011 UART [ 0.819011] 2. BCM GPIO
[ 1.042264] Timer test, spinning for 1 second [ 0.819369] Timer test, spinning for 1 second
[ !!! ] Writing through the remapped UART at 0x1FFF_1000 [ !!! ] Writing through the remapped UART at 0x1FFF_1000
[ 2.043305] Echoing input now [ 1.820409] Echoing input now
``` ```
## Diff to previous ## Diff to previous
@ -1118,7 +1119,16 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s
for i in bsp::driver::driver_manager().all_device_drivers().iter() { for i in bsp::driver::driver_manager().all_device_drivers().iter() {
if let Err(x) = i.init() { if let Err(x) = i.init() {
@@ -160,6 +171,9 @@ @@ -147,7 +158,7 @@
/// The main function running after the early init.
fn kernel_main() -> ! {
- use console::console;
+ use console::{console, interface::Write};
use core::time::Duration;
use driver::interface::DriverManager;
use time::interface::TimeManager;
@@ -159,6 +170,9 @@
); );
info!("Booting on: {}", bsp::board_name()); info!("Booting on: {}", bsp::board_name());
@ -1128,7 +1138,7 @@ diff -uNr 09_privilege_level/src/main.rs 10_virtual_mem_part1_identity_mapping/s
let (_, privilege_level) = exception::current_privilege_level(); let (_, privilege_level) = exception::current_privilege_level();
info!("Current privilege level: {}", privilege_level); info!("Current privilege level: {}", privilege_level);
@@ -183,6 +197,13 @@ @@ -182,6 +196,13 @@
info!("Timer test, spinning for 1 second"); info!("Timer test, spinning for 1 second");
time::time_manager().spin_for(Duration::from_secs(1)); time::time_manager().spin_for(Duration::from_secs(1));

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -158,8 +158,7 @@ unsafe fn kernel_init() -> ! {
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::{console, interface::Write};
use console::interface::All;
use core::time::Duration; use core::time::Duration;
use driver::interface::DriverManager; use driver::interface::DriverManager;
use time::interface::TimeManager; use time::interface::TimeManager;
@ -209,7 +208,7 @@ fn kernel_main() -> ! {
// Discard any spurious received characters before going into echo mode. // Discard any spurious received characters before going into echo mode.
console().clear_rx(); console().clear_rx();
loop { loop {
let c = bsp::console::console().read_char(); let c = console().read_char();
bsp::console::console().write_char(c); console().write_char(c);
} }
} }

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -69,7 +53,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"[ {:>3}.{:06}] Kernel panic!\n\n\ "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -417,31 +417,31 @@ Minipush 1.0
[MP] ⏩ Pushing 64 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 64 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 0.787414] mingo version 0.11.0 [ 0.798323] mingo version 0.11.0
[ 0.787621] Booting on: Raspberry Pi 3 [ 0.798530] Booting on: Raspberry Pi 3
[ 0.788076] MMU online. Special regions: [ 0.798985] MMU online. Special regions:
[ 0.788553] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data [ 0.799462] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data
[ 0.789571] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO [ 0.800480] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO
[ 0.790460] Current privilege level: EL1 [ 0.801369] Current privilege level: EL1
[ 0.790936] Exception handling state: [ 0.801845] Exception handling state:
[ 0.791380] Debug: Masked [ 0.802290] Debug: Masked
[ 0.791770] SError: Masked [ 0.802680] SError: Masked
[ 0.792160] IRQ: Masked [ 0.803069] IRQ: Masked
[ 0.792550] FIQ: Masked [ 0.803459] FIQ: Masked
[ 0.792940] Architectural timer resolution: 52 ns [ 0.803849] Architectural timer resolution: 52 ns
[ 0.793514] Drivers loaded: [ 0.804423] Drivers loaded:
[ 0.793850] 1. BCM GPIO [ 0.804759] 1. BCM PL011 UART
[ 0.794208] 2. BCM PL011 UART [ 0.805182] 2. BCM GPIO
[ 0.794630] Timer test, spinning for 1 second [ 0.805539] Timer test, spinning for 1 second
[ 1.795161] [ 1.806070]
[ 1.795165] Trying to read from address 8 GiB... [ 1.806074] Trying to read from address 8 GiB...
[ 1.795715] ************************************************ [ 1.806624] ************************************************
[ 1.796407] Whoa! We recovered from a synchronous exception! [ 1.807316] Whoa! We recovered from a synchronous exception!
[ 1.797100] ************************************************ [ 1.808009] ************************************************
[ 1.797794] [ 1.808703]
[ 1.797967] Let's try again [ 1.808876] Let's try again
[ 1.798303] Trying to read from address 9 GiB... [ 1.809212] Trying to read from address 9 GiB...
[ 1.798867] Kernel panic! [ 1.809776] Kernel panic!
Panic location: Panic location:
File 'src/_arch/aarch64/exception.rs', line 58, column 5 File 'src/_arch/aarch64/exception.rs', line 58, column 5
@ -464,25 +464,25 @@ SPSR_EL1: 0x600003c5
IRQ (I): Masked IRQ (I): Masked
FIQ (F): Masked FIQ (F): Masked
Illegal Execution State (IL): Not set Illegal Execution State (IL): Not set
ELR_EL1: 0x0000000000082194 ELR_EL1: 0x00000000000845f8
General purpose register: General purpose register:
x0 : 0x0000000000000000 x1 : 0x0000000000085517 x0 : 0x0000000000000000 x1 : 0x0000000000086187
x2 : 0x0000000000000027 x3 : 0x0000000000084380 x2 : 0x0000000000000027 x3 : 0x0000000000081280
x4 : 0x0000000000000006 x5 : 0xfb5f341800000000 x4 : 0x0000000000000006 x5 : 0x1e27329c00000000
x6 : 0x0000000000000000 x7 : 0x7f91bc012b2b0209 x6 : 0x0000000000000000 x7 : 0xd3d18908028f0243
x8 : 0x0000000240000000 x9 : 0x0000000000085517 x8 : 0x0000000240000000 x9 : 0x0000000000086187
x10: 0x0000000000000443 x11: 0x000000003f201000 x10: 0x0000000000000443 x11: 0x000000003f201000
x12: 0x0000000000000019 x13: 0x00000000ffffd8f0 x12: 0x0000000000000019 x13: 0x00000000ffffd8f0
x14: 0x000000000000147b x15: 0x00000000ffffff9c x14: 0x000000000000147b x15: 0x00000000ffffff9c
x16: 0x000000000007fd38 x17: 0x0000000005f5e0ff x16: 0x000000000007fd38 x17: 0x0000000005f5e0ff
x18: 0x0000000000000030 x19: 0x0000000000090008 x18: 0x00000000000c58fc x19: 0x0000000000090008
x20: 0x0000000000085350 x21: 0x000000003b9aca00 x20: 0x0000000000085fc0 x21: 0x000000003b9aca00
x22: 0x0000000000082e4c x23: 0x0000000000082308 x22: 0x0000000000082238 x23: 0x00000000000813d4
x24: 0x0000000010624dd3 x25: 0xffffffffc4653600 x24: 0x0000000010624dd3 x25: 0xffffffffc4653600
x26: 0x0000000000086638 x27: 0x0000000000085410 x26: 0x0000000000086988 x27: 0x0000000000086080
x28: 0x0000000000084f90 x29: 0x0000000000086538 x28: 0x0000000000085f10 x29: 0x0000000000085c00
lr : 0x0000000000082188 lr : 0x00000000000845ec
``` ```
## Diff to previous ## Diff to previous
@ -1033,7 +1033,16 @@ diff -uNr 10_virtual_mem_part1_identity_mapping/src/main.rs 11_exceptions_part1_
if let Err(string) = memory::mmu::mmu().enable_mmu_and_caching() { if let Err(string) = memory::mmu::mmu().enable_mmu_and_caching() {
panic!("MMU: {}", string); panic!("MMU: {}", string);
} }
@@ -197,13 +199,28 @@ @@ -158,7 +160,7 @@
/// The main function running after the early init.
fn kernel_main() -> ! {
- use console::{console, interface::Write};
+ use console::console;
use core::time::Duration;
use driver::interface::DriverManager;
use time::interface::TimeManager;
@@ -196,13 +198,28 @@
info!("Timer test, spinning for 1 second"); info!("Timer test, spinning for 1 second");
time::time_manager().spin_for(Duration::from_secs(1)); time::time_manager().spin_for(Duration::from_secs(1));

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,34 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,6 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -160,8 +160,7 @@ unsafe fn kernel_init() -> ! {
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::console;
use console::interface::All;
use core::time::Duration; use core::time::Duration;
use driver::interface::DriverManager; use driver::interface::DriverManager;
use time::interface::TimeManager; use time::interface::TimeManager;
@ -226,7 +225,7 @@ fn kernel_main() -> ! {
// Discard any spurious received characters before going into echo mode. // Discard any spurious received characters before going into echo mode.
console().clear_rx(); console().clear_rx();
loop { loop {
let c = bsp::console::console().read_char(); let c = console().read_char();
bsp::console::console().write_char(c); console().write_char(c);
} }
} }

@ -4,29 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -69,7 +53,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"[ {:>3}.{:06}] Kernel panic!\n\n\ "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -266,8 +266,10 @@ implementation in `lib.rs`:
#[cfg(test)] #[cfg(test)]
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
test_main(); test_main();
@ -275,12 +277,12 @@ unsafe fn kernel_init() -> ! {
} }
``` ```
Note the call to `bsp::console::qemu_bring_up_console()`. Since we are running all our tests inside Note the call to `bsp::driver::driver_manager().qemu_bring_up_console()`. Since we are running all
`QEMU`, we need to ensure that whatever peripheral implements the kernel's `console` interface is our tests inside `QEMU`, we need to ensure that whatever peripheral implements the kernel's
initialized, so that we can print from our tests. If you recall [tutorial 03], bringing up `console` interface is initialized, so that we can print from our tests. If you recall [tutorial
peripherals in `QEMU` might not need the full initialization as is needed on real hardware (setting 03], bringing up peripherals in `QEMU` might not need the full initialization as is needed on real
clocks, config registers, etc...) due to the abstractions in `QEMU`'s emulation code. So this is an hardware (setting clocks, config registers, etc...) due to the abstractions in `QEMU`'s emulation
opportunity to cut down on setup code. code. So this is an opportunity to cut down on setup code.
[tutorial 03]: ../03_hacky_hello_world [tutorial 03]: ../03_hacky_hello_world
@ -620,13 +622,15 @@ your test code into individual chunks. For example, take a look at `tests/01_tim
#![test_runner(libkernel::test_runner)] #![test_runner(libkernel::test_runner)]
use core::time::Duration; use core::time::Duration;
use libkernel::{bsp, cpu, exception, time, time::interface::TimeManager}; use libkernel::{bsp, cpu, driver, exception, time, time::interface::TimeManager};
use test_macros::kernel_test; use test_macros::kernel_test;
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi.
@ -714,14 +718,15 @@ so the wanted outcome is a `panic!`. Here is the whole test (minus some inline c
mod panic_exit_success; mod panic_exit_success;
use libkernel::{bsp, cpu, exception, memory, println}; use libkernel::{bsp, cpu, driver, exception, info, memory, println};
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
use memory::mmu::interface::MMU; use memory::mmu::interface::MMU;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// This line will be printed as the test header. // This line will be printed as the test header.
println!("Testing synchronous exception handling by causing a page fault"); println!("Testing synchronous exception handling by causing a page fault");
@ -788,15 +793,15 @@ The subtest first sends `"ABC"` over the console to the kernel, and then expects
/// Console tests should time out on the I/O harness in case of panic. /// Console tests should time out on the I/O harness in case of panic.
mod panic_wait_forever; mod panic_wait_forever;
use libkernel::{bsp, console, cpu, exception, print}; use libkernel::{bsp, console, cpu, driver, exception, print};
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use bsp::console::console; use console::console;
use console::interface::*; use driver::interface::DriverManager;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// Handshake // Handshake
assert_eq!(console().read_char(), 'A'); assert_eq!(console().read_char(), 'A');

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -167,18 +167,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -186,7 +183,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -326,7 +323,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -346,7 +349,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -400,3 +403,5 @@ impl console::interface::Statistics for PL011Uart {
self.inner.lock(|inner| inner.chars_read) self.inner.lock(|inner| inner.chars_read)
} }
} }
impl console::interface::All for PL011Uart {}

@ -9,17 +9,6 @@ pub mod cpu;
pub mod driver; pub mod driver;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START) };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

@ -4,45 +4,13 @@
//! BSP console facilities. //! BSP console facilities.
use super::memory; use crate::console;
use crate::{bsp::device_driver, console};
use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
/// 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 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. /// Return a reference to the console.
pub fn console() -> &'static impl console::interface::All { pub fn console() -> &'static dyn console::interface::All {
&super::PL011_UART &super::driver::PL011_UART
} }
//--------------------------------------------------------------------------------------------------
// Testing
//--------------------------------------------------------------------------------------------------
/// Minimal code needed to bring up the console in QEMU (for testing only). This is often less steps
/// than on real hardware due to QEMU's abstractions.
///
/// For the RPi, nothing needs to be done.
#[cfg(feature = "test_build")]
pub fn qemu_bring_up_console() {}

@ -4,7 +4,8 @@
//! BSP driver support. //! BSP driver support.
use crate::driver; use super::memory::map::mmio;
use crate::{bsp::device_driver, driver};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Definitions // Private Definitions
@ -19,8 +20,13 @@ struct BSPDriverManager {
// Global instances // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
pub(super) static PL011_UART: device_driver::PL011Uart =
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
device_drivers: [&super::GPIO, &super::PL011_UART], device_drivers: [&PL011_UART, &GPIO],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -44,6 +50,9 @@ impl driver::interface::DriverManager for BSPDriverManager {
fn post_device_driver_init(&self) { fn post_device_driver_init(&self) {
// Configure PL011Uart's output pins. // Configure PL011Uart's output pins.
super::GPIO.map_pl011_uart(); GPIO.map_pl011_uart();
} }
#[cfg(feature = "test_build")]
fn qemu_bring_up_console(&self) {}
} }

@ -4,6 +4,8 @@
//! System console. //! System console.
use crate::bsp;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Definitions // Public Definitions
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -49,5 +51,16 @@ pub mod interface {
} }
/// Trait alias for a full-fledged console. /// Trait alias for a full-fledged console.
pub trait All = Write + Read + Statistics; pub trait All: Write + Read + Statistics {}
}
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
/// Return a reference to the console.
///
/// This is the global console used by all printing macros.
pub fn console() -> &'static dyn interface::All {
bsp::console::console()
} }

@ -40,5 +40,10 @@ pub mod interface {
/// ///
/// For example, device driver code that depends on other drivers already being online. /// For example, device driver code that depends on other drivers already being online.
fn post_device_driver_init(&self); fn post_device_driver_init(&self);
/// Minimal code needed to bring up the console in QEMU (for testing only). This is often
/// less steps than on real hardware due to QEMU's abstractions.
#[cfg(feature = "test_build")]
fn qemu_bring_up_console(&self);
} }
} }

@ -177,8 +177,10 @@ pub fn test_runner(tests: &[&test_types::UnitTest]) {
#[cfg(test)] #[cfg(test)]
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
test_main(); test_main();

@ -49,8 +49,7 @@ unsafe fn kernel_init() -> ! {
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
use bsp::console::console; use console::console;
use console::interface::All;
use driver::interface::DriverManager; use driver::interface::DriverManager;
info!("{}", libkernel::version()); info!("{}", libkernel::version());
@ -84,7 +83,7 @@ fn kernel_main() -> ! {
// Discard any spurious received characters before going into echo mode. // Discard any spurious received characters before going into echo mode.
console().clear_rx(); console().clear_rx();
loop { loop {
let c = bsp::console::console().read_char(); let c = console().read_char();
bsp::console::console().write_char(c); console().write_char(c);
} }
} }

@ -4,19 +4,13 @@
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
use crate::{bsp, cpu}; use crate::{cpu, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Private Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
fn _panic_print(args: fmt::Arguments) {
use fmt::Write;
unsafe { bsp::console::panic_console_out().write_fmt(args).unwrap() };
}
/// The point of exit for `libkernel`. /// The point of exit for `libkernel`.
/// ///
/// It is linked weakly, so that the integration tests can overload its standard behavior. /// It is linked weakly, so that the integration tests can overload its standard behavior.
@ -34,16 +28,6 @@ fn _panic_exit() -> ! {
} }
} }
/// Prints with a newline - only use from the panic handler.
///
/// Carbon copy from <https://doc.rust-lang.org/src/std/macros.rs.html>
#[macro_export]
macro_rules! panic_println {
($($arg:tt)*) => ({
_panic_print(format_args_nl!($($arg)*));
})
}
/// Stop immediately if called a second time. /// Stop immediately if called a second time.
/// ///
/// # Note /// # Note
@ -86,7 +70,7 @@ fn panic(info: &PanicInfo) -> ! {
_ => ("???", 0, 0), _ => ("???", 0, 0),
}; };
panic_println!( println!(
"[ {:>3}.{:06}] Kernel panic!\n\n\ "[ {:>3}.{:06}] Kernel panic!\n\n\
Panic location:\n File '{}', line {}, column {}\n\n\ Panic location:\n File '{}', line {}, column {}\n\n\
{}", {}",

@ -4,7 +4,7 @@
//! Printing. //! Printing.
use crate::{bsp, console}; use crate::console;
use core::fmt; use core::fmt;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -13,9 +13,7 @@ use core::fmt;
#[doc(hidden)] #[doc(hidden)]
pub fn _print(args: fmt::Arguments) { pub fn _print(args: fmt::Arguments) {
use console::interface::Write; console::console().write_fmt(args).unwrap();
bsp::console::console().write_fmt(args).unwrap();
} }
/// Prints without a newline. /// Prints without a newline.

@ -11,15 +11,15 @@
/// Console tests should time out on the I/O harness in case of panic. /// Console tests should time out on the I/O harness in case of panic.
mod panic_wait_forever; mod panic_wait_forever;
use libkernel::{bsp, console, cpu, exception, print}; use libkernel::{bsp, console, cpu, driver, exception, print};
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use bsp::console::console; use console::console;
use console::interface::*; use driver::interface::DriverManager;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// Handshake // Handshake
assert_eq!(console().read_char(), 'A'); assert_eq!(console().read_char(), 'A');

@ -11,13 +11,15 @@
#![test_runner(libkernel::test_runner)] #![test_runner(libkernel::test_runner)]
use core::time::Duration; use core::time::Duration;
use libkernel::{bsp, cpu, exception, time, time::interface::TimeManager}; use libkernel::{bsp, cpu, driver, exception, time, time::interface::TimeManager};
use test_macros::kernel_test; use test_macros::kernel_test;
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi. // Depending on CPU arch, some timer bring-up code could go here. Not needed for the RPi.

@ -17,14 +17,15 @@
/// or indirectly. /// or indirectly.
mod panic_exit_success; mod panic_exit_success;
use libkernel::{bsp, cpu, exception, info, memory, println}; use libkernel::{bsp, cpu, driver, exception, info, memory, println};
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
use memory::mmu::interface::MMU; use memory::mmu::interface::MMU;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// This line will be printed as the test header. // This line will be printed as the test header.
println!("Testing synchronous exception handling by causing a page fault"); println!("Testing synchronous exception handling by causing a page fault");

@ -12,7 +12,7 @@
mod panic_wait_forever; mod panic_wait_forever;
use core::arch::asm; use core::arch::asm;
use libkernel::{bsp, cpu, exception, info, memory, println}; use libkernel::{bsp, cpu, driver, exception, info, memory, println};
#[inline(never)] #[inline(never)]
fn nested_system_call() { fn nested_system_call() {
@ -30,10 +30,11 @@ fn nested_system_call() {
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager;
use memory::mmu::interface::MMU; use memory::mmu::interface::MMU;
exception::handling_init(); exception::handling_init();
bsp::console::qemu_bring_up_console(); bsp::driver::driver_manager().qemu_bring_up_console();
// This line will be printed as the test header. // This line will be printed as the test header.
println!("Testing exception restore"); println!("Testing exception restore");

@ -29,7 +29,6 @@
+ [The GICv2 Driver (Pi 4)](#the-gicv2-driver-pi-4) + [The GICv2 Driver (Pi 4)](#the-gicv2-driver-pi-4)
- [GICC Details](#gicc-details) - [GICC Details](#gicc-details)
- [GICD Details](#gicd-details) - [GICD Details](#gicd-details)
- [UART hack](#uart-hack)
- [Test it](#test-it) - [Test it](#test-it)
- [Diff to previous](#diff-to-previous) - [Diff to previous](#diff-to-previous)
@ -282,7 +281,7 @@ fn register_and_enable_irq_handler(&'static self) -> Result<(), &'static str> {
use exception::asynchronous::{interface::IRQManager, IRQDescriptor}; use exception::asynchronous::{interface::IRQManager, IRQDescriptor};
let descriptor = IRQDescriptor { let descriptor = IRQDescriptor {
name: "BCM PL011 UART", name: Self::COMPATIBLE,
handler: self, handler: self,
}; };
@ -667,6 +666,7 @@ Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0 [MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected [MP] ✅ Serial connected
[MP] 🔌 Please power the target now [MP] 🔌 Please power the target now
__ __ _ _ _ _ __ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| | | \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` | | |\/| | | ' \| | |__/ _ \/ _` / _` |
@ -678,26 +678,26 @@ Minipush 1.0
[MP] ⏩ Pushing 66 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 66 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 1.010579] mingo version 0.13.0 [ 0.822492] mingo version 0.13.0
[ 1.010787] Booting on: Raspberry Pi 3 [ 0.822700] Booting on: Raspberry Pi 3
[ 1.011242] MMU online. Special regions: [ 0.823155] MMU online. Special regions:
[ 1.011718] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data [ 0.823632] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data
[ 1.012737] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO [ 0.824650] 0x3f000000 - 0x4000ffff | 16 MiB | Dev RW PXN | Device MMIO
[ 1.013625] Current privilege level: EL1 [ 0.825539] Current privilege level: EL1
[ 1.014102] Exception handling state: [ 0.826015] Exception handling state:
[ 1.014546] Debug: Masked [ 0.826459] Debug: Masked
[ 1.014936] SError: Masked [ 0.826849] SError: Masked
[ 1.015326] IRQ: Unmasked [ 0.827239] IRQ: Unmasked
[ 1.015738] FIQ: Masked [ 0.827651] FIQ: Masked
[ 1.016127] Architectural timer resolution: 52 ns [ 0.828041] Architectural timer resolution: 52 ns
[ 1.016702] Drivers loaded: [ 0.828615] Drivers loaded:
[ 1.017038] 1. BCM GPIO [ 0.828951] 1. BCM PL011 UART
[ 1.017395] 2. BCM PL011 UART [ 0.829373] 2. BCM GPIO
[ 1.017817] 3. BCM Interrupt Controller [ 0.829731] 3. BCM Interrupt Controller
[ 1.018348] Registered IRQ handlers: [ 0.830262] Registered IRQ handlers:
[ 1.018782] Peripheral handler: [ 0.830695] Peripheral handler:
[ 1.019228] 57. BCM PL011 UART [ 0.831141] 57. BCM PL011 UART
[ 1.019735] Echoing input now [ 0.831649] Echoing input now
``` ```
Raspberry Pi 4: Raspberry Pi 4:
@ -710,6 +710,7 @@ Minipush 1.0
[MP] ⏳ Waiting for /dev/ttyUSB0 [MP] ⏳ Waiting for /dev/ttyUSB0
[MP] ✅ Serial connected [MP] ✅ Serial connected
[MP] 🔌 Please power the target now [MP] 🔌 Please power the target now
__ __ _ _ _ _ __ __ _ _ _ _
| \/ (_)_ _ (_) | ___ __ _ __| | | \/ (_)_ _ (_) | ___ __ _ __| |
| |\/| | | ' \| | |__/ _ \/ _` / _` | | |\/| | | ' \| | |__/ _ \/ _` / _` |
@ -721,26 +722,26 @@ Minipush 1.0
[MP] ⏩ Pushing 73 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00 [MP] ⏩ Pushing 73 KiB =========================================🦀 100% 0 KiB/s Time: 00:00:00
[ML] Loaded! Executing the payload now [ML] Loaded! Executing the payload now
[ 1.030536] mingo version 0.13.0 [ 0.886853] mingo version 0.13.0
[ 1.030569] Booting on: Raspberry Pi 4 [ 0.886886] Booting on: Raspberry Pi 4
[ 1.031024] MMU online. Special regions: [ 0.887341] MMU online. Special regions:
[ 1.031501] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data [ 0.887818] 0x00080000 - 0x0008ffff | 64 KiB | C RO PX | Kernel code and RO data
[ 1.032519] 0xfe000000 - 0xff84ffff | 24 MiB | Dev RW PXN | Device MMIO [ 0.888836] 0xfe000000 - 0xff84ffff | 24 MiB | Dev RW PXN | Device MMIO
[ 1.033408] Current privilege level: EL1 [ 0.889725] Current privilege level: EL1
[ 1.033884] Exception handling state: [ 0.890201] Exception handling state:
[ 1.034328] Debug: Masked [ 0.890645] Debug: Masked
[ 1.034718] SError: Masked [ 0.891035] SError: Masked
[ 1.035108] IRQ: Unmasked [ 0.891425] IRQ: Unmasked
[ 1.035520] FIQ: Masked [ 0.891837] FIQ: Masked
[ 1.035910] Architectural timer resolution: 18 ns [ 0.892227] Architectural timer resolution: 18 ns
[ 1.036484] Drivers loaded: [ 0.892801] Drivers loaded:
[ 1.036820] 1. BCM GPIO [ 0.893137] 1. BCM PL011 UART
[ 1.037178] 2. BCM PL011 UART [ 0.893560] 2. BCM GPIO
[ 1.037600] 3. GICv2 (ARM Generic Interrupt Controller v2) [ 0.893917] 3. GICv2 (ARM Generic Interrupt Controller v2)
[ 1.038337] Registered IRQ handlers: [ 0.894654] Registered IRQ handlers:
[ 1.038770] Peripheral handler: [ 0.895087] Peripheral handler:
[ 1.039217] 153. BCM PL011 UART [ 0.895534] 153. BCM PL011 UART
[ 1.039725] Echoing input now [ 0.896042] Echoing input now
``` ```
## Diff to previous ## Diff to previous
@ -896,21 +897,19 @@ diff -uNr 12_integrated_testing/kernel/src/_arch/aarch64/exception.rs 13_excepti
//! //!
//! crate::exception::arch_exception //! crate::exception::arch_exception
+use crate::{bsp, exception}; +use crate::exception;
use core::{arch::global_asm, cell::UnsafeCell, fmt}; use core::{arch::global_asm, cell::UnsafeCell, fmt};
use cortex_a::{asm::barrier, registers::*}; use cortex_a::{asm::barrier, registers::*};
use tock_registers::{ use tock_registers::{
@@ -102,8 +103,11 @@ @@ -102,8 +103,9 @@
} }
#[no_mangle] #[no_mangle]
-unsafe extern "C" fn current_elx_irq(e: &mut ExceptionContext) { -unsafe extern "C" fn current_elx_irq(e: &mut ExceptionContext) {
- default_exception_handler(e); - default_exception_handler(e);
+unsafe extern "C" fn current_elx_irq(_e: &mut ExceptionContext) { +unsafe extern "C" fn current_elx_irq(_e: &mut ExceptionContext) {
+ use exception::asynchronous::interface::IRQManager;
+
+ let token = &exception::asynchronous::IRQContext::new(); + let token = &exception::asynchronous::IRQContext::new();
+ bsp::exception::asynchronous::irq_manager().handle_pending_irqs(token); + exception::asynchronous::irq_manager().handle_pending_irqs(token);
} }
#[no_mangle] #[no_mangle]
@ -1268,7 +1267,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2/gicd.rs 1
diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs
--- 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs --- 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/arm/gicv2.rs
@@ -0,0 +1,219 @@ @@ -0,0 +1,221 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2020-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2020-2022 Andre Richter <andre.o.richter@gmail.com>
@ -1385,6 +1384,8 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exc
+ const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. + const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space.
+ const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; + const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1;
+ +
+ pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)";
+
+ /// Create an instance. + /// Create an instance.
+ /// + ///
+ /// # Safety + /// # Safety
@ -1406,7 +1407,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/arm/gicv2.rs 13_exc
+ +
+impl driver::interface::DeviceDriver for GICv2 { +impl driver::interface::DeviceDriver for GICv2 {
+ fn compatible(&self) -> &'static str { + fn compatible(&self) -> &'static str {
+ "GICv2 (ARM Generic Interrupt Controller v2)" + Self::COMPATIBLE
+ } + }
+ +
+ unsafe fn init(&self) -> Result<(), &'static str> { + unsafe fn init(&self) -> Result<(), &'static str> {
@ -1515,7 +1516,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
}; };
use tock_registers::{ use tock_registers::{
interfaces::{ReadWriteable, Writeable}, interfaces::{ReadWriteable, Writeable},
@@ -121,7 +121,7 @@ @@ -118,7 +118,7 @@
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -1524,7 +1525,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_gpio.rs
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -197,7 +197,7 @@ @@ -200,7 +200,7 @@
/// - The user must ensure to provide a correct MMIO start address. /// - 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) -> Self {
Self { Self {
@ -1709,7 +1710,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru
diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs
--- 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs --- 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller.rs
@@ -0,0 +1,131 @@ @@ -0,0 +1,134 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2020-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2020-2022 Andre Richter <andre.o.richter@gmail.com>
@ -1740,6 +1741,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru
+ +
+/// Used for the associated type of trait [`exception::asynchronous::interface::IRQManager`]. +/// Used for the associated type of trait [`exception::asynchronous::interface::IRQManager`].
+#[derive(Copy, Clone)] +#[derive(Copy, Clone)]
+#[allow(missing_docs)]
+pub enum IRQNumber { +pub enum IRQNumber {
+ Local(LocalIRQ), + Local(LocalIRQ),
+ Peripheral(PeripheralIRQ), + Peripheral(PeripheralIRQ),
@ -1786,12 +1788,14 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru
+ const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; + const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63;
+ const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; + const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1;
+ +
+ pub const COMPATIBLE: &'static str = "BCM Interrupt Controller";
+
+ /// Create an instance. + /// Create an instance.
+ /// + ///
+ /// # Safety + /// # Safety
+ /// + ///
+ /// - The user must ensure to provide a correct MMIO start address. + /// - 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 { + pub const unsafe fn new(periph_mmio_start_addr: usize) -> Self {
+ Self { + Self {
+ periph: peripheral_ic::PeripheralIC::new(periph_mmio_start_addr), + periph: peripheral_ic::PeripheralIC::new(periph_mmio_start_addr),
+ } + }
@ -1804,7 +1808,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_interru
+ +
+impl driver::interface::DeviceDriver for InterruptController { +impl driver::interface::DeviceDriver for InterruptController {
+ fn compatible(&self) -> &'static str { + fn compatible(&self) -> &'static str {
+ "BCM Interrupt Controller" + Self::COMPATIBLE
+ } + }
+} +}
+ +
@ -1921,7 +1925,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_u
(0x44 => ICR: WriteOnly<u32, ICR::Register>), (0x44 => ICR: WriteOnly<u32, ICR::Register>),
(0x48 => @END), (0x48 => @END),
} }
@@ -182,7 +231,8 @@ @@ -179,7 +228,8 @@
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -1931,7 +1935,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_u
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -250,6 +300,14 @@ @@ -247,6 +297,14 @@
.LCR_H .LCR_H
.write(LCR_H::WLEN::EightBit + LCR_H::FEN::FifosEnabled); .write(LCR_H::WLEN::EightBit + LCR_H::FEN::FifosEnabled);
@ -1946,7 +1950,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_u
// Turn the UART on. // Turn the UART on.
self.registers self.registers
.CR .CR
@@ -332,9 +390,13 @@ @@ -335,9 +393,13 @@
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide a correct MMIO start address. /// - The user must ensure to provide a correct MMIO start address.
@ -1962,17 +1966,16 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_u
} }
} }
} }
@@ -354,6 +416,21 @@ @@ -357,6 +419,20 @@
Ok(()) Ok(())
} }
+ +
+ fn register_and_enable_irq_handler(&'static self) -> Result<(), &'static str> { + fn register_and_enable_irq_handler(&'static self) -> Result<(), &'static str> {
+ use bsp::exception::asynchronous::irq_manager; + use exception::asynchronous::{irq_manager, IRQDescriptor};
+ use exception::asynchronous::{interface::IRQManager, IRQDescriptor};
+ +
+ let descriptor = IRQDescriptor { + let descriptor = IRQDescriptor {
+ name: "BCM PL011 UART", + name: Self::COMPATIBLE,
+ handler: self, + handler: self,
+ }; + };
+ +
@ -1984,10 +1987,10 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver/bcm/bcm2xxx_pl011_u
} }
impl console::interface::Write for PL011Uart { impl console::interface::Write for PL011Uart {
@@ -400,3 +477,24 @@ @@ -405,3 +481,24 @@
self.inner.lock(|inner| inner.chars_read)
}
} }
impl console::interface::All for PL011Uart {}
+ +
+impl exception::asynchronous::interface::IRQHandler for PL011Uart { +impl exception::asynchronous::interface::IRQHandler for PL011Uart {
+ fn handle(&self) -> Result<(), &'static str> { + fn handle(&self) -> Result<(), &'static str> {
@ -2047,7 +2050,19 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/device_driver.rs 13_exceptions_pa
diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/driver.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/driver.rs diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/driver.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/driver.rs
--- 12_integrated_testing/kernel/src/bsp/raspberrypi/driver.rs --- 12_integrated_testing/kernel/src/bsp/raspberrypi/driver.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/driver.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/driver.rs
@@ -12,7 +12,7 @@ @@ -4,29 +4,43 @@
//! BSP driver support.
-use super::memory::map::mmio;
+use super::{exception, memory::map::mmio};
use crate::{bsp::device_driver, driver};
+pub use device_driver::IRQNumber;
+
//--------------------------------------------------------------------------------------------------
// Private Definitions
//--------------------------------------------------------------------------------------------------
/// Device Driver Manager type. /// Device Driver Manager type.
struct BSPDriverManager { struct BSPDriverManager {
@ -2056,16 +2071,31 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/driver.rs 13_exceptio
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -20,7 +20,11 @@ // Global instances
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
-pub(super) static PL011_UART: device_driver::PL011Uart =
- unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
+pub(super) static PL011_UART: device_driver::PL011Uart = unsafe {
+ device_driver::PL011Uart::new(
+ mmio::PL011_UART_START,
+ exception::asynchronous::irq_map::PL011_UART,
+ )
+};
static GPIO: device_driver::GPIO = unsafe { device_driver::GPIO::new(mmio::GPIO_START) };
+#[cfg(feature = "bsp_rpi3")]
+pub(super) static INTERRUPT_CONTROLLER: device_driver::InterruptController =
+ unsafe { device_driver::InterruptController::new(mmio::PERIPHERAL_INTERRUPT_CONTROLLER_START) };
+
+#[cfg(feature = "bsp_rpi4")]
+pub(super) static INTERRUPT_CONTROLLER: device_driver::GICv2 =
+ unsafe { device_driver::GICv2::new(mmio::GICD_START, mmio::GICC_START) };
+
static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager { static BSP_DRIVER_MANAGER: BSPDriverManager = BSPDriverManager {
- device_drivers: [&super::GPIO, &super::PL011_UART], - device_drivers: [&PL011_UART, &GPIO],
+ device_drivers: [ + device_drivers: [&PL011_UART, &GPIO, &INTERRUPT_CONTROLLER],
+ &super::GPIO,
+ &super::PL011_UART,
+ &super::INTERRUPT_CONTROLLER,
+ ],
}; };
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -2080,7 +2110,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/exception/asynchronou
+ +
+//! BSP asynchronous exception handling. +//! BSP asynchronous exception handling.
+ +
+use crate::{bsp, exception}; +use crate::{bsp, bsp::driver, exception};
+ +
+//-------------------------------------------------------------------------------------------------- +//--------------------------------------------------------------------------------------------------
+// Public Definitions +// Public Definitions
@ -2108,7 +2138,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/exception/asynchronou
+pub fn irq_manager() -> &'static impl exception::asynchronous::interface::IRQManager< +pub fn irq_manager() -> &'static impl exception::asynchronous::interface::IRQManager<
+ IRQNumberType = bsp::device_driver::IRQNumber, + IRQNumberType = bsp::device_driver::IRQNumber,
+> { +> {
+ &super::super::INTERRUPT_CONTROLLER + &driver::INTERRUPT_CONTROLLER
+} +}
diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/exception.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/exception.rs diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/exception.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/exception.rs
@ -2126,7 +2156,7 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/exception.rs 13_excep
diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/memory.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/memory.rs diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/memory.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/memory.rs
--- 12_integrated_testing/kernel/src/bsp/raspberrypi/memory.rs --- 12_integrated_testing/kernel/src/bsp/raspberrypi/memory.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/memory.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/bsp/raspberrypi/memory.rs
@@ -73,10 +73,12 @@ @@ -73,10 +73,11 @@
pub mod mmio { pub mod mmio {
use super::*; use super::*;
@ -2138,12 +2168,11 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi/memory.rs 13_exceptio
+ pub const PERIPHERAL_INTERRUPT_CONTROLLER_START: usize = START + 0x0000_B200; + pub const PERIPHERAL_INTERRUPT_CONTROLLER_START: usize = START + 0x0000_B200;
+ pub const GPIO_START: usize = START + GPIO_OFFSET; + pub const GPIO_START: usize = START + GPIO_OFFSET;
+ pub const PL011_UART_START: usize = START + UART_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; + pub const END_INCLUSIVE: usize = 0x4000_FFFF;
} }
/// Physical devices. /// Physical devices.
@@ -87,6 +89,8 @@ @@ -87,6 +88,8 @@
pub const START: usize = 0xFE00_0000; pub const START: usize = 0xFE00_0000;
pub const GPIO_START: usize = START + GPIO_OFFSET; pub const GPIO_START: usize = START + GPIO_OFFSET;
pub const PL011_UART_START: usize = START + UART_OFFSET; pub const PL011_UART_START: usize = START + UART_OFFSET;
@ -2164,34 +2193,6 @@ diff -uNr 12_integrated_testing/kernel/src/bsp/raspberrypi.rs 13_exceptions_part
pub mod memory; pub mod memory;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -17,8 +18,25 @@
static GPIO: device_driver::GPIO =
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_START) };
+static PL011_UART: device_driver::PL011Uart = unsafe {
+ device_driver::PL011Uart::new(
+ memory::map::mmio::PL011_UART_START,
+ exception::asynchronous::irq_map::PL011_UART,
+ )
+};
+
+#[cfg(feature = "bsp_rpi3")]
+static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe {
+ device_driver::InterruptController::new(
+ 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_START, memory::map::mmio::GICC_START)
+};
//--------------------------------------------------------------------------------------------------
// Public Code
diff -uNr 12_integrated_testing/kernel/src/cpu/smp.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/cpu/smp.rs diff -uNr 12_integrated_testing/kernel/src/cpu/smp.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/cpu/smp.rs
--- 12_integrated_testing/kernel/src/cpu/smp.rs --- 12_integrated_testing/kernel/src/cpu/smp.rs
@ -2247,10 +2248,11 @@ diff -uNr 12_integrated_testing/kernel/src/driver.rs 13_exceptions_part2_periphe
diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs
--- 12_integrated_testing/kernel/src/exception/asynchronous.rs --- 12_integrated_testing/kernel/src/exception/asynchronous.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs
@@ -8,7 +8,145 @@ @@ -8,7 +8,153 @@
#[path = "../_arch/aarch64/exception/asynchronous.rs"] #[path = "../_arch/aarch64/exception/asynchronous.rs"]
mod arch_asynchronous; mod arch_asynchronous;
+use crate::bsp;
+use core::{fmt, marker::PhantomData}; +use core::{fmt, marker::PhantomData};
+ +
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -2394,6 +2396,13 @@ diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptio
+ +
+ ret + ret
+} +}
+
+/// Return a reference to the IRQ manager.
+///
+/// This is the IRQ manager used by the architectural interrupt handling code.
+pub fn irq_manager() -> &'static dyn interface::IRQManager<IRQNumberType = bsp::driver::IRQNumber> {
+ bsp::exception::asynchronous::irq_manager()
+}
diff -uNr 12_integrated_testing/kernel/src/lib.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs diff -uNr 12_integrated_testing/kernel/src/lib.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/lib.rs
--- 12_integrated_testing/kernel/src/lib.rs --- 12_integrated_testing/kernel/src/lib.rs
@ -2428,7 +2437,7 @@ diff -uNr 12_integrated_testing/kernel/src/main.rs 13_exceptions_part2_periphera
#[no_mangle] #[no_mangle]
unsafe fn kernel_init() -> ! { unsafe fn kernel_init() -> ! {
use driver::interface::DriverManager; use driver::interface::DriverManager;
@@ -43,15 +43,27 @@ @@ -43,14 +43,27 @@
bsp::driver::driver_manager().post_device_driver_init(); bsp::driver::driver_manager().post_device_driver_init();
// println! is usable from here on. // println! is usable from here on.
@ -2451,14 +2460,13 @@ diff -uNr 12_integrated_testing/kernel/src/main.rs 13_exceptions_part2_periphera
/// The main function running after the early init. /// The main function running after the early init.
fn kernel_main() -> ! { fn kernel_main() -> ! {
- use bsp::console::console; - use console::console;
- use console::interface::All;
use driver::interface::DriverManager; use driver::interface::DriverManager;
+ use exception::asynchronous::interface::IRQManager; + use exception::asynchronous::interface::IRQManager;
info!("{}", libkernel::version()); info!("{}", libkernel::version());
info!("Booting on: {}", bsp::board_name()); info!("Booting on: {}", bsp::board_name());
@@ -79,12 +91,9 @@ @@ -78,12 +91,9 @@
info!(" {}. {}", i + 1, driver.compatible()); info!(" {}. {}", i + 1, driver.compatible());
} }
@ -2469,8 +2477,8 @@ diff -uNr 12_integrated_testing/kernel/src/main.rs 13_exceptions_part2_periphera
- // Discard any spurious received characters before going into echo mode. - // Discard any spurious received characters before going into echo mode.
- console().clear_rx(); - console().clear_rx();
- loop { - loop {
- let c = bsp::console::console().read_char(); - let c = console().read_char();
- bsp::console::console().write_char(c); - console().write_char(c);
- } - }
+ info!("Echoing input now"); + info!("Echoing input now");
+ cpu::wait_forever(); + cpu::wait_forever();
@ -2483,12 +2491,12 @@ diff -uNr 12_integrated_testing/kernel/src/panic_wait.rs 13_exceptions_part2_per
//! A panic handler that infinitely waits. //! A panic handler that infinitely waits.
-use crate::{bsp, cpu}; -use crate::{cpu, println};
+use crate::{bsp, cpu, exception}; +use crate::{cpu, exception, println};
use core::{fmt, panic::PanicInfo}; use core::panic::PanicInfo;
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@@ -77,6 +77,8 @@ @@ -61,6 +61,8 @@
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
@ -2733,7 +2741,7 @@ diff -uNr 12_integrated_testing/kernel/src/synchronization.rs 13_exceptions_part
diff -uNr 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs diff -uNr 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs
--- 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs --- 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/tests/04_exception_irq_sanity.rs
@@ -0,0 +1,66 @@ @@ -0,0 +1,67 @@
+// SPDX-License-Identifier: MIT OR Apache-2.0 +// SPDX-License-Identifier: MIT OR Apache-2.0
+// +//
+// Copyright (c) 2020-2022 Andre Richter <andre.o.richter@gmail.com> +// Copyright (c) 2020-2022 Andre Richter <andre.o.richter@gmail.com>
@ -2746,12 +2754,13 @@ diff -uNr 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs 13_excep
+#![reexport_test_harness_main = "test_main"] +#![reexport_test_harness_main = "test_main"]
+#![test_runner(libkernel::test_runner)] +#![test_runner(libkernel::test_runner)]
+ +
+use libkernel::{bsp, cpu, exception}; +use libkernel::{bsp, cpu, driver, exception};
+use test_macros::kernel_test; +use test_macros::kernel_test;
+ +
+#[no_mangle] +#[no_mangle]
+unsafe fn kernel_init() -> ! { +unsafe fn kernel_init() -> ! {
+ bsp::console::qemu_bring_up_console(); + use driver::interface::DriverManager;
+ bsp::driver::driver_manager().qemu_bring_up_console();
+ +
+ exception::handling_init(); + exception::handling_init();
+ exception::asynchronous::local_irq_unmask(); + exception::asynchronous::local_irq_unmask();

@ -11,7 +11,7 @@
//! //!
//! crate::exception::arch_exception //! crate::exception::arch_exception
use crate::{bsp, exception}; use crate::exception;
use core::{arch::global_asm, cell::UnsafeCell, fmt}; use core::{arch::global_asm, cell::UnsafeCell, fmt};
use cortex_a::{asm::barrier, registers::*}; use cortex_a::{asm::barrier, registers::*};
use tock_registers::{ use tock_registers::{
@ -104,10 +104,8 @@ unsafe extern "C" fn current_elx_synchronous(e: &mut ExceptionContext) {
#[no_mangle] #[no_mangle]
unsafe extern "C" fn current_elx_irq(_e: &mut ExceptionContext) { unsafe extern "C" fn current_elx_irq(_e: &mut ExceptionContext) {
use exception::asynchronous::interface::IRQManager;
let token = &exception::asynchronous::IRQContext::new(); let token = &exception::asynchronous::IRQContext::new();
bsp::exception::asynchronous::irq_manager().handle_pending_irqs(token); exception::asynchronous::irq_manager().handle_pending_irqs(token);
} }
#[no_mangle] #[no_mangle]

@ -114,6 +114,8 @@ impl GICv2 {
const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space. const MAX_IRQ_NUMBER: usize = 300; // Normally 1019, but keep it lower to save some space.
const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1; const NUM_IRQS: usize = Self::MAX_IRQ_NUMBER + 1;
pub const COMPATIBLE: &'static str = "GICv2 (ARM Generic Interrupt Controller v2)";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -135,7 +137,7 @@ use synchronization::interface::ReadWriteEx;
impl driver::interface::DeviceDriver for GICv2 { impl driver::interface::DeviceDriver for GICv2 {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"GICv2 (ARM Generic Interrupt Controller v2)" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {

@ -108,16 +108,13 @@ register_structs! {
/// Abstraction for the associated MMIO registers. /// Abstraction for the associated MMIO registers.
type Registers = MMIODerefWrapper<RegisterBlock>; type Registers = MMIODerefWrapper<RegisterBlock>;
//-------------------------------------------------------------------------------------------------- struct GPIOInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct GPIOInner {
registers: Registers, registers: Registers,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use GPIOInner as PanicGPIO; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the GPIO HW. /// Representation of the GPIO HW.
pub struct GPIO { pub struct GPIO {
@ -125,7 +122,7 @@ pub struct GPIO {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl GPIOInner { impl GPIOInner {
@ -189,7 +186,13 @@ impl GPIOInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl GPIO { impl GPIO {
pub const COMPATIBLE: &'static str = "BCM GPIO";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -214,6 +217,6 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for GPIO { impl driver::interface::DeviceDriver for GPIO {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM GPIO" Self::COMPATIBLE
} }
} }

@ -28,6 +28,7 @@ pub type PeripheralIRQ =
/// Used for the associated type of trait [`exception::asynchronous::interface::IRQManager`]. /// Used for the associated type of trait [`exception::asynchronous::interface::IRQManager`].
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[allow(missing_docs)]
pub enum IRQNumber { pub enum IRQNumber {
Local(LocalIRQ), Local(LocalIRQ),
Peripheral(PeripheralIRQ), Peripheral(PeripheralIRQ),
@ -74,12 +75,14 @@ impl InterruptController {
const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63; const MAX_PERIPHERAL_IRQ_NUMBER: usize = 63;
const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1; const NUM_PERIPHERAL_IRQS: usize = Self::MAX_PERIPHERAL_IRQ_NUMBER + 1;
pub const COMPATIBLE: &'static str = "BCM Interrupt Controller";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
/// ///
/// - The user must ensure to provide a correct MMIO start address. /// - 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 { pub const unsafe fn new(periph_mmio_start_addr: usize) -> Self {
Self { Self {
periph: peripheral_ic::PeripheralIC::new(periph_mmio_start_addr), periph: peripheral_ic::PeripheralIC::new(periph_mmio_start_addr),
} }
@ -92,7 +95,7 @@ impl InterruptController {
impl driver::interface::DeviceDriver for InterruptController { impl driver::interface::DeviceDriver for InterruptController {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM Interrupt Controller" Self::COMPATIBLE
} }
} }

@ -216,18 +216,15 @@ enum BlockingMode {
NonBlocking, NonBlocking,
} }
//-------------------------------------------------------------------------------------------------- struct PL011UartInner {
// Public Definitions
//--------------------------------------------------------------------------------------------------
pub struct PL011UartInner {
registers: Registers, registers: Registers,
chars_written: usize, chars_written: usize,
chars_read: usize, chars_read: usize,
} }
// Export the inner struct so that BSPs can use it for the panic handler. //--------------------------------------------------------------------------------------------------
pub use PL011UartInner as PanicUart; // Public Definitions
//--------------------------------------------------------------------------------------------------
/// Representation of the UART. /// Representation of the UART.
pub struct PL011Uart { pub struct PL011Uart {
@ -236,7 +233,7 @@ pub struct PL011Uart {
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Private Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
impl PL011UartInner { impl PL011UartInner {
@ -384,7 +381,13 @@ impl fmt::Write for PL011UartInner {
} }
} }
//--------------------------------------------------------------------------------------------------
// Public Code
//--------------------------------------------------------------------------------------------------
impl PL011Uart { impl PL011Uart {
pub const COMPATIBLE: &'static str = "BCM PL011 UART";
/// Create an instance. /// Create an instance.
/// ///
/// # Safety /// # Safety
@ -408,7 +411,7 @@ use synchronization::interface::Mutex;
impl driver::interface::DeviceDriver for PL011Uart { impl driver::interface::DeviceDriver for PL011Uart {
fn compatible(&self) -> &'static str { fn compatible(&self) -> &'static str {
"BCM PL011 UART" Self::COMPATIBLE
} }
unsafe fn init(&self) -> Result<(), &'static str> { unsafe fn init(&self) -> Result<(), &'static str> {
@ -418,11 +421,10 @@ impl driver::interface::DeviceDriver for PL011Uart {
} }
fn register_and_enable_irq_handler(&'static self) -> Result<(), &'static str> { fn register_and_enable_irq_handler(&'static self) -> Result<(), &'static str> {
use bsp::exception::asynchronous::irq_manager; use exception::asynchronous::{irq_manager, IRQDescriptor};
use exception::asynchronous::{interface::IRQManager, IRQDescriptor};
let descriptor = IRQDescriptor { let descriptor = IRQDescriptor {
name: "BCM PL011 UART", name: Self::COMPATIBLE,
handler: self, handler: self,
}; };
@ -478,6 +480,8 @@ impl console::interface::Statistics for PL011Uart {
} }
} }
impl console::interface::All for PL011Uart {}
impl exception::asynchronous::interface::IRQHandler for PL011Uart { impl exception::asynchronous::interface::IRQHandler for PL011Uart {
fn handle(&self) -> Result<(), &'static str> { fn handle(&self) -> Result<(), &'static str> {
self.inner.lock(|inner| { self.inner.lock(|inner| {

@ -10,34 +10,6 @@ pub mod driver;
pub mod exception; pub mod exception;
pub mod memory; pub mod memory;
//--------------------------------------------------------------------------------------------------
// Global instances
//--------------------------------------------------------------------------------------------------
use super::device_driver;
static GPIO: device_driver::GPIO =
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_START,
exception::asynchronous::irq_map::PL011_UART,
)
};
#[cfg(feature = "bsp_rpi3")]
static INTERRUPT_CONTROLLER: device_driver::InterruptController = unsafe {
device_driver::InterruptController::new(
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_START, memory::map::mmio::GICC_START)
};
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save