Big restructuring for more modularity

- Make architecture code separate from BSP code
- Make BSPs pull in drivers from a generic folder
    - Enables reuse of drivers between different BSPs.
pull/35/head
Andre Richter 5 years ago
parent be787f967c
commit 038c558ac8
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -2,10 +2,11 @@
## tl;dr
Project skeleton is set up; Code just halts all CPU cores.
Project skeleton is set up; Code just halts all CPU cores executing kernel code.
- Toolchain: `cargo xbuild` tools (`xrustc`, `xclippy`) and the
`aarch64-unknown-none-softfloat` target are used for building `AArch64` bare-metal code.
`aarch64-unknown-none-softfloat` target are used for building `AArch64`
bare-metal code.
- `Makefile` targets:
- `doc`: Generate documentation.
- `qemu`: Run the `kernel` in QEMU
@ -14,9 +15,10 @@ Project skeleton is set up; Code just halts all CPU cores.
- `readelf`: Inspect the `ELF` output.
- `objdump`: Inspect the assembly.
- `nm`: Inspect the symbols.
- Code is organized into `kernel` and `BSP` (Board Support Package) parts.
- Conditional compilation includes a `BSP` according to user-supplied
arguments.
- Code is organized into `kernel`, `arch` and `BSP` (Board Support Package)
parts.
- Conditional compilation includes respective `arch` and `BSP` according to
user-supplied arguments.
- Custom `link.ld` linker script.
- Load address at `0x80_000`
- Only `.text` section.

Binary file not shown.

@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Conditional exporting of processor architecture code.
#[cfg(feature = "bsp_rpi3")]
mod aarch64;
#[cfg(feature = "bsp_rpi3")]
pub use aarch64::*;

@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! AArch64.
global_asm!(include_str!("aarch64/start.S"));
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
unsafe {
loop {
asm!("wfe" :::: "volatile")
}
}
}

@ -4,6 +4,4 @@
//! Board Support Package for the Raspberry Pi 3.
mod panic_wait;
global_asm!(include_str!("rpi3/start.S"));
// Coming soon.

@ -12,8 +12,13 @@
#![no_main]
#![no_std]
// This module conditionally includes the correct `BSP` which provides the
// Conditionally includes the selected `architecture` code, which provides the
// `_start()` function, the first function to run.
mod arch;
// Conditionally includes the selected `BSP` code.
mod bsp;
mod panic_wait;
// Kernel code coming next tutorial.

@ -8,9 +8,5 @@ use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
unsafe {
loop {
asm!("wfe" :::: "volatile")
}
}
crate::arch::wait_forever()
}

@ -28,6 +28,28 @@ diff -uNr 01_wait_forever/Cargo.toml 02_runtime_init/Cargo.toml
-
+r0 = "0.2.*"
diff -uNr 01_wait_forever/src/arch/aarch64/start.S 02_runtime_init/src/arch/aarch64/start.S
--- 01_wait_forever/src/arch/aarch64/start.S
+++ 02_runtime_init/src/arch/aarch64/start.S
@@ -7,5 +7,15 @@
.global _start
_start:
-1: wfe // Wait for event
- b 1b // In case an event happend, jump back to 1
+ mrs x1, mpidr_el1 // Read Multiprocessor Affinity Register
+ and x1, x1, #3 // Clear all bits except [1:0], which hold core id
+ cbz x1, 2f // Jump to label 2 if we are core 0
+1: wfe // Wait for event
+ b 1b // In case an event happend, jump back to 1
+2: // If we are here, we are core0
+ ldr x1, =_start // Load address of function "_start()"
+ mov sp, x1 // Set start of stack to before our code, aka first
+ // address before "_start()"
+ bl init // Jump to the "init()" kernel function
+ b 1b // We should never reach here. But just in case,
+ // park this core aswell
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
@ -56,40 +78,23 @@ diff -uNr 01_wait_forever/src/bsp/rpi3/link.ld 02_runtime_init/src/bsp/rpi3/link
/DISCARD/ : { *(.comment*) }
}
diff -uNr 01_wait_forever/src/bsp/rpi3/start.S 02_runtime_init/src/bsp/rpi3/start.S
--- 01_wait_forever/src/bsp/rpi3/start.S
+++ 02_runtime_init/src/bsp/rpi3/start.S
@@ -7,5 +7,15 @@
.global _start
_start:
-1: wfe // Wait for event
- b 1b // In case an event happend, jump back to 1
+ mrs x1, mpidr_el1 // Read Multiprocessor Affinity Register
+ and x1, x1, #3 // Clear all bits except [1:0], which hold core id
+ cbz x1, 2f // Jump to label 2 if we are core 0
+1: wfe // Wait for event
+ b 1b // In case an event happend, jump back to 1
+2: // If we are here, we are core0
+ ldr x1, =_start // Load address of function "_start()"
+ mov sp, x1 // Set start of stack to before our code, aka first
+ // address before "_start()"
+ bl init // Jump to the "init()" kernel function
+ b 1b // We should never reach here. But just in case,
+ // park this core aswell
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,4 +16,11 @@
@@ -16,9 +16,16 @@
// `_start()` function, the first function to run.
mod bsp;
mod arch;
-// Kernel code coming next tutorial.
+// Afterwards, `BSP`'s early init code calls `runtime_init::init()` of this
+// module, 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;
mod panic_wait;
-// Kernel code coming next tutorial.
+/// Entrypoint of the `kernel`.
+fn kernel_entry() -> ! {
+ panic!()

Binary file not shown.

Binary file not shown.

@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Conditional exporting of processor architecture code.
#[cfg(feature = "bsp_rpi3")]
mod aarch64;
#[cfg(feature = "bsp_rpi3")]
pub use aarch64::*;

@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! AArch64.
global_asm!(include_str!("aarch64/start.S"));
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
unsafe {
loop {
asm!("wfe" :::: "volatile")
}
}
}

