Skip to content

Commit d6f19ce

Browse files
committed
feat(09): Add initial BSP structure for Raspberry Pi 5
Introduces the Board Support Package for Tutorial 09 for the Raspberry Pi 5. - Adds the 'bsp_rpi5' cargo feature - creates the 'src/bsp/raspberrypi5' directory, including boilerplate files for cpu, driver, kernel.ld, and memory map. - The memory map defines the base address for the RP1 I/O controller.
1 parent 5c995a4 commit d6f19ce

File tree

7 files changed

+219
-1
lines changed

7 files changed

+219
-1
lines changed

09_privilege_level/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ lto = true
1111
default = []
1212
bsp_rpi3 = ["tock-registers"]
1313
bsp_rpi4 = ["tock-registers"]
14+
bsp_rpi5 = ["tock-registers"]
1415

1516
[[bin]]
1617
name = "kernel"

09_privilege_level/src/bsp.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// SPDX-License-Identifier: MIT OR Apache-2.0
22
//
3-
// Copyright (c) 2018-2023 Andre Richter <[email protected]>
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
44

55
//! Conditional reexporting of Board Support Packages.
66
@@ -11,3 +11,9 @@ mod raspberrypi;
1111

1212
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
1313
pub use raspberrypi::*;
14+
15+
#[cfg(feature = "bsp_rpi5")]
16+
mod raspberrypi5;
17+
18+
#[cfg(feature = "bsp_rpi5")]
19+
pub use raspberrypi5::*;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
4+
// Copyright (c) 2025 Devansh Lodha <[email protected]>
5+
6+
//! Top-level BSP file for the Raspberry Pi 5.
7+
8+
pub mod cpu;
9+
pub mod driver;
10+
pub mod memory;
11+
12+
//--------------------------------------------------------------------------------------------------
13+
// Public Code
14+
//--------------------------------------------------------------------------------------------------
15+
16+
/// Board identification.
17+
pub fn board_name() -> &'static str {
18+
"Raspberry Pi 5"
19+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
4+
5+
//! BSP Processor code for the Raspberry Pi 5.
6+
7+
//--------------------------------------------------------------------------------------------------
8+
// Public Definitions
9+
//--------------------------------------------------------------------------------------------------
10+
11+
/// Used by `arch` code to find the early boot core.
12+
#[no_mangle]
13+
#[link_section = ".text._start_arguments"]
14+
pub static BOOT_CORE_ID: u64 = 0;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
4+
// Copyright (c) 2025 Devansh Lodha <[email protected]>
5+
6+
//! BSP driver support for the Raspberry Pi 5.
7+
8+
use super::memory::map::mmio;
9+
use crate::{bsp::device_driver, console, driver as generic_driver};
10+
use core::sync::atomic::{AtomicBool, Ordering};
11+
12+
//--------------------------------------------------------------------------------------------------
13+
// Global instances
14+
//--------------------------------------------------------------------------------------------------
15+
16+
static PL011_UART: device_driver::PL011Uart =
17+
unsafe { device_driver::PL011Uart::new(mmio::PL011_UART_START) };
18+
19+
static GPIO: device_driver::GPIO =
20+
unsafe { device_driver::GPIO::new(mmio::GPIO_START, mmio::PADS_BANK0_START) };
21+
22+
//--------------------------------------------------------------------------------------------------
23+
// Private Code
24+
//--------------------------------------------------------------------------------------------------
25+
26+
/// This must be called only after successful init of the UART driver.
27+
fn post_init_uart() -> Result<(), &'static str> {
28+
console::register_console(&PL011_UART);
29+
Ok(())
30+
}
31+
32+
/// This must be called only after successful init of the GPIO driver.
33+
fn post_init_gpio() -> Result<(), &'static str> {
34+
GPIO.map_pl011_uart();
35+
Ok(())
36+
}
37+
38+
fn driver_uart() -> Result<(), &'static str> {
39+
let uart_descriptor =
40+
generic_driver::DeviceDriverDescriptor::new(&PL011_UART, Some(post_init_uart));
41+
generic_driver::driver_manager().register_driver(uart_descriptor);
42+
Ok(())
43+
}
44+
45+
fn driver_gpio() -> Result<(), &'static str> {
46+
let gpio_descriptor = generic_driver::DeviceDriverDescriptor::new(&GPIO, Some(post_init_gpio));
47+
generic_driver::driver_manager().register_driver(gpio_descriptor);
48+
Ok(())
49+
}
50+
51+
//--------------------------------------------------------------------------------------------------
52+
// Public Code
53+
//--------------------------------------------------------------------------------------------------
54+
55+
/// Initialize the driver subsystem.
56+
///
57+
/// # Safety
58+
///
59+
/// See child function calls.
60+
pub unsafe fn init() -> Result<(), &'static str> {
61+
static INIT_DONE: AtomicBool = AtomicBool::new(false);
62+
if INIT_DONE.load(Ordering::Relaxed) {
63+
return Err("Init already done");
64+
}
65+
66+
// On the Raspberry Pi 5, GPIO pins must be configured for their peripheral
67+
// function (e.g., UART) before the peripheral itself is initialized.
68+
driver_gpio()?;
69+
driver_uart()?;
70+
71+
INIT_DONE.store(true, Ordering::Relaxed);
72+
Ok(())
73+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/* SPDX-License-Identifier: MIT OR Apache-2.0
2+
*
3+
* Copyright (c) 2018-2025 Andre Richter <[email protected]>
4+
*/
5+
6+
__rpi_phys_dram_start_addr = 0;
7+
8+
/* The physical address at which the the kernel binary will be loaded by the Raspberry's firmware */
9+
__rpi_phys_binary_load_addr = 0x80000;
10+
11+
12+
ENTRY(__rpi_phys_binary_load_addr)
13+
14+
/* Flags:
15+
* 4 == R
16+
* 5 == RX
17+
* 6 == RW
18+
*
19+
* Segments are marked PT_LOAD below so that the ELF file provides virtual and physical addresses.
20+
* It doesn't mean all of them need actually be loaded.
21+
*/
22+
PHDRS
23+
{
24+
segment_boot_core_stack PT_LOAD FLAGS(6);
25+
segment_code PT_LOAD FLAGS(5);
26+
segment_data PT_LOAD FLAGS(6);
27+
}
28+
29+
SECTIONS
30+
{
31+
. = __rpi_phys_dram_start_addr;
32+
33+
/***********************************************************************************************
34+
* Boot Core Stack
35+
***********************************************************************************************/
36+
.boot_core_stack (NOLOAD) :
37+
{
38+
/* ^ */
39+
/* | stack */
40+
. += __rpi_phys_binary_load_addr; /* | growth */
41+
/* | direction */
42+
__boot_core_stack_end_exclusive = .; /* | */
43+
} :segment_boot_core_stack
44+
45+
/***********************************************************************************************
46+
* Code + RO Data + Global Offset Table
47+
***********************************************************************************************/
48+
.text :
49+
{
50+
KEEP(*(.text._start))
51+
*(.text._start_arguments) /* Constants (or statics in Rust speak) read by _start(). */
52+
*(.text._start_rust) /* The Rust entry point */
53+
*(.text*) /* Everything else */
54+
} :segment_code
55+
56+
.rodata : ALIGN(8) { *(.rodata*) } :segment_code
57+
58+
/***********************************************************************************************
59+
* Data + BSS
60+
***********************************************************************************************/
61+
.data : { *(.data*) } :segment_data
62+
63+
/* Section is zeroed in pairs of u64. Align start and end to 16 bytes */
64+
.bss (NOLOAD) : ALIGN(16)
65+
{
66+
__bss_start = .;
67+
*(.bss*);
68+
. = ALIGN(16);
69+
__bss_end_exclusive = .;
70+
} :segment_data
71+
72+
/***********************************************************************************************
73+
* Misc
74+
***********************************************************************************************/
75+
.got : { *(.got*) }
76+
ASSERT(SIZEOF(.got) == 0, "Relocation support not expected")
77+
78+
/DISCARD/ : { *(.comment*) }
79+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
//
3+
// Copyright (c) 2018-2025 Andre Richter <[email protected]>
4+
// Copyright (c) 2025 Devansh Lodha <[email protected]>
5+
6+
//! BSP Memory Management.
7+
8+
//--------------------------------------------------------------------------------------------------
9+
// Public Definitions
10+
//--------------------------------------------------------------------------------------------------
11+
12+
/// The board's physical memory map.
13+
#[rustfmt::skip]
14+
pub(super) mod map {
15+
pub const RP1_PCI_ECAM_BASE: usize = 0x1f00000000;
16+
17+
/// Physical devices.
18+
pub mod mmio {
19+
use super::*;
20+
21+
// See `RP1 Peripherals` datasheet, table 5 and 22.
22+
pub const GPIO_START: usize = RP1_PCI_ECAM_BASE + 0xd0000;
23+
pub const PADS_BANK0_START: usize = RP1_PCI_ECAM_BASE + 0xf0000;
24+
pub const PL011_UART_START: usize = RP1_PCI_ECAM_BASE + 0x30000;
25+
}
26+
}

0 commit comments

Comments
 (0)