From 56a650397dea6546f0f9df19762096616e13ce77 Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Thu, 17 Oct 2019 21:49:38 +0200 Subject: [PATCH] Having a little code formatting party --- 01_wait_forever/src/bsp.rs | 2 +- 01_wait_forever/src/main.rs | 4 +- 02_runtime_init/README.md | 27 ++++- 02_runtime_init/kernel | Bin 68568 -> 68568 bytes 02_runtime_init/kernel8.img | Bin 368 -> 368 bytes 02_runtime_init/src/arch/aarch64.rs | 4 +- 02_runtime_init/src/bsp.rs | 2 +- 02_runtime_init/src/main.rs | 7 +- 02_runtime_init/src/runtime_init.rs | 4 +- 03_hacky_hello_world/README.md | 57 ++++++--- 03_hacky_hello_world/kernel | Bin 79144 -> 79144 bytes 03_hacky_hello_world/kernel8.img | Bin 6629 -> 6629 bytes 03_hacky_hello_world/src/arch/aarch64.rs | 4 +- 03_hacky_hello_world/src/bsp.rs | 2 +- 03_hacky_hello_world/src/bsp/rpi3.rs | 9 +- 03_hacky_hello_world/src/interface.rs | 6 +- 03_hacky_hello_world/src/main.rs | 16 ++- 03_hacky_hello_world/src/runtime_init.rs | 4 +- 04_zero_overhead_abstraction/README.md | 15 ++- .../src/arch/aarch64.rs | 7 +- 04_zero_overhead_abstraction/src/bsp.rs | 2 +- 04_zero_overhead_abstraction/src/bsp/rpi3.rs | 9 +- 04_zero_overhead_abstraction/src/interface.rs | 6 +- 04_zero_overhead_abstraction/src/main.rs | 16 ++- .../src/runtime_init.rs | 4 +- 05_safe_globals/README.md | 109 ++++++++---------- 05_safe_globals/src/arch/aarch64.rs | 7 +- 05_safe_globals/src/arch/aarch64/sync.rs | 15 +-- 05_safe_globals/src/bsp/rpi3.rs | 33 +++--- 05_safe_globals/src/interface.rs | 18 ++- 05_safe_globals/src/main.rs | 19 +-- 05_safe_globals/src/runtime_init.rs | 4 +- 06_drivers_gpio_uart/README.md | 102 ++++++++-------- 06_drivers_gpio_uart/kernel | Bin 83208 -> 83200 bytes 06_drivers_gpio_uart/kernel8.img | Bin 7856 -> 7856 bytes 06_drivers_gpio_uart/src/arch/aarch64.rs | 7 +- 06_drivers_gpio_uart/src/arch/aarch64/sync.rs | 15 +-- .../src/bsp/driver/bcm/bcm2837_gpio.rs | 8 +- .../src/bsp/driver/bcm/bcm2xxx_mini_uart.rs | 44 ++++--- 06_drivers_gpio_uart/src/bsp/rpi3.rs | 16 ++- 06_drivers_gpio_uart/src/interface.rs | 18 ++- 06_drivers_gpio_uart/src/main.rs | 19 +-- 06_drivers_gpio_uart/src/runtime_init.rs | 4 +- 07_uart_chainloader/README.md | 101 +++++++++------- 07_uart_chainloader/kernel | Bin 85032 -> 85048 bytes 07_uart_chainloader/kernel8.img | Bin 8776 -> 8776 bytes 07_uart_chainloader/src/arch/aarch64.rs | 7 +- 07_uart_chainloader/src/arch/aarch64/sync.rs | 15 +-- .../src/bsp/driver/bcm/bcm2837_gpio.rs | 8 +- .../src/bsp/driver/bcm/bcm2xxx_mini_uart.rs | 44 ++++--- 07_uart_chainloader/src/bsp/rpi3.rs | 16 ++- 07_uart_chainloader/src/interface.rs | 22 ++-- 07_uart_chainloader/src/main.rs | 24 ++-- 07_uart_chainloader/src/relocate.rs | 13 +-- 07_uart_chainloader/src/runtime_init.rs | 21 ++-- utils/clean_all.rb | 16 +-- utils/clippy_all.rb | 14 +-- utils/diff_all.rb | 14 +-- utils/fmt_all.rb | 14 +-- utils/helpers/copyrighted.rb | 48 ++++---- utils/helpers/tutorial_folders.rb | 10 +- utils/make_all.rb | 20 ++-- utils/sanity_checks.rb | 36 +++--- 63 files changed, 562 insertions(+), 526 deletions(-) diff --git a/01_wait_forever/src/bsp.rs b/01_wait_forever/src/bsp.rs index 7932435d..66c068da 100644 --- a/01_wait_forever/src/bsp.rs +++ b/01_wait_forever/src/bsp.rs @@ -5,7 +5,7 @@ //! Conditional exporting of Board Support Packages. #[cfg(feature = "bsp_rpi3")] -pub mod rpi3; +mod rpi3; #[cfg(feature = "bsp_rpi3")] pub use rpi3::*; diff --git a/01_wait_forever/src/main.rs b/01_wait_forever/src/main.rs index 0d631cb1..81f6c115 100644 --- a/01_wait_forever/src/main.rs +++ b/01_wait_forever/src/main.rs @@ -12,8 +12,8 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; // Conditionally includes the selected `BSP` code. diff --git a/02_runtime_init/README.md b/02_runtime_init/README.md index b5678141..91ac991d 100644 --- a/02_runtime_init/README.md +++ b/02_runtime_init/README.md @@ -50,6 +50,22 @@ diff -uNr 01_wait_forever/src/arch/aarch64/start.S 02_runtime_init/src/arch/aarc + b 1b // We should never reach here. But just in case, + // park this core aswell +diff -uNr 01_wait_forever/src/arch/aarch64.rs 02_runtime_init/src/arch/aarch64.rs +--- 01_wait_forever/src/arch/aarch64.rs ++++ 02_runtime_init/src/arch/aarch64.rs +@@ -6,9 +6,9 @@ + + global_asm!(include_str!("aarch64/start.S")); + +-//////////////////////////////////////////////////////////////////////////////// ++//////////////////////////////////////////////////////////////////////////////////////////////////// + // Implementation of the kernel's architecture abstraction code +-//////////////////////////////////////////////////////////////////////////////// ++//////////////////////////////////////////////////////////////////////////////////////////////////// + + /// Pause execution on the calling CPU core. + #[inline(always)] + diff -uNr 01_wait_forever/src/bsp/rpi3/link.ld 02_runtime_init/src/bsp/rpi3/link.ld --- 01_wait_forever/src/bsp/rpi3/link.ld +++ 02_runtime_init/src/bsp/rpi3/link.ld @@ -81,12 +97,11 @@ diff -uNr 01_wait_forever/src/bsp/rpi3/link.ld 02_runtime_init/src/bsp/rpi3/link diff -uNr 01_wait_forever/src/main.rs 02_runtime_init/src/main.rs --- 01_wait_forever/src/main.rs +++ 02_runtime_init/src/main.rs -@@ -16,9 +16,16 @@ - // `_start()` function, the first function to run. +@@ -16,9 +16,15 @@ + // the first function to run. mod arch; -+// `_start()` then calls `runtime_init::init()`, which on completion, jumps to -+// `kernel_entry()`. ++// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. +mod runtime_init; + // Conditionally includes the selected `BSP` code. @@ -110,8 +125,8 @@ diff -uNr 01_wait_forever/src/runtime_init.rs 02_runtime_init/src/runtime_init.r + +//! Rust runtime initialization code. + -+/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -+/// then calls the kernel entry. ++/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the ++/// kernel entry. +/// +/// Called from `BSP` code. +/// diff --git a/02_runtime_init/kernel b/02_runtime_init/kernel index 65d62d90e94bd02a812710201b78387812e88c7e..96813b4ec6ec051474eb7347e07ffc8821dd5597 100644 GIT binary patch delta 128 zcmcaHo#n=KmWC~i9*m5#+dUZ>-5D7JwohbY{LaXjxxJHxk)4szboxYAMsY@a2<1Kf zAdn}S#LU1Tz`)4Bz`y~-2(W(pM^?sEW)VXZLqjtI3v+X03lnooOG^_|1H-5DAEw@+kZ{LaXjvAvUpk)4szWcox_MsY?v2<0{X zAdn}S$jrbXz`)4Bz`y~-2(WJZM^?sEW?>TpQ*#pwBMT!_OG7g=VxI4ggPF95(;} diff --git a/02_runtime_init/kernel8.img b/02_runtime_init/kernel8.img index 44f9a3cd9507ca2d43890ba451f6082c78ccea01..38201b8c5ff5f474731ea4a60142c854c6fee1ad 100755 GIT binary patch delta 13 Ucmeys^nq!E2P32GWKTwQ03#O!00000 delta 13 Ucmeys^nq!E2P320WKTwQ03#d(0RR91 diff --git a/02_runtime_init/src/arch/aarch64.rs b/02_runtime_init/src/arch/aarch64.rs index 60b1a5e0..98cff2dc 100644 --- a/02_runtime_init/src/arch/aarch64.rs +++ b/02_runtime_init/src/arch/aarch64.rs @@ -6,9 +6,9 @@ global_asm!(include_str!("aarch64/start.S")); -//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// // Implementation of the kernel's architecture abstraction code -//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////// /// Pause execution on the calling CPU core. #[inline(always)] diff --git a/02_runtime_init/src/bsp.rs b/02_runtime_init/src/bsp.rs index 7932435d..66c068da 100644 --- a/02_runtime_init/src/bsp.rs +++ b/02_runtime_init/src/bsp.rs @@ -5,7 +5,7 @@ //! Conditional exporting of Board Support Packages. #[cfg(feature = "bsp_rpi3")] -pub mod rpi3; +mod rpi3; #[cfg(feature = "bsp_rpi3")] pub use rpi3::*; diff --git a/02_runtime_init/src/main.rs b/02_runtime_init/src/main.rs index 230a91ef..2f0c51dd 100644 --- a/02_runtime_init/src/main.rs +++ b/02_runtime_init/src/main.rs @@ -12,12 +12,11 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; -// `_start()` then calls `runtime_init::init()`, which on completion, jumps to -// `kernel_entry()`. +// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. mod runtime_init; // Conditionally includes the selected `BSP` code. diff --git a/02_runtime_init/src/runtime_init.rs b/02_runtime_init/src/runtime_init.rs index f27c8cec..fcc9b3f4 100644 --- a/02_runtime_init/src/runtime_init.rs +++ b/02_runtime_init/src/runtime_init.rs @@ -4,8 +4,8 @@ //! Rust runtime initialization code. -/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -/// then calls the kernel entry. +/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the +/// kernel entry. /// /// Called from `BSP` code. /// diff --git a/03_hacky_hello_world/README.md b/03_hacky_hello_world/README.md index 1a70fc9c..84adc25d 100644 --- a/03_hacky_hello_world/README.md +++ b/03_hacky_hello_world/README.md @@ -28,10 +28,26 @@ diff -uNr 02_runtime_init/Makefile 03_hacky_hello_world/Makefile RUSTC_MISC_ARGS = -C target-cpu=cortex-a53 endif +diff -uNr 02_runtime_init/src/arch/aarch64.rs 03_hacky_hello_world/src/arch/aarch64.rs +--- 02_runtime_init/src/arch/aarch64.rs ++++ 03_hacky_hello_world/src/arch/aarch64.rs +@@ -6,9 +6,9 @@ + + global_asm!(include_str!("aarch64/start.S")); + +-//////////////////////////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + // Implementation of the kernel's architecture abstraction code +-//////////////////////////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + + /// Pause execution on the calling CPU core. + #[inline(always)] + diff -uNr 02_runtime_init/src/bsp/rpi3.rs 03_hacky_hello_world/src/bsp/rpi3.rs --- 02_runtime_init/src/bsp/rpi3.rs +++ 03_hacky_hello_world/src/bsp/rpi3.rs -@@ -4,4 +4,36 @@ +@@ -4,4 +4,35 @@ //! Board Support Package for the Raspberry Pi 3. @@ -42,9 +58,8 @@ diff -uNr 02_runtime_init/src/bsp/rpi3.rs 03_hacky_hello_world/src/bsp/rpi3.rs +/// A mystical, magical device for generating QEMU output out of the void. +struct QEMUOutput; + -+/// Implementing `console::Write` enables usage of the `format_args!` macros, -+/// which in turn are used to implement the `kernel`'s `print!` and `println!` -+/// macros. ++/// Implementing `console::Write` enables usage of the `format_args!` macros, which in turn are used ++/// to implement the `kernel`'s `print!` and `println!` macros. +/// +/// See [`src/print.rs`]. +/// @@ -61,9 +76,9 @@ diff -uNr 02_runtime_init/src/bsp/rpi3.rs 03_hacky_hello_world/src/bsp/rpi3.rs + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// Implementation of the kernel's BSP calls -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + +/// Returns a ready-to-use `console::Write` implementation. +pub fn console() -> impl interface::console::Write { @@ -98,9 +113,9 @@ diff -uNr 02_runtime_init/src/interface.rs 03_hacky_hello_world/src/interface.rs +pub mod console { + /// Console write functions. + /// -+ /// `core::fmt::Write` is exactly what we need for now. Re-export it here -+ /// because implementing `console::Write` gives a better hint to the reader -+ /// about the intention. ++ /// `core::fmt::Write` is exactly what we need for now. Re-export it here because ++ /// implementing `console::Write` gives a better hint to the reader about the ++ /// intention. + pub use core::fmt::Write; + + /// Console read functions. @@ -114,15 +129,21 @@ diff -uNr 02_runtime_init/src/interface.rs 03_hacky_hello_world/src/interface.rs diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs --- 02_runtime_init/src/main.rs +++ 03_hacky_hello_world/src/main.rs -@@ -6,9 +6,17 @@ +@@ -6,9 +6,23 @@ #![doc(html_logo_url = "https://git.io/JeGIp")] //! The `kernel` +//! -+//! The `kernel` is composed by glueing together hardware-specific Board Support -+//! Package (`BSP`) code and hardware-agnostic `kernel` code through the -+//! [`kernel::interface`] traits. ++//! The `kernel` is composed by glueing together code from +//! ++//! - [Hardware-specific Board Support Packages] (`BSPs`). ++//! - [Architecture-specific code]. ++//! - HW- and architecture-agnostic `kernel` code. ++//! ++//! using the [`kernel::interface`] traits. ++//! ++//! [Hardware-specific Board Support Packages]: bsp/index.html ++//! [Architecture-specific code]: arch/index.html +//! [`kernel::interface`]: interface/index.html #![feature(asm)] @@ -132,7 +153,15 @@ diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs #![no_main] #![no_std] -@@ -23,9 +31,13 @@ +@@ -16,15 +30,20 @@ + // the first function to run. + mod arch; + +-// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. ++// `_start()` then calls `runtime_init::init()`, which on completion, jumps to ++// `kernel_entry()`. + mod runtime_init; + // Conditionally includes the selected `BSP` code. mod bsp; diff --git a/03_hacky_hello_world/kernel b/03_hacky_hello_world/kernel index a4c51d45931436972c3334baf1e19cecfcc5d245..856bb0ab991a59c5e2ff38249eef9bde8fe7b24b 100755 GIT binary patch delta 450 zcmZvXJxfAS7{{Og_4?KeL}YTUOv{7_qkHwH(o#c%ZB7+LA_OiD1wjN2EzK^`Q&ZGX z4h;#xv7v@&E~25O4-i6_-=K3nx2-cg&*A)j&&#Q|^mhKIG#Wa4Q?c`XZ-kx1__i4Dr?alUErlDgwf<3 zCp~qO@#0r<)1%~!E5GxFw2Xj!b$V6ZiEA!?X=ZJXr7-(15#magHua$gF)gy5Z&i}ZQbFV%l&-Lk6UlL>rMCJElvWM6sG|!d$7UnA*|y< z6o%miws|##79M$V1T7=qMFdTw$e_H)Gu4Si2ci(hCJ^F>QB;fxpVF>_N>h=j$fXG0 zaVGLn2o0ay9z)QW@e^qp=*6qNU8t^W9F3uZE53$j6IUGk#tj=srTu|AN?rqUTRmr7a5jAfbGylHVXf$4uiEs0rC VO~9}7j{#j=rcs1e>)|C6;a?-;PY3`2 diff --git a/03_hacky_hello_world/kernel8.img b/03_hacky_hello_world/kernel8.img index 3d9040d81a620904a11ffcc41b04bb1568e59a71..81ca0086fe92466abe8b3aafaabd6a3d24ec858c 100755 GIT binary patch delta 14 VcmaEA{M2~E3{ggd%`-)PSO75H1#kcW delta 14 VcmaEA{M2~E3{gg{%`-)PSO74&1!@2Q diff --git a/03_hacky_hello_world/src/arch/aarch64.rs b/03_hacky_hello_world/src/arch/aarch64.rs index 60b1a5e0..91fc1708 100644 --- a/03_hacky_hello_world/src/arch/aarch64.rs +++ b/03_hacky_hello_world/src/arch/aarch64.rs @@ -6,9 +6,9 @@ global_asm!(include_str!("aarch64/start.S")); -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's architecture abstraction code -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Pause execution on the calling CPU core. #[inline(always)] diff --git a/03_hacky_hello_world/src/bsp.rs b/03_hacky_hello_world/src/bsp.rs index 7932435d..66c068da 100644 --- a/03_hacky_hello_world/src/bsp.rs +++ b/03_hacky_hello_world/src/bsp.rs @@ -5,7 +5,7 @@ //! Conditional exporting of Board Support Packages. #[cfg(feature = "bsp_rpi3")] -pub mod rpi3; +mod rpi3; #[cfg(feature = "bsp_rpi3")] pub use rpi3::*; diff --git a/03_hacky_hello_world/src/bsp/rpi3.rs b/03_hacky_hello_world/src/bsp/rpi3.rs index af001076..b5cae078 100644 --- a/03_hacky_hello_world/src/bsp/rpi3.rs +++ b/03_hacky_hello_world/src/bsp/rpi3.rs @@ -10,9 +10,8 @@ use core::fmt; /// A mystical, magical device for generating QEMU output out of the void. struct QEMUOutput; -/// Implementing `console::Write` enables usage of the `format_args!` macros, -/// which in turn are used to implement the `kernel`'s `print!` and `println!` -/// macros. +/// Implementing `console::Write` enables usage of the `format_args!` macros, which in turn are used +/// to implement the `kernel`'s `print!` and `println!` macros. /// /// See [`src/print.rs`]. /// @@ -29,9 +28,9 @@ impl interface::console::Write for QEMUOutput { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's BSP calls -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Returns a ready-to-use `console::Write` implementation. pub fn console() -> impl interface::console::Write { diff --git a/03_hacky_hello_world/src/interface.rs b/03_hacky_hello_world/src/interface.rs index 62e2294c..79d74a5f 100644 --- a/03_hacky_hello_world/src/interface.rs +++ b/03_hacky_hello_world/src/interface.rs @@ -22,9 +22,9 @@ pub mod console { /// Console write functions. /// - /// `core::fmt::Write` is exactly what we need for now. Re-export it here - /// because implementing `console::Write` gives a better hint to the reader - /// about the intention. + /// `core::fmt::Write` is exactly what we need for now. Re-export it here because + /// implementing `console::Write` gives a better hint to the reader about the + /// intention. pub use core::fmt::Write; /// Console read functions. diff --git a/03_hacky_hello_world/src/main.rs b/03_hacky_hello_world/src/main.rs index b5779850..6e998a3b 100644 --- a/03_hacky_hello_world/src/main.rs +++ b/03_hacky_hello_world/src/main.rs @@ -7,10 +7,16 @@ //! The `kernel` //! -//! The `kernel` is composed by glueing together hardware-specific Board Support -//! Package (`BSP`) code and hardware-agnostic `kernel` code through the -//! [`kernel::interface`] traits. +//! The `kernel` is composed by glueing together code from //! +//! - [Hardware-specific Board Support Packages] (`BSPs`). +//! - [Architecture-specific code]. +//! - HW- and architecture-agnostic `kernel` code. +//! +//! using the [`kernel::interface`] traits. +//! +//! [Hardware-specific Board Support Packages]: bsp/index.html +//! [Architecture-specific code]: arch/index.html //! [`kernel::interface`]: interface/index.html #![feature(asm)] @@ -20,8 +26,8 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; // `_start()` then calls `runtime_init::init()`, which on completion, jumps to diff --git a/03_hacky_hello_world/src/runtime_init.rs b/03_hacky_hello_world/src/runtime_init.rs index f27c8cec..fcc9b3f4 100644 --- a/03_hacky_hello_world/src/runtime_init.rs +++ b/03_hacky_hello_world/src/runtime_init.rs @@ -4,8 +4,8 @@ //! Rust runtime initialization code. -/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -/// then calls the kernel entry. +/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the +/// kernel entry. /// /// Called from `BSP` code. /// diff --git a/04_zero_overhead_abstraction/README.md b/04_zero_overhead_abstraction/README.md index 87201a9c..1bcd0a4e 100644 --- a/04_zero_overhead_abstraction/README.md +++ b/04_zero_overhead_abstraction/README.md @@ -55,7 +55,7 @@ diff -uNr 03_hacky_hello_world/src/arch/aarch64/start.S 04_zero_overhead_abstrac diff -uNr 03_hacky_hello_world/src/arch/aarch64.rs 04_zero_overhead_abstraction/src/arch/aarch64.rs --- 03_hacky_hello_world/src/arch/aarch64.rs +++ 04_zero_overhead_abstraction/src/arch/aarch64.rs -@@ -4,7 +4,29 @@ +@@ -4,7 +4,28 @@ //! AArch64. @@ -65,8 +65,7 @@ diff -uNr 03_hacky_hello_world/src/arch/aarch64.rs 04_zero_overhead_abstraction/ + +/// The entry of the `kernel` binary. +/// -+/// The function must be named `_start`, because the linker is looking for this -+/// exact name. ++/// The function must be named `_start`, because the linker is looking for this exact name. +/// +/// # Safety +/// @@ -84,9 +83,9 @@ diff -uNr 03_hacky_hello_world/src/arch/aarch64.rs 04_zero_overhead_abstraction/ + } +} - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- // Implementation of the kernel's architecture abstraction code -@@ -13,9 +35,7 @@ +@@ -13,9 +34,7 @@ /// Pause execution on the calling CPU core. #[inline(always)] pub fn wait_forever() -> ! { @@ -116,8 +115,8 @@ diff -uNr 03_hacky_hello_world/src/bsp/rpi3.rs 04_zero_overhead_abstraction/src/ diff -uNr 03_hacky_hello_world/src/main.rs 04_zero_overhead_abstraction/src/main.rs --- 03_hacky_hello_world/src/main.rs +++ 04_zero_overhead_abstraction/src/main.rs -@@ -13,9 +13,7 @@ - //! +@@ -19,9 +19,7 @@ + //! [Architecture-specific code]: arch/index.html //! [`kernel::interface`]: interface/index.html -#![feature(asm)] @@ -126,7 +125,7 @@ diff -uNr 03_hacky_hello_world/src/main.rs 04_zero_overhead_abstraction/src/main #![feature(panic_info_message)] #![no_main] #![no_std] -@@ -37,7 +35,8 @@ +@@ -43,7 +41,8 @@ /// Entrypoint of the `kernel`. fn kernel_entry() -> ! { diff --git a/04_zero_overhead_abstraction/src/arch/aarch64.rs b/04_zero_overhead_abstraction/src/arch/aarch64.rs index 01655aa4..3dc16a08 100644 --- a/04_zero_overhead_abstraction/src/arch/aarch64.rs +++ b/04_zero_overhead_abstraction/src/arch/aarch64.rs @@ -9,8 +9,7 @@ use cortex_a::{asm, regs::*}; /// The entry of the `kernel` binary. /// -/// The function must be named `_start`, because the linker is looking for this -/// exact name. +/// The function must be named `_start`, because the linker is looking for this exact name. /// /// # Safety /// @@ -28,9 +27,9 @@ pub unsafe extern "C" fn _start() -> ! { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's architecture abstraction code -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Pause execution on the calling CPU core. #[inline(always)] diff --git a/04_zero_overhead_abstraction/src/bsp.rs b/04_zero_overhead_abstraction/src/bsp.rs index 7932435d..66c068da 100644 --- a/04_zero_overhead_abstraction/src/bsp.rs +++ b/04_zero_overhead_abstraction/src/bsp.rs @@ -5,7 +5,7 @@ //! Conditional exporting of Board Support Packages. #[cfg(feature = "bsp_rpi3")] -pub mod rpi3; +mod rpi3; #[cfg(feature = "bsp_rpi3")] pub use rpi3::*; diff --git a/04_zero_overhead_abstraction/src/bsp/rpi3.rs b/04_zero_overhead_abstraction/src/bsp/rpi3.rs index b6aafd02..53b96d27 100644 --- a/04_zero_overhead_abstraction/src/bsp/rpi3.rs +++ b/04_zero_overhead_abstraction/src/bsp/rpi3.rs @@ -13,9 +13,8 @@ pub const BOOT_CORE_STACK_START: u64 = 0x80_000; /// A mystical, magical device for generating QEMU output out of the void. struct QEMUOutput; -/// Implementing `console::Write` enables usage of the `format_args!` macros, -/// which in turn are used to implement the `kernel`'s `print!` and `println!` -/// macros. +/// Implementing `console::Write` enables usage of the `format_args!` macros, which in turn are used +/// to implement the `kernel`'s `print!` and `println!` macros. /// /// See [`src/print.rs`]. /// @@ -32,9 +31,9 @@ impl interface::console::Write for QEMUOutput { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's BSP calls -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Returns a ready-to-use `console::Write` implementation. pub fn console() -> impl interface::console::Write { diff --git a/04_zero_overhead_abstraction/src/interface.rs b/04_zero_overhead_abstraction/src/interface.rs index 62e2294c..79d74a5f 100644 --- a/04_zero_overhead_abstraction/src/interface.rs +++ b/04_zero_overhead_abstraction/src/interface.rs @@ -22,9 +22,9 @@ pub mod console { /// Console write functions. /// - /// `core::fmt::Write` is exactly what we need for now. Re-export it here - /// because implementing `console::Write` gives a better hint to the reader - /// about the intention. + /// `core::fmt::Write` is exactly what we need for now. Re-export it here because + /// implementing `console::Write` gives a better hint to the reader about the + /// intention. pub use core::fmt::Write; /// Console read functions. diff --git a/04_zero_overhead_abstraction/src/main.rs b/04_zero_overhead_abstraction/src/main.rs index 2675db6c..18beb6f8 100644 --- a/04_zero_overhead_abstraction/src/main.rs +++ b/04_zero_overhead_abstraction/src/main.rs @@ -7,10 +7,16 @@ //! The `kernel` //! -//! The `kernel` is composed by glueing together hardware-specific Board Support -//! Package (`BSP`) code and hardware-agnostic `kernel` code through the -//! [`kernel::interface`] traits. +//! The `kernel` is composed by glueing together code from //! +//! - [Hardware-specific Board Support Packages] (`BSPs`). +//! - [Architecture-specific code]. +//! - HW- and architecture-agnostic `kernel` code. +//! +//! using the [`kernel::interface`] traits. +//! +//! [Hardware-specific Board Support Packages]: bsp/index.html +//! [Architecture-specific code]: arch/index.html //! [`kernel::interface`]: interface/index.html #![feature(format_args_nl)] @@ -18,8 +24,8 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; // `_start()` then calls `runtime_init::init()`, which on completion, jumps to diff --git a/04_zero_overhead_abstraction/src/runtime_init.rs b/04_zero_overhead_abstraction/src/runtime_init.rs index 5d9bf311..c41702b4 100644 --- a/04_zero_overhead_abstraction/src/runtime_init.rs +++ b/04_zero_overhead_abstraction/src/runtime_init.rs @@ -4,8 +4,8 @@ //! Rust runtime initialization code. -/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -/// then calls the kernel entry. +/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the +/// kernel entry. /// /// Called from `BSP` code. /// diff --git a/05_safe_globals/README.md b/05_safe_globals/README.md index 4c5c8092..e136be54 100644 --- a/05_safe_globals/README.md +++ b/05_safe_globals/README.md @@ -45,7 +45,7 @@ you can check out implemntations in the [spin crate] or the [parking lot crate]. diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/src/arch/aarch64/sync.rs --- 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs +++ 05_safe_globals/src/arch/aarch64/sync.rs -@@ -0,0 +1,47 @@ +@@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) 2018-2019 Andre Richter @@ -59,13 +59,11 @@ diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/ +/// +/// Used to introduce [interior mutability]. +/// -+/// In contrast to a real Mutex implementation, does not protect against -+/// concurrent access to the contained data. This part is preserved for later -+/// lessons. ++/// In contrast to a real Mutex implementation, does not protect against concurrent access to the ++/// contained data. This part is preserved for later lessons. +/// -+/// The lock will only be used as long as it is safe to do so, i.e. as long as -+/// the kernel is executing single-threaded, aka only running on a single core -+/// with interrupts disabled. ++/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is ++/// executing single-threaded, aka only running on a single core with interrupts disabled. +/// +/// [interior mutability]: https://doc.rust-lang.org/std/cell/index.html +pub struct NullLock { @@ -87,9 +85,8 @@ diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64/sync.rs 05_safe_globals/ + type Data = T; + + fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { -+ // In a real lock, there would be code encapsulating this line that -+ // ensures that this mutable reference will ever only be given out once -+ // at a time. ++ // In a real lock, there would be code encapsulating this line that ensures that this ++ // mutable reference will ever only be given out once at a time. + f(unsafe { &mut *self.data.get() }) + } +} @@ -110,7 +107,7 @@ diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64.rs 05_safe_globals/src/a diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/rpi3.rs --- 04_zero_overhead_abstraction/src/bsp/rpi3.rs +++ 05_safe_globals/src/bsp/rpi3.rs -@@ -4,39 +4,115 @@ +@@ -4,38 +4,114 @@ //! Board Support Package for the Raspberry Pi 3. @@ -142,14 +139,13 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + } +} --/// Implementing `console::Write` enables usage of the `format_args!` macros, -+/// 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. -+/// macros. By implementing `write_str()`, we get `write_fmt()` automatically. +-/// Implementing `console::Write` enables usage of the `format_args!` macros, which in turn are used +-/// to implement the `kernel`'s `print!` and `println!` macros. ++/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are ++/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, ++/// we get `write_fmt()` automatically. +/// -+/// 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. /// /// See [`src/print.rs`]. /// @@ -175,9 +171,9 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r } } - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- +// BSP-public -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + +/// The main struct. +pub struct QEMUOutput { @@ -192,18 +188,18 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// OS interface implementations -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + -+/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded -+/// by a Mutex to serialize access. ++/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to ++/// serialize access. +impl interface::console::Write for QEMUOutput { + fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { + use interface::sync::Mutex; + -+ // Fully qualified syntax for the call to -+ // `core::fmt::Write::write:fmt()` to increase readability. ++ // Fully qualified syntax for the call to `core::fmt::Write::write:fmt()` to increase ++ // readability. + let mut r = &self.inner; + r.lock(|inner| fmt::Write::write_fmt(inner, args)) + } @@ -220,15 +216,15 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// Global instances -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + +static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new(); + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's BSP calls - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- -/// Returns a ready-to-use `console::Write` implementation. -pub fn console() -> impl interface::console::Write { @@ -238,23 +234,10 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r + &QEMU_OUTPUT } -diff -uNr 04_zero_overhead_abstraction/src/bsp.rs 05_safe_globals/src/bsp.rs ---- 04_zero_overhead_abstraction/src/bsp.rs -+++ 05_safe_globals/src/bsp.rs -@@ -5,7 +5,7 @@ - //! Conditional exporting of Board Support Packages. - - #[cfg(feature = "bsp_rpi3")] --pub mod rpi3; -+mod rpi3; - - #[cfg(feature = "bsp_rpi3")] - pub use rpi3::*; - diff -uNr 04_zero_overhead_abstraction/src/interface.rs 05_safe_globals/src/interface.rs --- 04_zero_overhead_abstraction/src/interface.rs +++ 05_safe_globals/src/interface.rs -@@ -20,17 +20,68 @@ +@@ -20,17 +20,66 @@ /// System console operations. pub mod console { @@ -262,9 +245,9 @@ diff -uNr 04_zero_overhead_abstraction/src/interface.rs 05_safe_globals/src/inte + /// Console write functions. - /// -- /// `core::fmt::Write` is exactly what we need for now. Re-export it here -- /// because implementing `console::Write` gives a better hint to the reader -- /// about the intention. +- /// `core::fmt::Write` is exactly what we need for now. Re-export it here because +- /// implementing `console::Write` gives a better hint to the reader about the +- /// intention. - pub use core::fmt::Write; + pub trait Write { + fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; @@ -297,20 +280,19 @@ diff -uNr 04_zero_overhead_abstraction/src/interface.rs 05_safe_globals/src/inte + +/// Synchronization primitives. +pub mod sync { -+ /// Any object implementing this trait guarantees exclusive access to the -+ /// data contained within the mutex for the duration of the lock. ++ /// Any object implementing this trait guarantees exclusive access to the data contained within ++ /// the mutex for the duration of the lock. + /// + /// The trait follows the [Rust embedded WG's -+ /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) -+ /// and therefore provides some goodness such as [deadlock ++ /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) and therefore ++ /// provides some goodness such as [deadlock + /// prevention](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md#design-decisions-and-compatibility). + /// + /// # Example + /// -+ /// Since the lock function takes an `&mut self` to enable -+ /// deadlock-prevention, the trait is best implemented **for a reference to -+ /// a container struct**, and has a usage pattern that might feel strange at -+ /// first: ++ /// Since the lock function takes an `&mut self` to enable deadlock-prevention, the trait is ++ /// best implemented **for a reference to a container struct**, and has a usage pattern that ++ /// might feel strange at first: + /// + /// ``` + /// static MUT: Mutex> = Mutex::new(RefCell::new(0)); @@ -324,8 +306,7 @@ diff -uNr 04_zero_overhead_abstraction/src/interface.rs 05_safe_globals/src/inte + /// Type of data encapsulated by the mutex. + type Data; + -+ /// Creates a critical section and grants temporary mutable access to -+ /// the encapsulated data. ++ /// Creates a critical section and grants temporary mutable access to the encapsulated data. + fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R; + } } @@ -333,7 +314,7 @@ diff -uNr 04_zero_overhead_abstraction/src/interface.rs 05_safe_globals/src/inte diff -uNr 04_zero_overhead_abstraction/src/main.rs 05_safe_globals/src/main.rs --- 04_zero_overhead_abstraction/src/main.rs +++ 05_safe_globals/src/main.rs -@@ -15,6 +15,7 @@ +@@ -21,6 +21,7 @@ #![feature(format_args_nl)] #![feature(panic_info_message)] @@ -341,7 +322,17 @@ diff -uNr 04_zero_overhead_abstraction/src/main.rs 05_safe_globals/src/main.rs #![no_main] #![no_std] -@@ -35,8 +36,12 @@ +@@ -28,8 +29,7 @@ + // the first function to run. + mod arch; + +-// `_start()` then calls `runtime_init::init()`, which on completion, jumps to +-// `kernel_entry()`. ++// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. + mod runtime_init; + + // Conditionally includes the selected `BSP` code. +@@ -41,8 +41,12 @@ /// Entrypoint of the `kernel`. fn kernel_entry() -> ! { diff --git a/05_safe_globals/src/arch/aarch64.rs b/05_safe_globals/src/arch/aarch64.rs index a5c5a0ce..a89bded3 100644 --- a/05_safe_globals/src/arch/aarch64.rs +++ b/05_safe_globals/src/arch/aarch64.rs @@ -11,8 +11,7 @@ use cortex_a::{asm, regs::*}; /// The entry of the `kernel` binary. /// -/// The function must be named `_start`, because the linker is looking for this -/// exact name. +/// The function must be named `_start`, because the linker is looking for this exact name. /// /// # Safety /// @@ -30,9 +29,9 @@ pub unsafe extern "C" fn _start() -> ! { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's architecture abstraction code -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Pause execution on the calling CPU core. #[inline(always)] diff --git a/05_safe_globals/src/arch/aarch64/sync.rs b/05_safe_globals/src/arch/aarch64/sync.rs index 62dc069c..dfebc0e1 100644 --- a/05_safe_globals/src/arch/aarch64/sync.rs +++ b/05_safe_globals/src/arch/aarch64/sync.rs @@ -11,13 +11,11 @@ use core::cell::UnsafeCell; /// /// Used to introduce [interior mutability]. /// -/// In contrast to a real Mutex implementation, does not protect against -/// concurrent access to the contained data. This part is preserved for later -/// lessons. +/// In contrast to a real Mutex implementation, does not protect against concurrent access to the +/// contained data. This part is preserved for later lessons. /// -/// The lock will only be used as long as it is safe to do so, i.e. as long as -/// the kernel is executing single-threaded, aka only running on a single core -/// with interrupts disabled. +/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is +/// executing single-threaded, aka only running on a single core with interrupts disabled. /// /// [interior mutability]: https://doc.rust-lang.org/std/cell/index.html pub struct NullLock { @@ -39,9 +37,8 @@ impl interface::sync::Mutex for &NullLock { type Data = T; fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { - // In a real lock, there would be code encapsulating this line that - // ensures that this mutable reference will ever only be given out once - // at a time. + // In a real lock, there would be code encapsulating this line that ensures that this + // mutable reference will ever only be given out once at a time. f(unsafe { &mut *self.data.get() }) } } diff --git a/05_safe_globals/src/bsp/rpi3.rs b/05_safe_globals/src/bsp/rpi3.rs index 06359a96..d3eed60d 100644 --- a/05_safe_globals/src/bsp/rpi3.rs +++ b/05_safe_globals/src/bsp/rpi3.rs @@ -30,12 +30,11 @@ impl QEMUOutputInner { } } -/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, -/// which in turn are used to implement the `kernel`'s `print!` and `println!` -/// macros. By implementing `write_str()`, we get `write_fmt()` automatically. +/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are +/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, +/// we get `write_fmt()` automatically. /// -/// 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. /// /// See [`src/print.rs`]. /// @@ -57,9 +56,9 @@ impl fmt::Write for QEMUOutputInner { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // BSP-public -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// The main struct. pub struct QEMUOutput { @@ -74,18 +73,18 @@ impl QEMUOutput { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // OS interface implementations -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- -/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded -/// by a Mutex to serialize access. +/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to +/// serialize access. impl interface::console::Write for QEMUOutput { fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { use interface::sync::Mutex; - // Fully qualified syntax for the call to - // `core::fmt::Write::write:fmt()` to increase readability. + // Fully qualified syntax for the call to `core::fmt::Write::write:fmt()` to increase + // readability. let mut r = &self.inner; r.lock(|inner| fmt::Write::write_fmt(inner, args)) } @@ -102,15 +101,15 @@ impl interface::console::Statistics for QEMUOutput { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Global instances -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new(); -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's BSP calls -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Return a reference to a `console::All` implementation. pub fn console() -> &'static impl interface::console::All { diff --git a/05_safe_globals/src/interface.rs b/05_safe_globals/src/interface.rs index 4878e6f3..005e625d 100644 --- a/05_safe_globals/src/interface.rs +++ b/05_safe_globals/src/interface.rs @@ -53,20 +53,19 @@ pub mod console { /// Synchronization primitives. pub mod sync { - /// Any object implementing this trait guarantees exclusive access to the - /// data contained within the mutex for the duration of the lock. + /// Any object implementing this trait guarantees exclusive access to the data contained within + /// the mutex for the duration of the lock. /// /// The trait follows the [Rust embedded WG's - /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) - /// and therefore provides some goodness such as [deadlock + /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) and therefore + /// provides some goodness such as [deadlock /// prevention](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md#design-decisions-and-compatibility). /// /// # Example /// - /// Since the lock function takes an `&mut self` to enable - /// deadlock-prevention, the trait is best implemented **for a reference to - /// a container struct**, and has a usage pattern that might feel strange at - /// first: + /// Since the lock function takes an `&mut self` to enable deadlock-prevention, the trait is + /// best implemented **for a reference to a container struct**, and has a usage pattern that + /// might feel strange at first: /// /// ``` /// static MUT: Mutex> = Mutex::new(RefCell::new(0)); @@ -80,8 +79,7 @@ pub mod sync { /// Type of data encapsulated by the mutex. type Data; - /// Creates a critical section and grants temporary mutable access to - /// the encapsulated data. + /// Creates a critical section and grants temporary mutable access to the encapsulated data. fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R; } } diff --git a/05_safe_globals/src/main.rs b/05_safe_globals/src/main.rs index 6e7c02c8..fe9f0e54 100644 --- a/05_safe_globals/src/main.rs +++ b/05_safe_globals/src/main.rs @@ -7,10 +7,16 @@ //! The `kernel` //! -//! The `kernel` is composed by glueing together hardware-specific Board Support -//! Package (`BSP`) code and hardware-agnostic `kernel` code through the -//! [`kernel::interface`] traits. +//! The `kernel` is composed by glueing together code from //! +//! - [Hardware-specific Board Support Packages] (`BSPs`). +//! - [Architecture-specific code]. +//! - HW- and architecture-agnostic `kernel` code. +//! +//! using the [`kernel::interface`] traits. +//! +//! [Hardware-specific Board Support Packages]: bsp/index.html +//! [Architecture-specific code]: arch/index.html //! [`kernel::interface`]: interface/index.html #![feature(format_args_nl)] @@ -19,12 +25,11 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; -// `_start()` then calls `runtime_init::init()`, which on completion, jumps to -// `kernel_entry()`. +// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. mod runtime_init; // Conditionally includes the selected `BSP` code. diff --git a/05_safe_globals/src/runtime_init.rs b/05_safe_globals/src/runtime_init.rs index 5d9bf311..c41702b4 100644 --- a/05_safe_globals/src/runtime_init.rs +++ b/05_safe_globals/src/runtime_init.rs @@ -4,8 +4,8 @@ //! Rust runtime initialization code. -/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -/// then calls the kernel entry. +/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the +/// kernel entry. /// /// Called from `BSP` code. /// diff --git a/06_drivers_gpio_uart/README.md b/06_drivers_gpio_uart/README.md index 88efc9fc..ac52ff1d 100644 --- a/06_drivers_gpio_uart/README.md +++ b/06_drivers_gpio_uart/README.md @@ -55,9 +55,9 @@ diff -uNr 05_safe_globals/Cargo.toml 06_drivers_gpio_uart/Cargo.toml diff -uNr 05_safe_globals/src/arch/aarch64.rs 06_drivers_gpio_uart/src/arch/aarch64.rs --- 05_safe_globals/src/arch/aarch64.rs +++ 06_drivers_gpio_uart/src/arch/aarch64.rs -@@ -34,6 +34,8 @@ +@@ -33,6 +33,8 @@ // Implementation of the kernel's architecture abstraction code - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- +pub use asm::nop; + @@ -198,9 +198,9 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2837_gpio.rs 06_drivers_gpio_uar + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// BSP-public -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +use interface::sync::Mutex; + +/// The driver's main struct. @@ -222,9 +222,9 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2837_gpio.rs 06_drivers_gpio_uar + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// OS interface implementations -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + +impl interface::driver::DeviceDriver for GPIO { + fn compatible(&self) -> &str { @@ -235,7 +235,7 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2837_gpio.rs 06_drivers_gpio_uar diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs --- 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs +++ 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs -@@ -0,0 +1,287 @@ +@@ -0,0 +1,283 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) 2018-2019 Andre Richter @@ -255,11 +255,10 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpi + + /// Auxiliary enables + AUX_ENABLES [ -+ /// If set the mini UART is enabled. The UART will immediately -+ /// start receiving data, especially if the UART1_RX line is -+ /// low. -+ /// If clear the mini UART is disabled. That also disables any -+ /// mini UART register access ++ /// If set the mini UART is enabled. The UART will immediately start receiving data, ++ /// especially if the UART1_RX line is low. ++ /// ++ /// If clear the mini UART is disabled. That also disables any mini UART register access + MINI_UART_ENABLE OFFSET(0) NUMBITS(1) [] + ], + @@ -285,16 +284,14 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpi + + /// Mini Uart Line Status + AUX_MU_LSR [ -+ /// This bit is set if the transmit FIFO is empty and the transmitter is -+ /// idle. (Finished shifting out the last bit). ++ /// This bit is set if the transmit FIFO is empty and the transmitter is idle. (Finished ++ /// shifting out the last bit). + TX_IDLE OFFSET(6) NUMBITS(1) [], + -+ /// This bit is set if the transmit FIFO can accept at least -+ /// one byte. ++ /// This bit is set if the transmit FIFO can accept at least one byte. + TX_EMPTY OFFSET(5) NUMBITS(1) [], + -+ /// This bit is set if the receive FIFO holds at least 1 -+ /// symbol. ++ /// This bit is set if the receive FIFO holds at least 1 symbol. + DATA_READY OFFSET(0) NUMBITS(1) [] + ], + @@ -393,12 +390,11 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpi + } +} + -+/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, -+/// which in turn are used to implement the `kernel`'s `print!` and `println!` -+/// macros. By implementing `write_str()`, we get `write_fmt()` automatically. ++/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are ++/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, ++/// we get `write_fmt()` automatically. +/// -+/// 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. +/// +/// See [`src/print.rs`]. +/// @@ -421,9 +417,9 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpi + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// BSP-public -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- + +/// The driver's main struct. +pub struct MiniUart { @@ -441,9 +437,9 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpi + } +} + -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +// OS interface implementations -+//////////////////////////////////////////////////////////////////////////////// ++//-------------------------------------------------------------------------------------------------- +use interface::sync::Mutex; + +impl interface::driver::DeviceDriver for MiniUart { @@ -477,16 +473,16 @@ diff -uNr 05_safe_globals/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 06_drivers_gpi +} + +impl interface::console::Write for MiniUart { -+ /// Passthrough of `args` to the `core::fmt::Write` implementation, but -+ /// guarded by a Mutex to serialize access. ++ /// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to ++ /// serialize access. + fn write_char(&self, c: char) { + let mut r = &self.inner; + r.lock(|inner| inner.write_char(c)); + } + + fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { -+ // Fully qualified syntax for the call to -+ // `core::fmt::Write::write:fmt()` to increase readability. ++ // Fully qualified syntax for the call to `core::fmt::Write::write:fmt()` to increase ++ // readability. + let mut r = &self.inner; + r.lock(|inner| fmt::Write::write_fmt(inner, args)) + } @@ -579,7 +575,7 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/memory_map.rs 06_drivers_gpio_uart/src/bs diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs --- 05_safe_globals/src/bsp/rpi3.rs +++ 06_drivers_gpio_uart/src/bsp/rpi3.rs -@@ -4,115 +4,59 @@ +@@ -4,114 +4,58 @@ //! Board Support Package for the Raspberry Pi 3. @@ -613,12 +609,11 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs - } -} - --/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, --/// which in turn are used to implement the `kernel`'s `print!` and `println!` --/// macros. By implementing `write_str()`, we get `write_fmt()` automatically. +-/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are +-/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, +-/// we get `write_fmt()` automatically. -/// --/// 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. -/// -/// See [`src/print.rs`]. -/// @@ -641,10 +636,10 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs - } -} - - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- -// BSP-public +// Global BSP driver instances - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- -/// The main struct. -pub struct QEMUOutput { @@ -662,19 +657,19 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs +static MINI_UART: driver::MiniUart = + unsafe { driver::MiniUart::new(memory_map::mmio::MINI_UART_BASE) }; - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- -// OS interface implementations +// Implementation of the kernel's BSP calls - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- --/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded --/// by a Mutex to serialize access. +-/// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to +-/// serialize access. -impl interface::console::Write for QEMUOutput { - fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { - use interface::sync::Mutex; - -- // Fully qualified syntax for the call to -- // `core::fmt::Write::write:fmt()` to increase readability. +- // Fully qualified syntax for the call to `core::fmt::Write::write:fmt()` to increase +- // readability. - let mut r = &self.inner; - r.lock(|inner| fmt::Write::write_fmt(inner, args)) - } @@ -697,9 +692,9 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs + &MINI_UART } --//////////////////////////////////////////////////////////////////////////////// +-//-------------------------------------------------------------------------------------------------- -// Global instances --//////////////////////////////////////////////////////////////////////////////// +-//-------------------------------------------------------------------------------------------------- - -static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new(); +/// Return an array of references to all `DeviceDriver` compatible `BSP` @@ -712,18 +707,17 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs + [&GPIO, &MINI_UART] +} --//////////////////////////////////////////////////////////////////////////////// +-//-------------------------------------------------------------------------------------------------- -// Implementation of the kernel's BSP calls --//////////////////////////////////////////////////////////////////////////////// +-//-------------------------------------------------------------------------------------------------- +/// The BSP's main initialization function. +/// +/// Called early on kernel start. +pub fn init() { + for i in device_drivers().iter() { + if let Err(()) = i.init() { -+ // This message will only be readable if, at the time of failure, -+ // the return value of `bsp::console()` is already in functioning -+ // state. ++ // This message will only be readable if, at the time of failure, the return value of ++ // `bsp::console()` is already in functioning state. + panic!("Error loading driver: {}", i.compatible()) + } + } @@ -759,7 +753,7 @@ diff -uNr 05_safe_globals/src/interface.rs 06_drivers_gpio_uart/src/interface.rs fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; } -@@ -85,3 +86,20 @@ +@@ -83,3 +84,20 @@ fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R; } } @@ -784,7 +778,7 @@ diff -uNr 05_safe_globals/src/interface.rs 06_drivers_gpio_uart/src/interface.rs diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs --- 05_safe_globals/src/main.rs +++ 06_drivers_gpio_uart/src/main.rs -@@ -36,12 +36,23 @@ +@@ -41,12 +41,23 @@ /// Entrypoint of the `kernel`. fn kernel_entry() -> ! { diff --git a/06_drivers_gpio_uart/kernel b/06_drivers_gpio_uart/kernel index 3378937528be6f0c003108303e244a22d393f671..1afa74470c3998354a7851ab229a4adb7b64e11d 100755 GIT binary patch delta 684 zcmaKnPbfrD6vprOWX$+GhT^@2GMJeshM6AMP?MrqSeRmANlF-2{$xkQWP{a7HtZ=D zda{v)Vx=i%VIfN!Qp!eh-<-D`?&93;`F-Da&dqEWu5K6ZMj+PAa}#7h+SdjiJ^Db2 z5YRM{(Y?Ys?YSz1kIw2*gCn}D#{d#k8N?N~C>vDGTY3%RT|e;&p=l7`9=49S)+hRC zP^uZ**9Zb8=%@)bx>n4Csts0`yXrp5I(Wmy!!C}v_=XTtVII;$cti_*gs_Ygdpe9M zV3x8G?BJQkO{J-(6;o+0>{K)Ewb+lJ*PE>6f$Et%gO%L(mvDap+&`vNs|t(LORGvz z(NUGTn7j0~G9d!O5wfR|Eh0l`Q_Fv;&p7zBm@!u&k`#0BW(DJoQU<-Qdz8i3V#X|?s&HWF?P(xO^Pe=fJx8v}{IMNlzX8WNGT0}&!I5QawLZ~9`a z$sj?HYZD`jbTXJ2Bo<;O;@qAyHr(OdOa1w&k~N`yn_s!dGFC4=MB3hex|Q zR?Qd`h2>QTv%YxgWXw(Hel+5k?)(@*KY0SU!7dd8eE2|b0eq;ZPR0}k?AtD)Q!@HO zpRL?lFr956V1^3qXjCg*;-UthueG zJ>eEuuMqr+4lL~Q3Vh-acvPl`%-a|aoef$%(W52xM30`(jd*ugDrp#$Gmt7zt_^IK rC!St(G;7gpb~zU ! { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's architecture abstraction code -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- pub use asm::nop; diff --git a/06_drivers_gpio_uart/src/arch/aarch64/sync.rs b/06_drivers_gpio_uart/src/arch/aarch64/sync.rs index 62dc069c..dfebc0e1 100644 --- a/06_drivers_gpio_uart/src/arch/aarch64/sync.rs +++ b/06_drivers_gpio_uart/src/arch/aarch64/sync.rs @@ -11,13 +11,11 @@ use core::cell::UnsafeCell; /// /// Used to introduce [interior mutability]. /// -/// In contrast to a real Mutex implementation, does not protect against -/// concurrent access to the contained data. This part is preserved for later -/// lessons. +/// In contrast to a real Mutex implementation, does not protect against concurrent access to the +/// contained data. This part is preserved for later lessons. /// -/// The lock will only be used as long as it is safe to do so, i.e. as long as -/// the kernel is executing single-threaded, aka only running on a single core -/// with interrupts disabled. +/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is +/// executing single-threaded, aka only running on a single core with interrupts disabled. /// /// [interior mutability]: https://doc.rust-lang.org/std/cell/index.html pub struct NullLock { @@ -39,9 +37,8 @@ impl interface::sync::Mutex for &NullLock { type Data = T; fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { - // In a real lock, there would be code encapsulating this line that - // ensures that this mutable reference will ever only be given out once - // at a time. + // In a real lock, there would be code encapsulating this line that ensures that this + // mutable reference will ever only be given out once at a time. f(unsafe { &mut *self.data.get() }) } } diff --git a/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs index 195973b1..361f901c 100644 --- a/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs +++ b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2837_gpio.rs @@ -127,9 +127,9 @@ impl GPIOInner { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // BSP-public -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- use interface::sync::Mutex; /// The driver's main struct. @@ -151,9 +151,9 @@ impl GPIO { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // OS interface implementations -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- impl interface::driver::DeviceDriver for GPIO { fn compatible(&self) -> &str { diff --git a/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs index 7fdcf7ce..bbc7781d 100644 --- a/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs +++ b/06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs @@ -17,11 +17,10 @@ register_bitfields! { /// Auxiliary enables AUX_ENABLES [ - /// If set the mini UART is enabled. The UART will immediately - /// start receiving data, especially if the UART1_RX line is - /// low. - /// If clear the mini UART is disabled. That also disables any - /// mini UART register access + /// If set the mini UART is enabled. The UART will immediately start receiving data, + /// especially if the UART1_RX line is low. + /// + /// If clear the mini UART is disabled. That also disables any mini UART register access MINI_UART_ENABLE OFFSET(0) NUMBITS(1) [] ], @@ -47,16 +46,14 @@ register_bitfields! { /// Mini Uart Line Status AUX_MU_LSR [ - /// This bit is set if the transmit FIFO is empty and the transmitter is - /// idle. (Finished shifting out the last bit). + /// This bit is set if the transmit FIFO is empty and the transmitter is idle. (Finished + /// shifting out the last bit). TX_IDLE OFFSET(6) NUMBITS(1) [], - /// This bit is set if the transmit FIFO can accept at least - /// one byte. + /// This bit is set if the transmit FIFO can accept at least one byte. TX_EMPTY OFFSET(5) NUMBITS(1) [], - /// This bit is set if the receive FIFO holds at least 1 - /// symbol. + /// This bit is set if the receive FIFO holds at least 1 symbol. DATA_READY OFFSET(0) NUMBITS(1) [] ], @@ -155,12 +152,11 @@ impl MiniUartInner { } } -/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, -/// which in turn are used to implement the `kernel`'s `print!` and `println!` -/// macros. By implementing `write_str()`, we get `write_fmt()` automatically. +/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are +/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, +/// we get `write_fmt()` automatically. /// -/// 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. /// /// See [`src/print.rs`]. /// @@ -182,9 +178,9 @@ impl fmt::Write for MiniUartInner { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // BSP-public -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// The driver's main struct. pub struct MiniUart { @@ -202,9 +198,9 @@ impl MiniUart { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // OS interface implementations -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- use interface::sync::Mutex; impl interface::driver::DeviceDriver for MiniUart { @@ -238,16 +234,16 @@ impl interface::driver::DeviceDriver for MiniUart { } impl interface::console::Write for MiniUart { - /// Passthrough of `args` to the `core::fmt::Write` implementation, but - /// guarded by a Mutex to serialize access. + /// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to + /// serialize access. fn write_char(&self, c: char) { let mut r = &self.inner; r.lock(|inner| inner.write_char(c)); } fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { - // Fully qualified syntax for the call to - // `core::fmt::Write::write:fmt()` to increase readability. + // Fully qualified syntax for the call to `core::fmt::Write::write:fmt()` to increase + // readability. let mut r = &self.inner; r.lock(|inner| fmt::Write::write_fmt(inner, args)) } diff --git a/06_drivers_gpio_uart/src/bsp/rpi3.rs b/06_drivers_gpio_uart/src/bsp/rpi3.rs index 88a54894..32e045ca 100644 --- a/06_drivers_gpio_uart/src/bsp/rpi3.rs +++ b/06_drivers_gpio_uart/src/bsp/rpi3.rs @@ -12,17 +12,17 @@ use crate::interface; pub const BOOT_CORE_ID: u64 = 0; pub const BOOT_CORE_STACK_START: u64 = 0x80_000; -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Global BSP driver instances -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- static GPIO: driver::GPIO = unsafe { driver::GPIO::new(memory_map::mmio::GPIO_BASE) }; static MINI_UART: driver::MiniUart = unsafe { driver::MiniUart::new(memory_map::mmio::MINI_UART_BASE) }; -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's BSP calls -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Board identification. pub fn board_name() -> &'static str { @@ -34,8 +34,7 @@ pub fn console() -> &'static impl interface::console::All { &MINI_UART } -/// Return an array of references to all `DeviceDriver` compatible `BSP` -/// drivers. +/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers. /// /// # Safety /// @@ -50,9 +49,8 @@ pub fn device_drivers() -> [&'static dyn interface::driver::DeviceDriver; 2] { pub fn init() { for i in device_drivers().iter() { if let Err(()) = i.init() { - // This message will only be readable if, at the time of failure, - // the return value of `bsp::console()` is already in functioning - // state. + // This message will only be readable if, at the time of failure, the return value of + // `bsp::console()` is already in functioning state. panic!("Error loading driver: {}", i.compatible()) } } diff --git a/06_drivers_gpio_uart/src/interface.rs b/06_drivers_gpio_uart/src/interface.rs index d47f45d6..acffde62 100644 --- a/06_drivers_gpio_uart/src/interface.rs +++ b/06_drivers_gpio_uart/src/interface.rs @@ -54,20 +54,19 @@ pub mod console { /// Synchronization primitives. pub mod sync { - /// Any object implementing this trait guarantees exclusive access to the - /// data contained within the mutex for the duration of the lock. + /// Any object implementing this trait guarantees exclusive access to the data contained within + /// the mutex for the duration of the lock. /// /// The trait follows the [Rust embedded WG's - /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) - /// and therefore provides some goodness such as [deadlock + /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) and therefore + /// provides some goodness such as [deadlock /// prevention](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md#design-decisions-and-compatibility). /// /// # Example /// - /// Since the lock function takes an `&mut self` to enable - /// deadlock-prevention, the trait is best implemented **for a reference to - /// a container struct**, and has a usage pattern that might feel strange at - /// first: + /// Since the lock function takes an `&mut self` to enable deadlock-prevention, the trait is + /// best implemented **for a reference to a container struct**, and has a usage pattern that + /// might feel strange at first: /// /// ``` /// static MUT: Mutex> = Mutex::new(RefCell::new(0)); @@ -81,8 +80,7 @@ pub mod sync { /// Type of data encapsulated by the mutex. type Data; - /// Creates a critical section and grants temporary mutable access to - /// the encapsulated data. + /// Creates a critical section and grants temporary mutable access to the encapsulated data. fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R; } } diff --git a/06_drivers_gpio_uart/src/main.rs b/06_drivers_gpio_uart/src/main.rs index 560bbad9..6ea3bf1f 100644 --- a/06_drivers_gpio_uart/src/main.rs +++ b/06_drivers_gpio_uart/src/main.rs @@ -7,10 +7,16 @@ //! The `kernel` //! -//! The `kernel` is composed by glueing together hardware-specific Board Support -//! Package (`BSP`) code and hardware-agnostic `kernel` code through the -//! [`kernel::interface`] traits. +//! The `kernel` is composed by glueing together code from //! +//! - [Hardware-specific Board Support Packages] (`BSPs`). +//! - [Architecture-specific code]. +//! - HW- and architecture-agnostic `kernel` code. +//! +//! using the [`kernel::interface`] traits. +//! +//! [Hardware-specific Board Support Packages]: bsp/index.html +//! [Architecture-specific code]: arch/index.html //! [`kernel::interface`]: interface/index.html #![feature(format_args_nl)] @@ -19,12 +25,11 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; -// `_start()` then calls `runtime_init::init()`, which on completion, jumps to -// `kernel_entry()`. +// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. mod runtime_init; // Conditionally includes the selected `BSP` code. diff --git a/06_drivers_gpio_uart/src/runtime_init.rs b/06_drivers_gpio_uart/src/runtime_init.rs index 5d9bf311..c41702b4 100644 --- a/06_drivers_gpio_uart/src/runtime_init.rs +++ b/06_drivers_gpio_uart/src/runtime_init.rs @@ -4,8 +4,8 @@ //! Rust runtime initialization code. -/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -/// then calls the kernel entry. +/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the +/// kernel entry. /// /// Called from `BSP` code. /// diff --git a/07_uart_chainloader/README.md b/07_uart_chainloader/README.md index 812df04d..10a93c65 100644 --- a/07_uart_chainloader/README.md +++ b/07_uart_chainloader/README.md @@ -103,7 +103,7 @@ diff -uNr 06_drivers_gpio_uart/Makefile 07_uart_chainloader/Makefile diff -uNr 06_drivers_gpio_uart/src/arch/aarch64.rs 07_uart_chainloader/src/arch/aarch64.rs --- 06_drivers_gpio_uart/src/arch/aarch64.rs +++ 07_uart_chainloader/src/arch/aarch64.rs -@@ -23,7 +23,7 @@ +@@ -22,7 +22,7 @@ if bsp::BOOT_CORE_ID == MPIDR_EL1.get() & CORE_MASK { SP.set(bsp::BOOT_CORE_STACK_START); @@ -116,7 +116,22 @@ diff -uNr 06_drivers_gpio_uart/src/arch/aarch64.rs 07_uart_chainloader/src/arch/ diff -uNr 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs --- 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs +++ 07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs -@@ -251,6 +251,15 @@ +@@ -50,10 +50,12 @@ + /// shifting out the last bit). + TX_IDLE OFFSET(6) NUMBITS(1) [], + +- /// This bit is set if the transmit FIFO can accept at least one byte. ++ /// This bit is set if the transmit FIFO can accept at least ++ /// one byte. + TX_EMPTY OFFSET(5) NUMBITS(1) [], + +- /// This bit is set if the receive FIFO holds at least 1 symbol. ++ /// This bit is set if the receive FIFO holds at least 1 ++ /// symbol. + DATA_READY OFFSET(0) NUMBITS(1) [] + ], + +@@ -247,6 +249,15 @@ let mut r = &self.inner; r.lock(|inner| fmt::Write::write_fmt(inner, args)) } @@ -132,15 +147,14 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs 07_uart_c } impl interface::console::Read for MiniUart { -@@ -267,14 +276,14 @@ +@@ -263,14 +274,14 @@ } // Read one character. - let mut ret = inner.AUX_MU_IO.get() as u8 as char; - - // Convert carrige return to newline. -- if ret == ' -' { +- if ret == ' ' { - ret = ' ' - } @@ -199,9 +213,19 @@ diff -uNr 06_drivers_gpio_uart/src/bsp/rpi3.rs 07_uart_chainloader/src/bsp/rpi3. +/// The address on which the RPi3 firmware loads every binary by default. +pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x80_000; + - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- // Global BSP driver instances - //////////////////////////////////////////////////////////////////////////////// + //-------------------------------------------------------------------------------------------------- +@@ -34,8 +37,7 @@ + &MINI_UART + } + +-/// Return an array of references to all `DeviceDriver` compatible `BSP` +-/// drivers. ++/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers. + /// + /// # Safety + /// diff -uNr 06_drivers_gpio_uart/src/interface.rs 07_uart_chainloader/src/interface.rs --- 06_drivers_gpio_uart/src/interface.rs @@ -211,8 +235,8 @@ diff -uNr 06_drivers_gpio_uart/src/interface.rs 07_uart_chainloader/src/interfac fn write_char(&self, c: char); fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; + -+ /// Block execution until the last character has been physically put on -+ /// the TX wire (draining TX buffers/FIFOs, if any). ++ /// Block execution until the last character has been physically put on the TX wire ++ /// (draining TX buffers/FIFOs, if any). + fn flush(&self); } @@ -231,21 +255,20 @@ diff -uNr 06_drivers_gpio_uart/src/interface.rs 07_uart_chainloader/src/interfac diff -uNr 06_drivers_gpio_uart/src/main.rs 07_uart_chainloader/src/main.rs --- 06_drivers_gpio_uart/src/main.rs +++ 07_uart_chainloader/src/main.rs -@@ -23,8 +23,11 @@ - // `_start()` function, the first function to run. +@@ -29,7 +29,11 @@ + // the first function to run. mod arch; --// `_start()` then calls `runtime_init::init()`, which on completion, jumps to --// `kernel_entry()`. +-// `_start()` then calls `runtime_init::init()`, which on completion, jumps to `kernel_entry()`. +// `_start()` then calls `relocate::relocate_self()`. +mod relocate; + -+// `relocate::relocate_self()` calls `runtime_init::init()`, which on -+// completion, jumps to `kernel_entry()`. ++// `relocate::relocate_self()` calls `runtime_init::init()`, which on completion, jumps to ++// `kernel_entry()`. mod runtime_init; // Conditionally includes the selected `BSP` code. -@@ -41,18 +44,48 @@ +@@ -46,18 +50,48 @@ // Run the BSP's initialization code. bsp::init(); @@ -260,8 +283,8 @@ diff -uNr 06_drivers_gpio_uart/src/main.rs 07_uart_chainloader/src/main.rs + println!("[ML] Requesting binary"); + bsp::console().flush(); + -+ // Clear the RX FIFOs, if any, of spurious received characters before -+ // starting with the loader protocol. ++ // Clear the RX FIFOs, if any, of spurious received characters before starting with the loader ++ // protocol. + bsp::console().clear(); + + // Notify raspbootcom to send the binary. @@ -309,15 +332,15 @@ diff -uNr 06_drivers_gpio_uart/src/main.rs 07_uart_chainloader/src/main.rs diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate.rs --- 06_drivers_gpio_uart/src/relocate.rs +++ 07_uart_chainloader/src/relocate.rs -@@ -0,0 +1,47 @@ +@@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +// +// Copyright (c) 2018-2019 Andre Richter + +//! Relocation code. + -+/// Relocates the own binary from `bsp::BOARD_DEFAULT_LOAD_ADDRESS` to the -+/// `__binary_start` address from the linker script. ++/// Relocates the own binary from `bsp::BOARD_DEFAULT_LOAD_ADDRESS` to the `__binary_start` address ++/// from the linker script. +/// +/// # Safety +/// @@ -341,8 +364,7 @@ diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate. + + // Copy the whole binary. + // -+ // This is essentially a `memcpy()` optimized for throughput by transferring -+ // in chunks of T. ++ // This is essentially a `memcpy()` optimized for throughput by transferring in chunks of T. + let n = binary_size_in_byte / core::mem::size_of::(); + for _ in 0..n { + use core::ptr; @@ -352,28 +374,26 @@ diff -uNr 06_drivers_gpio_uart/src/relocate.rs 07_uart_chainloader/src/relocate. + src_addr = src_addr.offset(1); + } + -+ // Call `init()` through a trait object, causing the jump to use an absolute -+ // address to reach the relocated binary. An elaborate explanation can be -+ // found in the runtime_init.rs source comments. ++ // Call `init()` through a trait object, causing the jump to use an absolute address to reach ++ // the relocated binary. An elaborate explanation can be found in the runtime_init.rs source ++ // comments. + crate::runtime_init::get().init() +} diff -uNr 06_drivers_gpio_uart/src/runtime_init.rs 07_uart_chainloader/src/runtime_init.rs --- 06_drivers_gpio_uart/src/runtime_init.rs +++ 07_uart_chainloader/src/runtime_init.rs -@@ -4,23 +4,44 @@ +@@ -4,23 +4,41 @@ //! Rust runtime initialization code. --/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, --/// then calls the kernel entry. -+/// We are outsmarting the compiler here by using a trait as a layer of -+/// indirection. Because we are generating PIC code, a static dispatch to -+/// `init()` would generate a relative jump from the callee to `init()`. -+/// However, when calling `init()`, code just finished copying the binary to the -+/// actual link-time address, and hence is still running at whatever location -+/// the previous loader has put it. So we do not want a relative jump, because -+/// it would not jump to the relocated code. +-/// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the +-/// kernel entry. ++/// We are outsmarting the compiler here by using a trait as a layer of indirection. Because we are ++/// generating PIC code, a static dispatch to `init()` would generate a relative jump from the ++/// callee to `init()`. However, when calling `init()`, code just finished copying the binary to the ++/// actual link-time address, and hence is still running at whatever location the previous loader ++/// has put it. So we do not want a relative jump, because it would not jump to the relocated code. /// -/// Called from `BSP` code. -/// @@ -385,12 +405,11 @@ diff -uNr 06_drivers_gpio_uart/src/runtime_init.rs 07_uart_chainloader/src/runti - // Boundaries of the .bss section, provided by the linker script. - static mut __bss_start: u64; - static mut __bss_end: u64; -+/// By indirecting through a trait object, we can make use of the property that -+/// vtables store absolute addresses. So calling `init()` this way will kick -+/// execution to the relocated binary. ++/// By indirecting through a trait object, we can make use of the property that vtables store ++/// absolute addresses. So calling `init()` this way will kick execution to the relocated binary. +pub trait RunTimeInit { -+ /// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, -+ /// then calls the kernel entry. ++ /// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the ++ /// kernel entry. + /// + /// Called from `BSP` code. + /// diff --git a/07_uart_chainloader/kernel b/07_uart_chainloader/kernel index 2f774bea8a51c22d809eefe35c604b0f955dd1b6..f2e0c63f0e9d5711b050b37340ec9e8106355b15 100755 GIT binary patch delta 753 zcmZ{gy=zlZ7{`6VpJwD3u!$du!6PH#cpGL(_oJY6dL`Iux;+oitNR7tLSL zW_nYarMM^+w1XTs>C`%DMG&DP1v}^o-laW=AjC;bqh%dlXf+J<0qKt74 z_AIDnajjxCaviKU;idtkTo&$M|-+Al;jeq^v?nk>-1 z!jBDp_n-TSki`rtbTx~QxKDNtOZX|)bGQ!l)3*_3V#H8k-rF%874B3y~}YSJ{`{1EUb3R0^M8YkOHaZ(hNLR}nMx)tir z^eL@E7jaNrDpz!{La~E`N}(bMl@6jqg%lU3dQQ(-LZfFm2fpWh-|zd*=DcHN-Z5+9 z;!WK~9ljZ8v@-_WdD@>M(rR#pHOkb$uj@sOLDN{e@^1^{Cnzp{Uf9MX`~*G_OfK6m zW=zw-R-IDjkt#Ms4JKyLPrE{OT_RNL)cE$ujFDVes^4PeM%}?l4y_ls?;@1kB zs>yRY5_m!3!~fg}q61Ot4B{ArWP~t@U-m)>J%EEQA7e)MmC7~Cs$^%UitePjFgI=4 z!%uLa>Fl9gAipAez%EK#@Z%{BTYTHEbYo!$r*stM#q)oUKEi*<%fNG`HK0075Mq4z zJvU<>=3vjNC03Murv`yT{6mGiw>W#gmozBww!#6o#I4Hyj^;SVZ~64mt`NWX$}DH0 z6t^q!B4vd5hwX}^yTF@>M52*+GLlSMu|(WT#1mws;G?M&0=eMl6xMUqo7+%JORact uCp^0c>app4As*!Iub>S4+w2#WWQFRMax0!4J diff --git a/07_uart_chainloader/kernel8.img b/07_uart_chainloader/kernel8.img index 54e5f87f8a747f905f5fd7bbe4bdf17d8f688a8b..411fbb818495fb2f674bb2faade66106e48b4beb 100755 GIT binary patch delta 13 UcmX@%a>8Z92SrB9$sZNN0WKE?5C8xG delta 13 UcmX@%a>8Z92SrBf$sZNN0WKj15&!@I diff --git a/07_uart_chainloader/src/arch/aarch64.rs b/07_uart_chainloader/src/arch/aarch64.rs index 131de856..b1174255 100644 --- a/07_uart_chainloader/src/arch/aarch64.rs +++ b/07_uart_chainloader/src/arch/aarch64.rs @@ -11,8 +11,7 @@ use cortex_a::{asm, regs::*}; /// The entry of the `kernel` binary. /// -/// The function must be named `_start`, because the linker is looking for this -/// exact name. +/// The function must be named `_start`, because the linker is looking for this exact name. /// /// # Safety /// @@ -30,9 +29,9 @@ pub unsafe extern "C" fn _start() -> ! { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's architecture abstraction code -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- pub use asm::nop; diff --git a/07_uart_chainloader/src/arch/aarch64/sync.rs b/07_uart_chainloader/src/arch/aarch64/sync.rs index 62dc069c..dfebc0e1 100644 --- a/07_uart_chainloader/src/arch/aarch64/sync.rs +++ b/07_uart_chainloader/src/arch/aarch64/sync.rs @@ -11,13 +11,11 @@ use core::cell::UnsafeCell; /// /// Used to introduce [interior mutability]. /// -/// In contrast to a real Mutex implementation, does not protect against -/// concurrent access to the contained data. This part is preserved for later -/// lessons. +/// In contrast to a real Mutex implementation, does not protect against concurrent access to the +/// contained data. This part is preserved for later lessons. /// -/// The lock will only be used as long as it is safe to do so, i.e. as long as -/// the kernel is executing single-threaded, aka only running on a single core -/// with interrupts disabled. +/// The lock will only be used as long as it is safe to do so, i.e. as long as the kernel is +/// executing single-threaded, aka only running on a single core with interrupts disabled. /// /// [interior mutability]: https://doc.rust-lang.org/std/cell/index.html pub struct NullLock { @@ -39,9 +37,8 @@ impl interface::sync::Mutex for &NullLock { type Data = T; fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R { - // In a real lock, there would be code encapsulating this line that - // ensures that this mutable reference will ever only be given out once - // at a time. + // In a real lock, there would be code encapsulating this line that ensures that this + // mutable reference will ever only be given out once at a time. f(unsafe { &mut *self.data.get() }) } } diff --git a/07_uart_chainloader/src/bsp/driver/bcm/bcm2837_gpio.rs b/07_uart_chainloader/src/bsp/driver/bcm/bcm2837_gpio.rs index 195973b1..361f901c 100644 --- a/07_uart_chainloader/src/bsp/driver/bcm/bcm2837_gpio.rs +++ b/07_uart_chainloader/src/bsp/driver/bcm/bcm2837_gpio.rs @@ -127,9 +127,9 @@ impl GPIOInner { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // BSP-public -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- use interface::sync::Mutex; /// The driver's main struct. @@ -151,9 +151,9 @@ impl GPIO { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // OS interface implementations -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- impl interface::driver::DeviceDriver for GPIO { fn compatible(&self) -> &str { diff --git a/07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs b/07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs index b9a76b19..431b0cf6 100644 --- a/07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs +++ b/07_uart_chainloader/src/bsp/driver/bcm/bcm2xxx_mini_uart.rs @@ -17,11 +17,10 @@ register_bitfields! { /// Auxiliary enables AUX_ENABLES [ - /// If set the mini UART is enabled. The UART will immediately - /// start receiving data, especially if the UART1_RX line is - /// low. - /// If clear the mini UART is disabled. That also disables any - /// mini UART register access + /// If set the mini UART is enabled. The UART will immediately start receiving data, + /// especially if the UART1_RX line is low. + /// + /// If clear the mini UART is disabled. That also disables any mini UART register access MINI_UART_ENABLE OFFSET(0) NUMBITS(1) [] ], @@ -47,16 +46,14 @@ register_bitfields! { /// Mini Uart Line Status AUX_MU_LSR [ - /// This bit is set if the transmit FIFO is empty and the transmitter is - /// idle. (Finished shifting out the last bit). + /// This bit is set if the transmit FIFO is empty and the transmitter is idle. (Finished + /// shifting out the last bit). TX_IDLE OFFSET(6) NUMBITS(1) [], - /// This bit is set if the transmit FIFO can accept at least - /// one byte. + /// This bit is set if the transmit FIFO can accept at least one byte. TX_EMPTY OFFSET(5) NUMBITS(1) [], - /// This bit is set if the receive FIFO holds at least 1 - /// symbol. + /// This bit is set if the receive FIFO holds at least 1 symbol. DATA_READY OFFSET(0) NUMBITS(1) [] ], @@ -155,12 +152,11 @@ impl MiniUartInner { } } -/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, -/// which in turn are used to implement the `kernel`'s `print!` and `println!` -/// macros. By implementing `write_str()`, we get `write_fmt()` automatically. +/// Implementing `core::fmt::Write` enables usage of the `format_args!` macros, which in turn are +/// used to implement the `kernel`'s `print!` and `println!` macros. By implementing `write_str()`, +/// we get `write_fmt()` automatically. /// -/// 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. /// /// See [`src/print.rs`]. /// @@ -182,9 +178,9 @@ impl fmt::Write for MiniUartInner { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // BSP-public -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// The driver's main struct. pub struct MiniUart { @@ -202,9 +198,9 @@ impl MiniUart { } } -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // OS interface implementations -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- use interface::sync::Mutex; impl interface::driver::DeviceDriver for MiniUart { @@ -238,16 +234,16 @@ impl interface::driver::DeviceDriver for MiniUart { } impl interface::console::Write for MiniUart { - /// Passthrough of `args` to the `core::fmt::Write` implementation, but - /// guarded by a Mutex to serialize access. + /// Passthrough of `args` to the `core::fmt::Write` implementation, but guarded by a Mutex to + /// serialize access. fn write_char(&self, c: char) { let mut r = &self.inner; r.lock(|inner| inner.write_char(c)); } fn write_fmt(&self, args: core::fmt::Arguments) -> fmt::Result { - // Fully qualified syntax for the call to - // `core::fmt::Write::write:fmt()` to increase readability. + // Fully qualified syntax for the call to `core::fmt::Write::write:fmt()` to increase + // readability. let mut r = &self.inner; r.lock(|inner| fmt::Write::write_fmt(inner, args)) } diff --git a/07_uart_chainloader/src/bsp/rpi3.rs b/07_uart_chainloader/src/bsp/rpi3.rs index 21e28551..bd883722 100644 --- a/07_uart_chainloader/src/bsp/rpi3.rs +++ b/07_uart_chainloader/src/bsp/rpi3.rs @@ -15,17 +15,17 @@ pub const BOOT_CORE_STACK_START: u64 = 0x80_000; /// The address on which the RPi3 firmware loads every binary by default. pub const BOARD_DEFAULT_LOAD_ADDRESS: usize = 0x80_000; -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Global BSP driver instances -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- static GPIO: driver::GPIO = unsafe { driver::GPIO::new(memory_map::mmio::GPIO_BASE) }; static MINI_UART: driver::MiniUart = unsafe { driver::MiniUart::new(memory_map::mmio::MINI_UART_BASE) }; -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- // Implementation of the kernel's BSP calls -//////////////////////////////////////////////////////////////////////////////// +//-------------------------------------------------------------------------------------------------- /// Board identification. pub fn board_name() -> &'static str { @@ -37,8 +37,7 @@ pub fn console() -> &'static impl interface::console::All { &MINI_UART } -/// Return an array of references to all `DeviceDriver` compatible `BSP` -/// drivers. +/// Return an array of references to all `DeviceDriver` compatible `BSP` drivers. /// /// # Safety /// @@ -53,9 +52,8 @@ pub fn device_drivers() -> [&'static dyn interface::driver::DeviceDriver; 2] { pub fn init() { for i in device_drivers().iter() { if let Err(()) = i.init() { - // This message will only be readable if, at the time of failure, - // the return value of `bsp::console()` is already in functioning - // state. + // This message will only be readable if, at the time of failure, the return value of + // `bsp::console()` is already in functioning state. panic!("Error loading driver: {}", i.compatible()) } } diff --git a/07_uart_chainloader/src/interface.rs b/07_uart_chainloader/src/interface.rs index 19493d6b..767b2746 100644 --- a/07_uart_chainloader/src/interface.rs +++ b/07_uart_chainloader/src/interface.rs @@ -27,8 +27,8 @@ pub mod console { fn write_char(&self, c: char); fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result; - /// Block execution until the last character has been physically put on - /// the TX wire (draining TX buffers/FIFOs, if any). + /// Block execution until the last character has been physically put on the TX wire + /// (draining TX buffers/FIFOs, if any). fn flush(&self); } @@ -61,20 +61,19 @@ pub mod console { /// Synchronization primitives. pub mod sync { - /// Any object implementing this trait guarantees exclusive access to the - /// data contained within the mutex for the duration of the lock. + /// Any object implementing this trait guarantees exclusive access to the data contained within + /// the mutex for the duration of the lock. /// /// The trait follows the [Rust embedded WG's - /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) - /// and therefore provides some goodness such as [deadlock + /// proposal](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md) and therefore + /// provides some goodness such as [deadlock /// prevention](https://github.com/korken89/wg/blob/master/rfcs/0377-mutex-trait.md#design-decisions-and-compatibility). /// /// # Example /// - /// Since the lock function takes an `&mut self` to enable - /// deadlock-prevention, the trait is best implemented **for a reference to - /// a container struct**, and has a usage pattern that might feel strange at - /// first: + /// Since the lock function takes an `&mut self` to enable deadlock-prevention, the trait is + /// best implemented **for a reference to a container struct**, and has a usage pattern that + /// might feel strange at first: /// /// ``` /// static MUT: Mutex> = Mutex::new(RefCell::new(0)); @@ -88,8 +87,7 @@ pub mod sync { /// Type of data encapsulated by the mutex. type Data; - /// Creates a critical section and grants temporary mutable access to - /// the encapsulated data. + /// Creates a critical section and grants temporary mutable access to the encapsulated data. fn lock(&mut self, f: impl FnOnce(&mut Self::Data) -> R) -> R; } } diff --git a/07_uart_chainloader/src/main.rs b/07_uart_chainloader/src/main.rs index 6045377a..6412ba61 100644 --- a/07_uart_chainloader/src/main.rs +++ b/07_uart_chainloader/src/main.rs @@ -7,10 +7,16 @@ //! The `kernel` //! -//! The `kernel` is composed by glueing together hardware-specific Board Support -//! Package (`BSP`) code and hardware-agnostic `kernel` code through the -//! [`kernel::interface`] traits. +//! The `kernel` is composed by glueing together code from //! +//! - [Hardware-specific Board Support Packages] (`BSPs`). +//! - [Architecture-specific code]. +//! - HW- and architecture-agnostic `kernel` code. +//! +//! using the [`kernel::interface`] traits. +//! +//! [Hardware-specific Board Support Packages]: bsp/index.html +//! [Architecture-specific code]: arch/index.html //! [`kernel::interface`]: interface/index.html #![feature(format_args_nl)] @@ -19,15 +25,15 @@ #![no_main] #![no_std] -// Conditionally includes the selected `architecture` code, which provides the -// `_start()` function, the first function to run. +// Conditionally includes the selected `architecture` code, which provides the `_start()` function, +// the first function to run. mod arch; // `_start()` then calls `relocate::relocate_self()`. mod relocate; -// `relocate::relocate_self()` calls `runtime_init::init()`, which on -// completion, jumps to `kernel_entry()`. +// `relocate::relocate_self()` calls `runtime_init::init()`, which on completion, jumps to +// `kernel_entry()`. mod runtime_init; // Conditionally includes the selected `BSP` code. @@ -54,8 +60,8 @@ fn kernel_entry() -> ! { println!("[ML] Requesting binary"); bsp::console().flush(); - // Clear the RX FIFOs, if any, of spurious received characters before - // starting with the loader protocol. + // Clear the RX FIFOs, if any, of spurious received characters before starting with the loader + // protocol. bsp::console().clear(); // Notify raspbootcom to send the binary. diff --git a/07_uart_chainloader/src/relocate.rs b/07_uart_chainloader/src/relocate.rs index 49801eca..30cd2257 100644 --- a/07_uart_chainloader/src/relocate.rs +++ b/07_uart_chainloader/src/relocate.rs @@ -4,8 +4,8 @@ //! Relocation code. -/// Relocates the own binary from `bsp::BOARD_DEFAULT_LOAD_ADDRESS` to the -/// `__binary_start` address from the linker script. +/// Relocates the own binary from `bsp::BOARD_DEFAULT_LOAD_ADDRESS` to the `__binary_start` address +/// from the linker script. /// /// # Safety /// @@ -29,8 +29,7 @@ pub unsafe fn relocate_self() -> ! { // Copy the whole binary. // - // This is essentially a `memcpy()` optimized for throughput by transferring - // in chunks of T. + // This is essentially a `memcpy()` optimized for throughput by transferring in chunks of T. let n = binary_size_in_byte / core::mem::size_of::(); for _ in 0..n { use core::ptr; @@ -40,8 +39,8 @@ pub unsafe fn relocate_self() -> ! { src_addr = src_addr.offset(1); } - // Call `init()` through a trait object, causing the jump to use an absolute - // address to reach the relocated binary. An elaborate explanation can be - // found in the runtime_init.rs source comments. + // Call `init()` through a trait object, causing the jump to use an absolute address to reach + // the relocated binary. An elaborate explanation can be found in the runtime_init.rs source + // comments. crate::runtime_init::get().init() } diff --git a/07_uart_chainloader/src/runtime_init.rs b/07_uart_chainloader/src/runtime_init.rs index a5b31ecc..a62b73bb 100644 --- a/07_uart_chainloader/src/runtime_init.rs +++ b/07_uart_chainloader/src/runtime_init.rs @@ -4,20 +4,17 @@ //! Rust runtime initialization code. -/// We are outsmarting the compiler here by using a trait as a layer of -/// indirection. Because we are generating PIC code, a static dispatch to -/// `init()` would generate a relative jump from the callee to `init()`. -/// However, when calling `init()`, code just finished copying the binary to the -/// actual link-time address, and hence is still running at whatever location -/// the previous loader has put it. So we do not want a relative jump, because -/// it would not jump to the relocated code. +/// We are outsmarting the compiler here by using a trait as a layer of indirection. Because we are +/// generating PIC code, a static dispatch to `init()` would generate a relative jump from the +/// callee to `init()`. However, when calling `init()`, code just finished copying the binary to the +/// actual link-time address, and hence is still running at whatever location the previous loader +/// has put it. So we do not want a relative jump, because it would not jump to the relocated code. /// -/// By indirecting through a trait object, we can make use of the property that -/// vtables store absolute addresses. So calling `init()` this way will kick -/// execution to the relocated binary. +/// By indirecting through a trait object, we can make use of the property that vtables store +/// absolute addresses. So calling `init()` this way will kick execution to the relocated binary. pub trait RunTimeInit { - /// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, - /// then calls the kernel entry. + /// Equivalent to `crt0` or `c0` code in C/C++ world. Clears the `bss` section, then calls the + /// kernel entry. /// /// Called from `BSP` code. /// diff --git a/utils/clean_all.rb b/utils/clean_all.rb index 1a26f96a..d8611d02 100755 --- a/utils/clean_all.rb +++ b/utils/clean_all.rb @@ -9,17 +9,17 @@ require 'fileutils' require_relative 'helpers/tutorial_folders.rb' def clean_all - crates = tutorial_folders + crates = tutorial_folders - crates.each do |x| - x = File.dirname(x) - Dir.chdir(x) do - puts "Cleaning #{x}" - system('rm -rf target') || exit(1) + crates.each do |x| + x = File.dirname(x) + Dir.chdir(x) do + puts "Cleaning #{x}" + system('rm -rf target') || exit(1) + end end - end - FileUtils.rm_rf('xbuild_sysroot') + FileUtils.rm_rf('xbuild_sysroot') end clean_all if $PROGRAM_NAME == __FILE__ diff --git a/utils/clippy_all.rb b/utils/clippy_all.rb index b3baa22b..96a7376e 100755 --- a/utils/clippy_all.rb +++ b/utils/clippy_all.rb @@ -8,16 +8,16 @@ require_relative 'helpers/tutorial_folders.rb' def clippy_all - crates = tutorial_folders + crates = tutorial_folders - crates.each do |x| - x = File.dirname(x) + crates.each do |x| + x = File.dirname(x) - Dir.chdir(x) do - puts "Clippy: #{x}" - system('make clippy') + Dir.chdir(x) do + puts "Clippy: #{x}" + system('make clippy') + end end - end end clippy_all if $PROGRAM_NAME == __FILE__ diff --git a/utils/diff_all.rb b/utils/diff_all.rb index ef672ce7..4df965f4 100755 --- a/utils/diff_all.rb +++ b/utils/diff_all.rb @@ -9,14 +9,14 @@ require 'fileutils' require_relative 'helpers/tutorial_folders.rb' def diff_all - crates = tutorial_folders + crates = tutorial_folders - for i in 0..(crates.length - 2) - old = File.dirname(crates[i]) - new = File.dirname(crates[i + 1]) - puts "Diffing #{old} -> #{new}" - system("bash utils/helpers/diff_tut_folders.bash #{old} #{new}") - end + (0..(crates.length - 2)).each do |i| + old = File.dirname(crates[i]) + new = File.dirname(crates[i + 1]) + puts "Diffing #{old} -> #{new}" + system("bash utils/helpers/diff_tut_folders.bash #{old} #{new}") + end end diff_all if $PROGRAM_NAME == __FILE__ diff --git a/utils/fmt_all.rb b/utils/fmt_all.rb index 10860d51..9f63af4a 100755 --- a/utils/fmt_all.rb +++ b/utils/fmt_all.rb @@ -8,16 +8,16 @@ require_relative 'helpers/tutorial_folders.rb' def fmt_all - crates = tutorial_folders + crates = tutorial_folders - crates.each do |x| - x = File.dirname(x) + crates.each do |x| + x = File.dirname(x) - Dir.chdir(x) do - puts "Formatting #{x}" - system('cargo fmt') + Dir.chdir(x) do + puts "Formatting #{x}" + system('cargo fmt') + end end - end end fmt_all if $PROGRAM_NAME == __FILE__ diff --git a/utils/helpers/copyrighted.rb b/utils/helpers/copyrighted.rb index 60221780..8c500098 100644 --- a/utils/helpers/copyrighted.rb +++ b/utils/helpers/copyrighted.rb @@ -5,41 +5,41 @@ # Copyright (c) 2018-2019 Andre Richter def checkin_years(file) - checkin_years = `git --no-pager log \ - --reverse --pretty=format:'%ad' --date=format:'%Y' #{file}` + checkin_years = `git --no-pager log \ + --reverse --pretty=format:'%ad' --date=format:'%Y' #{file}` - checkin_years.split(/\n/).map!(&:to_i) + checkin_years.split(/\n/).map!(&:to_i) end def copyrighted?(file, is_being_checked_in) - checkin_years = checkin_years(file) + checkin_years = checkin_years(file) - checkin_years << Time.now.year if is_being_checked_in + checkin_years << Time.now.year if is_being_checked_in - checkin_min = checkin_years.min - checkin_max = checkin_years.max + checkin_min = checkin_years.min + checkin_max = checkin_years.max - copyright_lines = File.readlines(file).grep(/.*Copyright.*/) + copyright_lines = File.readlines(file).grep(/.*Copyright.*/) - min_seen = false - max_seen = false - copyright_lines.each do |x| - x.scan(/\d\d\d\d/).each do |y| - y = y.to_i + min_seen = false + max_seen = false + copyright_lines.each do |x| + x.scan(/\d\d\d\d/).each do |y| + y = y.to_i - min_seen = true if y == checkin_min - max_seen = true if y == checkin_max + min_seen = true if y == checkin_min + max_seen = true if y == checkin_max + end end - end - unless min_seen && max_seen - puts file + ': ' - puts "\tHeader: " + copyright_lines.inspect - puts "\tMin year: " + checkin_min.to_s - puts "\tMax year: " + checkin_max.to_s + unless min_seen && max_seen + puts file + ': ' + puts "\tHeader: " + copyright_lines.inspect + puts "\tMin year: " + checkin_min.to_s + puts "\tMax year: " + checkin_max.to_s - return false - end + return false + end - true + true end diff --git a/utils/helpers/tutorial_folders.rb b/utils/helpers/tutorial_folders.rb index 5ccfd28a..d96f5b74 100755 --- a/utils/helpers/tutorial_folders.rb +++ b/utils/helpers/tutorial_folders.rb @@ -8,13 +8,13 @@ require 'fileutils' def tutorial_folders - crates = Dir['**/Cargo.toml'] + crates = Dir['**/Cargo.toml'] - crates.delete_if do |x| - !/[0-9][0-9]/.match?(x[0..1]) - end + crates.delete_if do |x| + !/[0-9][0-9]/.match?(x[0..1]) + end - crates.sort! + crates.sort! end puts tutorial_folders if $PROGRAM_NAME == __FILE__ diff --git a/utils/make_all.rb b/utils/make_all.rb index 79b135f3..dd5290e4 100755 --- a/utils/make_all.rb +++ b/utils/make_all.rb @@ -8,18 +8,18 @@ require_relative 'helpers/tutorial_folders.rb' def make_all - crates = tutorial_folders + crates = tutorial_folders - crates.each do |x| - x = File.dirname(x) - puts "\n\n" + x.to_s + "\n\n" - Dir.chdir(x) do - unless system('make') - puts "\n\nBuild failed!" - exit(1) # Exit with error code - end + crates.each do |x| + x = File.dirname(x) + puts "\n\n" + x.to_s + "\n\n" + Dir.chdir(x) do + unless system('make') + puts "\n\nBuild failed!" + exit(1) # Exit with error code + end + end end - end end make_all if $PROGRAM_NAME == __FILE__ diff --git a/utils/sanity_checks.rb b/utils/sanity_checks.rb index 87866018..a36721f9 100755 --- a/utils/sanity_checks.rb +++ b/utils/sanity_checks.rb @@ -9,36 +9,36 @@ require_relative 'helpers/copyrighted' require_relative 'helpers/tutorial_folders.rb' def patched? - crates = tutorial_folders + crates = tutorial_folders - crates.each do |f| - unless File.readlines(f).grep(/patch.crates-io/).empty? - puts "#{fb} contains patch.crates-io!" - exit(1) + crates.each do |f| + unless File.readlines(f).grep(/patch.crates-io/).empty? + puts "#{fb} contains patch.crates-io!" + exit(1) + end end - end end def check_old_copyrights - error = false + error = false - sources = Dir.glob('**/*.{S,rs,rb}') + Dir.glob('**/Makefile') + sources = Dir.glob('**/*.{S,rs,rb}') + Dir.glob('**/Makefile') - sources.delete_if do |x| - !system("git ls-files --error-unmatch #{x}", %i[out err] => File::NULL) - end + sources.delete_if do |x| + !system("git ls-files --error-unmatch #{x}", %i[out err] => File::NULL) + end - sources.sort.reverse_each do |f| - puts "Checking for copyright: #{f}" - error = true unless copyrighted?(f, false) - end + sources.sort.reverse_each do |f| + puts "Checking for copyright: #{f}" + error = true unless copyrighted?(f, false) + end - exit(1) if error + exit(1) if error end def sanity_checks - patched? - check_old_copyrights + patched? + check_old_copyrights end sanity_checks if $PROGRAM_NAME == __FILE__