@ -4,6 +4,4 @@
//! Board Support Package for the Raspberry Pi 3.
mod panic_wait;
global_asm!(include_str!("rpi3/start.S"));
// Coming soon.

@ -12,14 +12,19 @@
#![no_main]
#![no_std]
// This module conditionally includes the correct `BSP` which provides the
// Conditionally includes the selected `architecture` code, which provides the
// `_start()` function, the first function to run.
mod bsp;
mod arch;
// Afterwards, `BSP`'s early init code calls `runtime_init::init()` of this
// module, 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;
mod panic_wait;
/// Entrypoint of the `kernel`.
fn kernel_entry() -> ! {
panic!()

@ -8,9 +8,5 @@ use core::panic::PanicInfo;
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
unsafe {
loop {
asm!("wfe" :::: "volatile")
}
}
crate::arch::wait_forever()
}

@ -28,40 +28,16 @@ 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/bsp/rpi3/panic_wait.rs 03_hacky_hello_world/src/bsp/rpi3/panic_wait.rs
--- 02_runtime_init/src/bsp/rpi3/panic_wait.rs
+++ 03_hacky_hello_world/src/bsp/rpi3/panic_wait.rs
@@ -4,10 +4,17 @@
//! A panic handler that infinitely waits.
+use crate::println;
use core::panic::PanicInfo;
#[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
+fn panic(info: &PanicInfo) -> ! {
+ if let Some(args) = info.message() {
+ println!("Kernel panic: {}", args);
+ } else {
+ println!("Kernel panic!");
+ }
+
unsafe {
loop {
asm!("wfe" :::: "volatile")
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
@@ -6,4 +6,38 @@
@@ -4,4 +4,36 @@
mod panic_wait;
//! Board Support Package for the Raspberry Pi 3.
-// Coming soon.
+use crate::interface;
+use core::fmt;
+
global_asm!(include_str!("rpi3/start.S"));
+
+/// A mystical, magical device for generating QEMU output out of the void.
+struct QEMUOutput;
@ -156,13 +132,14 @@ diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs
#![no_main]
#![no_std]
@@ -20,7 +28,12 @@
// module, which on completion, jumps to `kernel_entry()`.
mod runtime_init;
@@ -23,9 +31,13 @@
// Conditionally includes the selected `BSP` code.
mod bsp;
+mod interface;
mod panic_wait;
+mod print;
+
/// Entrypoint of the `kernel`.
fn kernel_entry() -> ! {
- panic!()
@ -171,18 +148,39 @@ diff -uNr 02_runtime_init/src/main.rs 03_hacky_hello_world/src/main.rs
+ panic!("Stopping here.")
}
diff -uNr 02_runtime_init/src/panic_wait.rs 03_hacky_hello_world/src/panic_wait.rs
--- 02_runtime_init/src/panic_wait.rs
+++ 03_hacky_hello_world/src/panic_wait.rs
@@ -4,9 +4,16 @@
//! A panic handler that infinitely waits.
+use crate::println;
use core::panic::PanicInfo;
#[panic_handler]
-fn panic(_info: &PanicInfo) -> ! {
+fn panic(info: &PanicInfo) -> ! {
+ if let Some(args) = info.message() {
+ println!("Kernel panic: {}", args);
+ } else {
+ println!("Kernel panic!");
+ }
+
crate::arch::wait_forever()
}
diff -uNr 02_runtime_init/src/print.rs 03_hacky_hello_world/src/print.rs
--- 02_runtime_init/src/print.rs
+++ 03_hacky_hello_world/src/print.rs
@@ -0,0 +1,34 @@
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
+
+//! Printing facilities.
+
+use crate::bsp;
+use crate::interface;
+use crate::{bsp, interface};
+use core::fmt;
+
+/// Prints without a newline.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Conditional exporting of processor architecture code.
#[cfg(feature = "bsp_rpi3")]
mod aarch64;
#[cfg(feature = "bsp_rpi3")]
pub use aarch64::*;

@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! AArch64.
global_asm!(include_str!("aarch64/start.S"));
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
unsafe {
loop {
asm!("wfe" :::: "volatile")
}
}
}

@ -4,13 +4,9 @@
//! Board Support Package for the Raspberry Pi 3.
mod panic_wait;
use crate::interface;
use core::fmt;
global_asm!(include_str!("rpi3/start.S"));
/// A mystical, magical device for generating QEMU output out of the void.
struct QEMUOutput;

@ -20,15 +20,19 @@
#![no_main]
#![no_std]
// This module conditionally includes the correct `BSP` which provides the
// Conditionally includes the selected `architecture` code, which provides the
// `_start()` function, the first function to run.
mod bsp;
mod arch;
// Afterwards, `BSP`'s early init code calls `runtime_init::init()` of this
// module, 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;
mod interface;
mod panic_wait;
mod print;
/// Entrypoint of the `kernel`.

@ -15,5 +15,5 @@ fn panic(info: &PanicInfo) -> ! {
println!("Kernel panic!");
}
super::wait_forever()
crate::arch::wait_forever()
}

@ -5,8 +5,6 @@
All hand-written assembly is replaced by Rust code from the [cortex-a] crate,
which provides zero-overhead abstractions and wraps the `unsafe` parts.
- `bsp::wait_forever()` is introduced.
[cortex-a]: https://github.com/rust-embedded/cortex-a
## Diff to previous
@ -28,24 +26,9 @@ diff -uNr 03_hacky_hello_world/Cargo.toml 04_zero_overhead_abstraction/Cargo.tom
+# Optional dependencies
+cortex-a = { version = "2.*", optional = true }
diff -uNr 03_hacky_hello_world/src/bsp/rpi3/panic_wait.rs 04_zero_overhead_abstraction/src/bsp/rpi3/panic_wait.rs
--- 03_hacky_hello_world/src/bsp/rpi3/panic_wait.rs
+++ 04_zero_overhead_abstraction/src/bsp/rpi3/panic_wait.rs
@@ -15,9 +15,5 @@
println!("Kernel panic!");
}
- unsafe {
- loop {
- asm!("wfe" :::: "volatile")
- }
- }
+ super::wait_forever()
}
diff -uNr 03_hacky_hello_world/src/bsp/rpi3/start.S 04_zero_overhead_abstraction/src/bsp/rpi3/start.S
--- 03_hacky_hello_world/src/bsp/rpi3/start.S
+++ 04_zero_overhead_abstraction/src/bsp/rpi3/start.S
diff -uNr 03_hacky_hello_world/src/arch/aarch64/start.S 04_zero_overhead_abstraction/src/arch/aarch64/start.S
--- 03_hacky_hello_world/src/arch/aarch64/start.S
+++ 04_zero_overhead_abstraction/src/arch/aarch64/start.S
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: MIT
-//
@ -69,16 +52,17 @@ diff -uNr 03_hacky_hello_world/src/bsp/rpi3/start.S 04_zero_overhead_abstraction
- b 1b // We should never reach here. But just in case,
- // park this core aswell
diff -uNr 03_hacky_hello_world/src/bsp/rpi3.rs 04_zero_overhead_abstraction/src/bsp/rpi3.rs
--- 03_hacky_hello_world/src/bsp/rpi3.rs
+++ 04_zero_overhead_abstraction/src/bsp/rpi3.rs
@@ -8,8 +8,34 @@
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 @@
use crate::interface;
use core::fmt;
+use cortex_a::{asm, regs::*};
//! AArch64.
-global_asm!(include_str!("rpi3/start.S"));
-global_asm!(include_str!("aarch64/start.S"));
+use crate::bsp;
+use cortex_a::{asm, regs::*};
+
+/// The entry of the `kernel` binary.
+///
+/// The function must be named `_start`, because the linker is looking for this
@ -89,39 +73,45 @@ diff -uNr 03_hacky_hello_world/src/bsp/rpi3.rs 04_zero_overhead_abstraction/src/
+/// - Linker script must ensure to place this function at `0x80_000`.
+#[no_mangle]
+pub unsafe extern "C" fn _start() -> ! {
+ use crate::runtime_init;
+
+ const CORE_0: u64 = 0;
+ const CORE_MASK: u64 = 0x3;
+ const STACK_START: u64 = 0x80_000;
+
+ if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
+ SP.set(STACK_START);
+ runtime_init::init()
+ if bsp::BOOT_CORE_ID == MPIDR_EL1.get() & CORE_MASK {
+ SP.set(bsp::BOOT_CORE_STACK_START);
+ crate::runtime_init::init()
+ } else {
+ // if not core0, infinitely wait for events
+ loop {
+ asm::wfe();
+ }
+ wait_forever()
+ }
+}
/// A mystical, magical device for generating QEMU output out of the void.
struct QEMUOutput;
@@ -37,6 +63,13 @@
// Implementation of the kernel's BSP calls
////////////////////////////////////////////////////////////////////////////////
+/// Park execution on the calling CPU core.
+pub fn wait_forever() -> ! {
// Implementation of the kernel's architecture abstraction code
@@ -13,9 +35,7 @@
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
- unsafe {
- loop {
- asm!("wfe" :::: "volatile")
- }
+ loop {
+ asm::wfe()
+ }
+}
}
}
diff -uNr 03_hacky_hello_world/src/bsp/rpi3.rs 04_zero_overhead_abstraction/src/bsp/rpi3.rs
--- 03_hacky_hello_world/src/bsp/rpi3.rs
+++ 04_zero_overhead_abstraction/src/bsp/rpi3.rs
@@ -7,6 +7,9 @@
use crate::interface;
use core::fmt;
+pub const BOOT_CORE_ID: u64 = 0;
+pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
+
/// Returns a ready-to-use `console::Write` implementation.
pub fn console() -> impl interface::console::Write {
QEMUOutput {}
/// A mystical, magical device for generating QEMU output out of the void.
struct QEMUOutput;
diff -uNr 03_hacky_hello_world/src/main.rs 04_zero_overhead_abstraction/src/main.rs
--- 03_hacky_hello_world/src/main.rs
@ -136,7 +126,7 @@ diff -uNr 03_hacky_hello_world/src/main.rs 04_zero_overhead_abstraction/src/main
#![feature(panic_info_message)]
#![no_main]
#![no_std]
@@ -33,7 +31,8 @@
@@ -37,7 +35,8 @@
/// Entrypoint of the `kernel`.
fn kernel_entry() -> ! {
@ -145,7 +135,7 @@ diff -uNr 03_hacky_hello_world/src/main.rs 04_zero_overhead_abstraction/src/main
- panic!("Stopping here.")
+ println!("[1] Stopping here.");
+ bsp::wait_forever()
+ arch::wait_forever()
}
diff -uNr 03_hacky_hello_world/src/runtime_init.rs 04_zero_overhead_abstraction/src/runtime_init.rs

@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Conditional exporting of processor architecture code.
#[cfg(feature = "bsp_rpi3")]
mod aarch64;
#[cfg(feature = "bsp_rpi3")]
pub use aarch64::*;

@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! AArch64.
use crate::bsp;
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.
///
/// # Safety
///
/// - Linker script must ensure to place this function at `0x80_000`.
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
const CORE_MASK: u64 = 0x3;
if bsp::BOOT_CORE_ID == MPIDR_EL1.get() & CORE_MASK {
SP.set(bsp::BOOT_CORE_STACK_START);
crate::runtime_init::init()
} else {
// if not core0, infinitely wait for events
wait_forever()
}
}
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
loop {
asm::wfe()
}
}

@ -4,38 +4,11 @@
//! Board Support Package for the Raspberry Pi 3.
mod panic_wait;
use crate::interface;
use core::fmt;
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.
///
/// # Safety
///
/// - Linker script must ensure to place this function at `0x80_000`.
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
use crate::runtime_init;
const CORE_0: u64 = 0;
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_000;
if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
SP.set(STACK_START);
runtime_init::init()
} else {
// if not core0, infinitely wait for events
loop {
asm::wfe();
}
}
}
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
/// A mystical, magical device for generating QEMU output out of the void.
struct QEMUOutput;
@ -63,13 +36,6 @@ impl interface::console::Write for QEMUOutput {
// Implementation of the kernel's BSP calls
////////////////////////////////////////////////////////////////////////////////
/// Park execution on the calling CPU core.
pub fn wait_forever() -> ! {
loop {
asm::wfe()
}
}
/// Returns a ready-to-use `console::Write` implementation.
pub fn console() -> impl interface::console::Write {
QEMUOutput {}

@ -18,15 +18,19 @@
#![no_main]
#![no_std]
// This module conditionally includes the correct `BSP` which provides the
// Conditionally includes the selected `architecture` code, which provides the
// `_start()` function, the first function to run.
mod bsp;
mod arch;
// Afterwards, `BSP`'s early init code calls `runtime_init::init()` of this
// module, 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;
mod interface;
mod panic_wait;
mod print;
/// Entrypoint of the `kernel`.
@ -34,5 +38,5 @@ fn kernel_entry() -> ! {
println!("[0] Hello from pure Rust!");
println!("[1] Stopping here.");
bsp::wait_forever()
arch::wait_forever()
}

@ -15,5 +15,5 @@ fn panic(info: &PanicInfo) -> ! {
println!("Kernel panic!");
}
super::wait_forever()
crate::arch::wait_forever()
}

@ -21,8 +21,8 @@ The borrow checker can't help here).
The solution to this problem is to wrap the global into a synchronization
primitive. In our case, a variant of a *MUTual EXclusion* primivite. `Mutex` is
introduced as a trait in `interfaces.rs`, and implemented by the name of
`NullLock` in `sync.rs` in the `bsp` folder. For teaching purposes, to make the
code lean, it leaves out the actual platform-specific logic for protection
`NullLock` in `sync.rs` in the `arch` folder. For teaching purposes, to make the
code lean, it leaves out the actual architecture-specific logic for protection
against concurrent access, since we don't need it as long as the kernel only
exeuts on a single core with interrupts disabled.
@ -42,15 +42,15 @@ can check out implemntations in the [spin crate] or the [parking lot crate].
## Diff to previous
```diff
diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3/sync.rs 05_safe_globals/src/bsp/rpi3/sync.rs
--- 04_zero_overhead_abstraction/src/bsp/rpi3/sync.rs
+++ 05_safe_globals/src/bsp/rpi3/sync.rs
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 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
+
+//! Board-specific synchronization primitives.
+//! Synchronization primitives.
+
+use crate::interface;
+use core::cell::UnsafeCell;
@ -94,24 +94,32 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3/sync.rs 05_safe_globals/src/
+ }
+}
diff -uNr 04_zero_overhead_abstraction/src/arch/aarch64.rs 05_safe_globals/src/arch/aarch64.rs
--- 04_zero_overhead_abstraction/src/arch/aarch64.rs
+++ 05_safe_globals/src/arch/aarch64.rs
@@ -4,6 +4,8 @@
//! AArch64.
+pub mod sync;
+
use crate::bsp;
use cortex_a::{asm, regs::*};
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
@@ -5,10 +5,12 @@
//! Board Support Package for the Raspberry Pi 3.
@@ -4,39 +4,111 @@
mod panic_wait;
+mod sync;
//! Board Support Package for the Raspberry Pi 3.
use crate::interface;
-use crate::interface;
+use crate::{arch::sync::NullLock, interface};
use core::fmt;
use cortex_a::{asm, regs::*};
+use sync::NullLock;
/// The entry of the `kernel` binary.
///
@@ -38,28 +40,100 @@
}
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
/// A mystical, magical device for generating QEMU output out of the void.
-struct QEMUOutput;
@ -218,10 +226,6 @@ diff -uNr 04_zero_overhead_abstraction/src/bsp/rpi3.rs 05_safe_globals/src/bsp/r
// Implementation of the kernel's BSP calls
////////////////////////////////////////////////////////////////////////////////
@@ -70,7 +144,7 @@
}
}
-/// Returns a ready-to-use `console::Write` implementation.
-pub fn console() -> impl interface::console::Write {
- QEMUOutput {}
@ -230,6 +234,19 @@ 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
@ -320,7 +337,7 @@ diff -uNr 04_zero_overhead_abstraction/src/main.rs 05_safe_globals/src/main.rs
#![no_main]
#![no_std]
@@ -31,8 +32,12 @@
@@ -35,8 +36,12 @@
/// Entrypoint of the `kernel`.
fn kernel_entry() -> ! {
@ -332,6 +349,6 @@ diff -uNr 04_zero_overhead_abstraction/src/main.rs 05_safe_globals/src/main.rs
+ println!("[1] Chars written: {}", bsp::console().chars_written());
+
+ println!("[2] Stopping here.");
bsp::wait_forever()
arch::wait_forever()
}
```

Binary file not shown.

@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Conditional exporting of processor architecture code.
#[cfg(feature = "bsp_rpi3")]
mod aarch64;
#[cfg(feature = "bsp_rpi3")]
pub use aarch64::*;

@ -0,0 +1,43 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! AArch64.
pub mod sync;
use crate::bsp;
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.
///
/// # Safety
///
/// - Linker script must ensure to place this function at `0x80_000`.
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
const CORE_MASK: u64 = 0x3;
if bsp::BOOT_CORE_ID == MPIDR_EL1.get() & CORE_MASK {
SP.set(bsp::BOOT_CORE_STACK_START);
crate::runtime_init::init()
} else {
// if not core0, infinitely wait for events
wait_forever()
}
}
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
loop {
asm::wfe()
}
}

@ -2,7 +2,7 @@
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Board-specific synchronization primitives.
//! Synchronization primitives.
use crate::interface;
use core::cell::UnsafeCell;

@ -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::*;

@ -4,40 +4,11 @@
//! Board Support Package for the Raspberry Pi 3.
mod panic_wait;
mod sync;
use crate::interface;
use crate::{arch::sync::NullLock, interface};
use core::fmt;
use cortex_a::{asm, regs::*};
use sync::NullLock;
/// The entry of the `kernel` binary.
///
/// The function must be named `_start`, because the linker is looking for this
/// exact name.
///
/// # Safety
///
/// - Linker script must ensure to place this function at `0x80_000`.
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
use crate::runtime_init;
const CORE_0: u64 = 0;
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_000;
if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
SP.set(STACK_START);
runtime_init::init()
} else {
// if not core0, infinitely wait for events
loop {
asm::wfe();
}
}
}
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
/// A mystical, magical device for generating QEMU output out of the void.
///
@ -137,13 +108,6 @@ static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new();
// Implementation of the kernel's BSP calls
////////////////////////////////////////////////////////////////////////////////
/// Park execution on the calling CPU core.
pub fn wait_forever() -> ! {
loop {
asm::wfe()
}
}
/// Return a reference to a `console::All` implementation.
pub fn console() -> &'static impl interface::console::All {
&QEMU_OUTPUT

@ -19,15 +19,19 @@
#![no_main]
#![no_std]
// This module conditionally includes the correct `BSP` which provides the
// Conditionally includes the selected `architecture` code, which provides the
// `_start()` function, the first function to run.
mod bsp;
mod arch;
// Afterwards, `BSP`'s early init code calls `runtime_init::init()` of this
// module, 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;
mod interface;
mod panic_wait;
mod print;
/// Entrypoint of the `kernel`.
@ -39,5 +43,5 @@ fn kernel_entry() -> ! {
println!("[1] Chars written: {}", bsp::console().chars_written());
println!("[2] Stopping here.");
bsp::wait_forever()
arch::wait_forever()
}

@ -15,5 +15,5 @@ fn panic(info: &PanicInfo) -> ! {
println!("Kernel panic!");
}
super::wait_forever()
crate::arch::wait_forever()
}

@ -6,15 +6,17 @@ Now that we enabled safe globals in the previous tutorial, the infrastructure is
laid for adding the first real device drivers. We throw out the magic QEMU
console and use a real UART now. Like real though embedded people do!
- A `DeviceDriver` trait is added for abstracting BSP driver implementations
- A `DeviceDriver` trait is added for abstracting `BSP` driver implementations
from kernel code.
- Introducing the `GPIO` driver, which pinmuxes the RPi's Mini UART.
- Most importantly, the `MiniUart` driver: It implements the `Console` traits
and is from now on used as the system console output.
- **Be sure to check it out by booting this kernel from the SD card and
watching the output!**
- `memory_map.rs` contains the RPi3 device's MMIO addresses.
- Drivers are stored in `bsp/driver`, and can be reused between `BSP`s.
- Introducing the `GPIO` driver, which pinmuxes the RPi's Mini UART.
- Most importantly, the `MiniUart` driver: It implements the `Console`
traits and is from now on used as the system console output.
- **Be sure to check it out by booting this kernel from the SD card and
watching the output!**
- `BSP`s now contain a`memory_map.rs`. In the specific case, they contain the
RPi's MMIO addresses which are used to instantiate compatible device drivers
from `bsp/driver`.
## Diff to previous
```diff
@ -36,20 +38,31 @@ diff -uNr 05_safe_globals/Cargo.toml 06_drivers_gpio_uart/Cargo.toml
cortex-a = { version = "2.*", optional = true }
+register = { version = "0.3.*", optional = true }
diff -uNr 05_safe_globals/src/bsp/rpi3/driver/gpio.rs 06_drivers_gpio_uart/src/bsp/rpi3/driver/gpio.rs
--- 05_safe_globals/src/bsp/rpi3/driver/gpio.rs
+++ 06_drivers_gpio_uart/src/bsp/rpi3/driver/gpio.rs
@@ -0,0 +1,164 @@
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 @@
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
+pub use asm::nop;
+
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
diff -uNr 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs 06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs
--- 05_safe_globals/src/bsp/driver/bcm2837_gpio.rs
+++ 06_drivers_gpio_uart/src/bsp/driver/bcm2837_gpio.rs
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
+
+//! GPIO driver.
+
+use super::super::NullLock;
+use crate::interface;
+use crate::{arch, arch::sync::NullLock, interface};
+use core::ops;
+use cortex_a::asm;
+use register::{mmio::ReadWrite, register_bitfields};
+
+// GPIO registers.
@ -160,13 +173,13 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/driver/gpio.rs 06_drivers_gpio_uart/src/b
+ // Enable pins 14 and 15.
+ self.GPPUD.set(0);
+ for _ in 0..150 {
+ asm::nop();
+ arch::nop();
+ }
+
+ self.GPPUDCLK0
+ .write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
+ for _ in 0..150 {
+ asm::nop();
+ arch::nop();
+ }
+
+ self.GPPUDCLK0.set(0);
@ -205,20 +218,18 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/driver/gpio.rs 06_drivers_gpio_uart/src/b
+ }
+}
diff -uNr 05_safe_globals/src/bsp/rpi3/driver/mini_uart.rs 06_drivers_gpio_uart/src/bsp/rpi3/driver/mini_uart.rs
--- 05_safe_globals/src/bsp/rpi3/driver/mini_uart.rs
+++ 06_drivers_gpio_uart/src/bsp/rpi3/driver/mini_uart.rs
@@ -0,0 +1,263 @@
diff -uNr 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs 06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs
--- 05_safe_globals/src/bsp/driver/bcm2xxx_mini_uart.rs
+++ 06_drivers_gpio_uart/src/bsp/driver/bcm2xxx_mini_uart.rs
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
+
+//! Mini UART driver.
+
+use super::super::NullLock;
+use crate::interface;
+use crate::{arch, arch::sync::NullLock, interface};
+use core::{fmt, ops};
+use cortex_a::asm;
+use register::{mmio::*, register_bitfields};
+
+// Mini UART registers.
@ -381,7 +392,7 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/driver/mini_uart.rs 06_drivers_gpio_uart/
+ break;
+ }
+
+ asm::nop();
+ arch::nop();
+ }
+
+ // Write the character to the buffer.
@ -405,8 +416,7 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/driver/mini_uart.rs 06_drivers_gpio_uart/
+ // Convert newline to carrige return + newline.
+ if c == '
' {
+ self.write_char('
')
+ self.write_char(' ')
+ }
+
+ self.write_char(c);
@ -475,21 +485,27 @@ diff -uNr 05_safe_globals/src/bsp/rpi3/driver/mini_uart.rs 06_drivers_gpio_uart/
+ }
+}
diff -uNr 05_safe_globals/src/bsp/rpi3/driver.rs 06_drivers_gpio_uart/src/bsp/rpi3/driver.rs
--- 05_safe_globals/src/bsp/rpi3/driver.rs
+++ 06_drivers_gpio_uart/src/bsp/rpi3/driver.rs
@@ -0,0 +1,11 @@
diff -uNr 05_safe_globals/src/bsp/driver.rs 06_drivers_gpio_uart/src/bsp/driver.rs
--- 05_safe_globals/src/bsp/driver.rs
+++ 06_drivers_gpio_uart/src/bsp/driver.rs
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: MIT
+//
+// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
+
+//! Collection of device drivers.
+//! Drivers.
+
+#[cfg(feature = "bsp_rpi3")]
+mod bcm2837_gpio;
+
+mod gpio;
+mod mini_uart;
+#[cfg(feature = "bsp_rpi3")]
+mod bcm2xxx_mini_uart;
+
+pub use gpio::GPIO;
+pub use mini_uart::MiniUart;
+#[cfg(feature = "bsp_rpi3")]
+pub use bcm2837_gpio::GPIO;
+
+#[cfg(feature = "bsp_rpi3")]
+pub use bcm2xxx_mini_uart::MiniUart;
diff -uNr 05_safe_globals/src/bsp/rpi3/memory_map.rs 06_drivers_gpio_uart/src/bsp/rpi3/memory_map.rs
--- 05_safe_globals/src/bsp/rpi3/memory_map.rs
@ -512,23 +528,19 @@ 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,11 +4,12 @@
@@ -4,105 +4,21 @@
//! Board Support Package for the Raspberry Pi 3.
+mod driver;
-use crate::{arch::sync::NullLock, interface};
-use core::fmt;
+mod memory_map;
mod panic_wait;
mod sync;
+
+use super::driver;
+use crate::interface;
use crate::interface;
-use core::fmt;
use cortex_a::{asm, regs::*};
use sync::NullLock;
@@ -39,99 +40,13 @@
}
}
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
-/// A mystical, magical device for generating QEMU output out of the void.
-///
@ -566,8 +578,7 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs
- // Convert newline to carrige return + newline.
- if c == '
' {
- self.write_char('
')
- self.write_char(' ')
- }
-
- self.write_char(c);
@ -579,11 +590,10 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs
- }
-}
-
////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-// OS interface implementations
+// Global BSP driver instances
////////////////////////////////////////////////////////////////////////////////
-////////////////////////////////////////////////////////////////////////////////
-
-/// The main struct.
-pub struct QEMUOutput {
- inner: NullLock<QEMUOutputInner>,
@ -621,10 +631,11 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs
- }
-}
-
-////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
-// Global instances
-////////////////////////////////////////////////////////////////////////////////
-
+// Global BSP driver instances
////////////////////////////////////////////////////////////////////////////////
-static QEMU_OUTPUT: QEMUOutput = QEMUOutput::new();
+static GPIO: driver::GPIO = unsafe { driver::GPIO::new(memory_map::mmio::GPIO_BASE) };
+static MINI_UART: driver::MiniUart =
@ -632,7 +643,7 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's BSP calls
@@ -146,5 +61,15 @@
@@ -110,5 +26,15 @@
/// Return a reference to a `console::All` implementation.
pub fn console() -> &'static impl interface::console::All {
@ -650,6 +661,19 @@ diff -uNr 05_safe_globals/src/bsp/rpi3.rs 06_drivers_gpio_uart/src/bsp/rpi3.rs
+ [&GPIO, &MINI_UART]
}
diff -uNr 05_safe_globals/src/bsp.rs 06_drivers_gpio_uart/src/bsp.rs
--- 05_safe_globals/src/bsp.rs
+++ 06_drivers_gpio_uart/src/bsp.rs
@@ -4,6 +4,8 @@
//! Conditional exporting of Board Support Packages.
+mod driver;
+
#[cfg(feature = "bsp_rpi3")]
mod rpi3;
diff -uNr 05_safe_globals/src/interface.rs 06_drivers_gpio_uart/src/interface.rs
--- 05_safe_globals/src/interface.rs
+++ 06_drivers_gpio_uart/src/interface.rs
@ -678,7 +702,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
@@ -34,10 +34,27 @@
@@ -38,10 +38,27 @@
fn kernel_entry() -> ! {
use interface::console::Statistics;
@ -706,6 +730,6 @@ diff -uNr 05_safe_globals/src/main.rs 06_drivers_gpio_uart/src/main.rs
- println!("[2] Stopping here.");
+ println!("[3] Stopping here.");
bsp::wait_forever()
arch::wait_forever()
}
```

Binary file not shown.

Binary file not shown.

@ -0,0 +1,11 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Conditional exporting of processor architecture code.
#[cfg(feature = "bsp_rpi3")]
mod aarch64;
#[cfg(feature = "bsp_rpi3")]
pub use aarch64::*;

@ -0,0 +1,45 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! AArch64.
pub mod sync;
use crate::bsp;
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.
///
/// # Safety
///
/// - Linker script must ensure to place this function at `0x80_000`.
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
const CORE_MASK: u64 = 0x3;
if bsp::BOOT_CORE_ID == MPIDR_EL1.get() & CORE_MASK {
SP.set(bsp::BOOT_CORE_STACK_START);
crate::runtime_init::init()
} else {
// if not core0, infinitely wait for events
wait_forever()
}
}
////////////////////////////////////////////////////////////////////////////////
// Implementation of the kernel's architecture abstraction code
////////////////////////////////////////////////////////////////////////////////
pub use asm::nop;
/// Pause execution on the calling CPU core.
#[inline(always)]
pub fn wait_forever() -> ! {
loop {
asm::wfe()
}
}

@ -2,7 +2,7 @@
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Board-specific synchronization primitives.
//! Synchronization primitives.
use crate::interface;
use core::cell::UnsafeCell;

@ -4,8 +4,10 @@
//! Conditional exporting of Board Support Packages.
mod driver;
#[cfg(feature = "bsp_rpi3")]
pub mod rpi3;
mod rpi3;
#[cfg(feature = "bsp_rpi3")]
pub use rpi3::*;

@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Drivers.
#[cfg(feature = "bsp_rpi3")]
mod bcm2837_gpio;
#[cfg(feature = "bsp_rpi3")]
mod bcm2xxx_mini_uart;
#[cfg(feature = "bsp_rpi3")]
pub use bcm2837_gpio::GPIO;
#[cfg(feature = "bsp_rpi3")]
pub use bcm2xxx_mini_uart::MiniUart;

@ -4,10 +4,8 @@
//! GPIO driver.
use super::super::NullLock;
use crate::interface;
use crate::{arch, arch::sync::NullLock, interface};
use core::ops;
use cortex_a::asm;
use register::{mmio::ReadWrite, register_bitfields};
// GPIO registers.
@ -118,13 +116,13 @@ impl GPIOInner {
// Enable pins 14 and 15.
self.GPPUD.set(0);
for _ in 0..150 {
asm::nop();
arch::nop();
}
self.GPPUDCLK0
.write(GPPUDCLK0::PUDCLK14::AssertClock + GPPUDCLK0::PUDCLK15::AssertClock);
for _ in 0..150 {
asm::nop();
arch::nop();
}
self.GPPUDCLK0.set(0);

@ -4,10 +4,8 @@
//! Mini UART driver.
use super::super::NullLock;
use crate::interface;
use crate::{arch, arch::sync::NullLock, interface};
use core::{fmt, ops};
use cortex_a::asm;
use register::{mmio::*, register_bitfields};
// Mini UART registers.
@ -170,7 +168,7 @@ impl MiniUartInner {
break;
}
asm::nop();
arch::nop();
}
// Write the character to the buffer.

@ -4,41 +4,13 @@
//! Board Support Package for the Raspberry Pi 3.
mod driver;
mod memory_map;
mod panic_wait;
mod sync;
use super::driver;
use crate::interface;
use cortex_a::{asm, regs::*};
use sync::NullLock;
/// The entry of the `kernel` binary.
///
/// The function must be named `_start`, because the linker is looking for this
/// exact name.
///
/// # Safety
///
/// - Linker script must ensure to place this function at `0x80_000`.
#[no_mangle]
pub unsafe extern "C" fn _start() -> ! {
use crate::runtime_init;
const CORE_0: u64 = 0;
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_000;
if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
SP.set(STACK_START);
runtime_init::init()
} else {
// if not core0, infinitely wait for events
loop {
asm::wfe();
}
}
}
pub const BOOT_CORE_ID: u64 = 0;
pub const BOOT_CORE_STACK_START: u64 = 0x80_000;
////////////////////////////////////////////////////////////////////////////////
// Global BSP driver instances
@ -52,13 +24,6 @@ static MINI_UART: driver::MiniUart =
// Implementation of the kernel's BSP calls
////////////////////////////////////////////////////////////////////////////////
/// Park execution on the calling CPU core.
pub fn wait_forever() -> ! {
loop {
asm::wfe()
}
}
/// Return a reference to a `console::All` implementation.
pub fn console() -> &'static impl interface::console::All {
&MINI_UART

@ -1,11 +0,0 @@
// SPDX-License-Identifier: MIT
//
// Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
//! Collection of device drivers.
mod gpio;
mod mini_uart;
pub use gpio::GPIO;
pub use mini_uart::MiniUart;

@ -19,15 +19,19 @@
#![no_main]
#![no_std]
// This module conditionally includes the correct `BSP` which provides the
// Conditionally includes the selected `architecture` code, which provides the
// `_start()` function, the first function to run.
mod bsp;
mod arch;
// Afterwards, `BSP`'s early init code calls `runtime_init::init()` of this
// module, 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;
mod interface;
mod panic_wait;
mod print;
/// Entrypoint of the `kernel`.
@ -56,5 +60,5 @@ fn kernel_entry() -> ! {
println!("[2] Chars written: {}", bsp::console().chars_written());
println!("[3] Stopping here.");
bsp::wait_forever()
arch::wait_forever()
}

@ -15,9 +15,5 @@ fn panic(info: &PanicInfo) -> ! {
println!("Kernel panic!");
}
unsafe {
loop {
asm!("wfe" :::: "volatile")
}
}
crate::arch::wait_forever()
}
Loading…
Cancel
Save