Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 78 additions & 23 deletions 19_kernel_heap/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## SPDX-License-Identifier: MIT OR Apache-2.0
##
## Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
## Copyright (c) 2026 Devansh Lodha <devanshlodha12@gmail.com>

include ../common/docker.mk
include ../common/format.mk
Expand Down Expand Up @@ -63,6 +64,22 @@ else ifeq ($(BSP),rpi4)
JTAG_BOOT_IMAGE = ../X1_JTAG_boot/jtag_boot_rpi4.img
LD_SCRIPT_PATH = $(shell pwd)/kernel/src/bsp/raspberrypi
RUSTC_MISC_ARGS = -C target-cpu=cortex-a72 -C force-frame-pointers
else ifeq ($(BSP),rpi5)
TARGET = aarch64-unknown-none-softfloat
KERNEL_BIN = kernel8.img
QEMU_BINARY = echo "RPi5 QEMU not supported"; \#
QEMU_MACHINE_TYPE =
QEMU_RELEASE_ARGS =
QEMU_TEST_ARGS =
OBJDUMP_BINARY = aarch64-none-elf-objdump
NM_BINARY = aarch64-none-elf-nm
READELF_BINARY = aarch64-none-elf-readelf
GDB_BINARY = aarch64-elf-gdb
GDB_INIT_FILE = ../debug/pi5/gdb-init.txt
OPENOCD_ARG = -f ../debug/pi5/cmsis-dap.cfg -f ../debug/pi5/raspberrypi5.cfg
JTAG_BOOT_IMAGE = ../X2_pi5_jtag_halt_stub/halt_stub.img
LD_SCRIPT_PATH = $(shell pwd)/kernel/src/bsp/raspberrypi
RUSTC_MISC_ARGS = -C target-cpu=cortex-a76 -C force-frame-pointers
endif

# Export for build.rs.
Expand Down Expand Up @@ -129,11 +146,11 @@ COMPILER_ARGS = --target=$(TARGET) \

# build-std can be skipped for helper commands that do not rely on correct stack frames and other
# custom compiler options. This results in a huge speedup.
RUSTC_CMD = cargo rustc $(COMPILER_ARGS) -Z build-std=core,alloc --manifest-path $(KERNEL_MANIFEST)
DOC_CMD = cargo doc $(COMPILER_ARGS)
CLIPPY_CMD = cargo clippy $(COMPILER_ARGS)
TEST_CMD = cargo test $(COMPILER_ARGS) -Z build-std=core,alloc --manifest-path $(KERNEL_MANIFEST)
OBJCOPY_CMD = rust-objcopy \
BASE_RUSTC_CMD = cargo rustc $(COMPILER_ARGS) -Z build-std=core,alloc --manifest-path $(KERNEL_MANIFEST)
BASE_DOC_CMD = cargo doc $(COMPILER_ARGS)
BASE_CLIPPY_CMD = cargo clippy $(COMPILER_ARGS)
BASE_TEST_CMD = cargo test $(COMPILER_ARGS) -Z build-std=core,alloc --manifest-path $(KERNEL_MANIFEST)
BASE_OBJCOPY_CMD = rust-objcopy \
--strip-all \
-O binary

Expand All @@ -149,27 +166,41 @@ DOCKER_CMD = docker run -t --rm -v $(shell pwd):/work/tutorial -w /wo
DOCKER_CMD_INTERACT = $(DOCKER_CMD) -i
DOCKER_ARG_DIR_COMMON = -v $(shell pwd)/../common:/work/common
DOCKER_ARG_DIR_JTAG = -v $(shell pwd)/../X1_JTAG_boot:/work/X1_JTAG_boot
DOCKER_ARG_DIR_HALT = -v $(shell pwd)/../X2_pi5_jtag_halt_stub:/work/X2_pi5_jtag_halt_stub
DOCKER_ARG_DIR_DEBUG = -v $(shell pwd)/../debug:/work/debug
DOCKER_ARG_DEV = --privileged -v /dev:/dev
DOCKER_ARG_NET = --network host

# DOCKER_IMAGE defined in include file (see top of this file).
DOCKER_QEMU = $(DOCKER_CMD_INTERACT) $(DOCKER_IMAGE)
DOCKER_TOOLS = $(DOCKER_CMD) $(DOCKER_IMAGE)
DOCKER_TEST = $(DOCKER_CMD) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)
DOCKER_GDB = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_NET) $(DOCKER_IMAGE)
DOCKER_GDB = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_NET) $(DOCKER_ARG_DIR_DEBUG) $(DOCKER_IMAGE)

# Dockerize commands, which require USB device passthrough, only on Linux.
ifeq ($(shell uname -s),Linux)
DOCKER_CMD_DEV = $(DOCKER_CMD_INTERACT) $(DOCKER_ARG_DEV)

DOCKER_CHAINBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_IMAGE)
DOCKER_JTAGBOOT = $(DOCKER_CMD_DEV) $(DOCKER_ARG_DIR_COMMON) $(DOCKER_ARG_DIR_JTAG) $(DOCKER_IMAGE)
DOCKER_OPENOCD = $(DOCKER_CMD_DEV) $(DOCKER_ARG_NET) $(DOCKER_IMAGE)
DOCKER_OPENOCD = $(DOCKER_CMD_DEV) $(DOCKER_ARG_NET) $(DOCKER_ARG_DIR_DEBUG) $(DOCKER_IMAGE)
STUB_MAKE_CMD = $(DOCKER_CMD) $(DOCKER_ARG_DIR_HALT) -w /work/X2_pi5_jtag_halt_stub $(DOCKER_IMAGE) make
else ifeq ($(shell uname -s),Darwin)
DOCKER_OPENOCD =
GDB_CMD = $(GDB_BINARY)
STUB_MAKE_CMD = $(MAKE) -C ../X2_pi5_jtag_halt_stub
else
DOCKER_OPENOCD = echo "Not yet supported on non-Linux systems."; \#
STUB_MAKE_CMD = echo "Not yet supported on non-Linux systems."; \#
endif


# These commands are always local, as per the repository's design
RUSTC_CMD = $(BASE_RUSTC_CMD)
DOC_CMD = $(BASE_DOC_CMD)
CLIPPY_CMD = $(BASE_CLIPPY_CMD)
TEST_CMD = $(BASE_TEST_CMD)
OBJCOPY_CMD = $(BASE_OBJCOPY_CMD)
CLEAN_CMD = cargo clean

##--------------------------------------------------------------------------------------------------
## Targets
Expand All @@ -191,6 +222,7 @@ $(LAST_BUILD_CONFIG):
##------------------------------------------------------------------------------
$(KERNEL_ELF_RAW): $(KERNEL_ELF_RAW_DEPS)
$(call color_header, "Compiling kernel ELF - $(BSP)")
@echo "RUSTC_CMD: RUSTFLAGS=\"$(RUSTFLAGS_PEDANTIC)\" $(RUSTC_CMD)"
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(RUSTC_CMD)

##------------------------------------------------------------------------------
Expand Down Expand Up @@ -297,7 +329,15 @@ nm: $(KERNEL_ELF)
## Push the JTAG boot image to the real HW target
##------------------------------------------------------------------------------
jtagboot:
ifeq ($(BSP),rpi5)
$(call color_header, "Building RPi5 Halt Stub")
@$(STUB_MAKE_CMD)
@cp $(JTAG_BOOT_IMAGE) kernel8.img
$(call color_progress_prefix, "Finished")
@echo "Created kernel8.img. Please copy this to your SD card."
else
@$(DOCKER_JTAGBOOT) $(EXEC_MINIPUSH) $(DEV_SERIAL) $(JTAG_BOOT_IMAGE)
endif

##------------------------------------------------------------------------------
## Start OpenOCD session
Expand All @@ -312,7 +352,11 @@ openocd:
gdb-opt0: RUSTC_MISC_ARGS += -C opt-level=0
gdb gdb-opt0: $(KERNEL_ELF)
$(call color_header, "Launching GDB")
@$(DOCKER_GDB) gdb-multiarch -q $(KERNEL_ELF)
ifeq ($(BSP),rpi5)
@$(GDB_CMD) -q -x $(GDB_INIT_FILE) $(KERNEL_ELF)
else
@$(GDB_CMD) -q $(KERNEL_ELF)
endif



Expand All @@ -323,19 +367,18 @@ gdb gdb-opt0: $(KERNEL_ELF)

test_unit test_integration: FEATURES += --features test_build

ifeq ($(QEMU_MACHINE_TYPE),) # QEMU is not supported for the board.

test_boot test_unit test_integration test:
$(call color_header, "$(QEMU_MISSING_STRING)")

else # QEMU is supported.

##------------------------------------------------------------------------------
## Run boot test
##------------------------------------------------------------------------------
test_boot: $(KERNEL_BIN)
$(call color_header, "Boot test - $(BSP)")
ifeq ($(BSP),rpi5)
@$(call color_header, "Skipping boot test for $(BSP) (no QEMU support)")
else ifeq ($(QEMU_MACHINE_TYPE),)
@$(call color_header, "$(QEMU_MISSING_STRING)")
else
@$(call color_header, "Boot test - $(BSP)")
@$(DOCKER_TEST) $(EXEC_TEST_DISPATCH) $(EXEC_QEMU) $(QEMU_RELEASE_ARGS) -kernel $(KERNEL_BIN)
endif

##------------------------------------------------------------------------------
## Helpers for unit and integration test targets
Expand Down Expand Up @@ -376,18 +419,30 @@ endef
## Run unit test(s)
##------------------------------------------------------------------------------
test_unit:
$(call color_header, "Compiling unit test(s) - $(BSP)")
$(call test_prepare)
ifeq ($(BSP),rpi5)
@echo "## Compiling unit test(s) for $(BSP), but not running."
@echo "Due to no QEMU support, tests are built but not executed."
@echo "Load and run the test binaries on-target manually for verification."
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(TEST_CMD) --no-run --lib
else
@$(call color_header, "Compiling unit test(s) - $(BSP)")
@$(call test_prepare)
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(TEST_CMD) --lib
endif

##------------------------------------------------------------------------------
## Run integration test(s)
##------------------------------------------------------------------------------
test_integration:
$(call color_header, "Compiling integration test(s) - $(BSP)")
$(call test_prepare)
ifeq ($(BSP),rpi5)
@echo "## Compiling integration test(s) for $(BSP), but not running."
@echo "Due to no QEMU support, tests are built but not executed."
@echo "Load and run the test binaries on-target manually for verification."
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(TEST_CMD) --no-run $(TEST_ARG)
else
@$(call color_header, "Compiling integration test(s) - $(BSP)")
@$(call test_prepare)
@RUSTFLAGS="$(RUSTFLAGS_PEDANTIC)" $(TEST_CMD) $(TEST_ARG)
endif

test: test_boot test_unit test_integration

endif
3 changes: 2 additions & 1 deletion 19_kernel_heap/kernel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
[package]
name = "mingo"
version = "0.19.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
authors = ["Andre Richter <andre.o.richter@gmail.com>", "Devansh Lodha <devanshlodha12@gmail.com>"]
edition = "2021"

[features]
default = []
debug_prints = []
bsp_rpi3 = ["tock-registers"]
bsp_rpi4 = ["tock-registers"]
bsp_rpi5 = ["tock-registers"]
test_build = ["qemu-exit"]

##--------------------------------------------------------------------------------------------------
Expand Down
5 changes: 3 additions & 2 deletions 19_kernel_heap/kernel/src/bsp.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
// Copyright (c) 2026 Devansh Lodha <devanshlodha12@gmail.com>

//! Conditional reexporting of Board Support Packages.

mod device_driver;

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4", feature = "bsp_rpi5"))]
mod raspberrypi;

#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4", feature = "bsp_rpi5"))]
pub use raspberrypi::*;
9 changes: 5 additions & 4 deletions 19_kernel_heap/kernel/src/bsp/device_driver.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
// Copyright (c) 2026 Devansh Lodha <devanshlodha12@gmail.com>

//! Device driver.

#[cfg(feature = "bsp_rpi4")]
#[cfg(any(feature = "bsp_rpi4", feature = "bsp_rpi5"))]
mod arm;
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4", feature = "bsp_rpi5"))]
mod bcm;
mod common;

#[cfg(feature = "bsp_rpi4")]
#[cfg(any(feature = "bsp_rpi4", feature = "bsp_rpi5"))]
pub use arm::*;
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4"))]
#[cfg(any(feature = "bsp_rpi3", feature = "bsp_rpi4", feature = "bsp_rpi5"))]
pub use bcm::*;
13 changes: 10 additions & 3 deletions 19_kernel_heap/kernel/src/bsp/device_driver/arm/gicv2.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>
// Copyright (c) 2026 Devansh Lodha <devanshlodha12@gmail.com>

//! GICv2 Driver - ARM Generic Interrupt Controller v2.
//!
Expand Down Expand Up @@ -104,13 +105,13 @@ pub type IRQNumber = BoundedUsize<{ GICv2::MAX_IRQ_NUMBER }>;
/// Representation of the GIC.
pub struct GICv2 {
/// The Distributor.
gicd: gicd::GICD,
pub(crate) gicd: gicd::GICD,

/// The CPU Interface.
gicc: gicc::GICC,
pub(crate) gicc: gicc::GICC,

/// Stores registered IRQ handlers. Writable only during kernel init. RO afterwards.
handler_table: InitStateLock<HandlerTable>,
pub(crate) handler_table: InitStateLock<HandlerTable>,
}

//--------------------------------------------------------------------------------------------------
Expand All @@ -137,6 +138,12 @@ impl GICv2 {
handler_table: InitStateLock::new(Vec::new()),
}
}

/// Set the trigger type for an interrupt (Edge or Level).
#[cfg(feature = "bsp_rpi5")]
pub fn set_trigger(&self, irq_number: &IRQNumber, edge: bool) {
self.gicd.set_trigger(irq_number, edge);
}
}

//------------------------------------------------------------------------------
Expand Down
37 changes: 35 additions & 2 deletions 19_kernel_heap/kernel/src/bsp/device_driver/arm/gicv2/gicd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2020-2023 Andre Richter <andre.o.richter@gmail.com>
// Copyright (c) 2026 Devansh Lodha <devanshlodha12@gmail.com>

//! GICD Driver - GIC Distributor.
//!
Expand Down Expand Up @@ -54,7 +55,8 @@ register_structs! {
(0x104 => ISENABLER: [ReadWrite<u32>; 31]),
(0x180 => _reserved2),
(0x820 => ITARGETSR: [ReadWrite<u32, ITARGETSR::Register>; 248]),
(0xC00 => @END),
(0xC00 => ICFGR: [ReadWrite<u32>; 64]),
(0xD00 => @END),
}
}

Expand All @@ -65,7 +67,9 @@ register_structs! {
(0x100 => ISENABLER: ReadWrite<u32>),
(0x104 => _reserved2),
(0x800 => ITARGETSR: [ReadOnly<u32, ITARGETSR::Register>; 8]),
(0x820 => @END),
(0x820 => _reserved3),
(0xC00 => ICFGR: [ReadWrite<u32>; 2]), // Banked for PPIs
(0xC08 => @END),
}
}

Expand Down Expand Up @@ -198,4 +202,33 @@ impl GICD {
}
}
}

/// Set the trigger type for an interrupt (Edge or Level).
#[cfg(feature = "bsp_rpi5")]
pub fn set_trigger(&self, irq_num: &super::IRQNumber, edge: bool) {
let irq_num = irq_num.get();
// Each register holds 16 IRQs (2 bits per IRQ).
let reg_index = irq_num >> 4;
let bit_shift = (irq_num % 16) * 2;
let config_val = if edge { 0b10 } else { 0b00 }; // 10=Edge, 00=Level

match irq_num {
0..=31 => {
let reg = &self.banked_registers.ICFGR[reg_index];
let mut val = reg.get();
val &= !(0b11 << bit_shift);
val |= config_val << bit_shift;
reg.set(val);
}
_ => {
self.shared_registers.lock(|regs| {
let reg = &regs.ICFGR[reg_index];
let mut val = reg.get();
val &= !(0b11 << bit_shift);
val |= config_val << bit_shift;
reg.set(val);
});
}
}
}
}
18 changes: 18 additions & 0 deletions 19_kernel_heap/kernel/src/bsp/device_driver/bcm.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
//
// Copyright (c) 2018-2023 Andre Richter <andre.o.richter@gmail.com>
// Copyright (c) 2026 Devansh Lodha <devanshlodha12@gmail.com>

//! BCM driver top level.

#[cfg(not(feature = "bsp_rpi5"))]
mod bcm2xxx_gpio;
#[cfg(feature = "bsp_rpi3")]
mod bcm2xxx_interrupt_controller;
mod bcm2xxx_pl011_uart;

#[cfg(not(feature = "bsp_rpi5"))]
pub use bcm2xxx_gpio::*;
#[cfg(feature = "bsp_rpi3")]
pub use bcm2xxx_interrupt_controller::*;
pub use bcm2xxx_pl011_uart::*;

#[cfg(feature = "bsp_rpi5")]
mod rp1_gpio;
#[cfg(feature = "bsp_rpi5")]
pub use rp1_gpio::*;

#[cfg(feature = "bsp_rpi5")]
mod bcm2712_ic;
#[cfg(feature = "bsp_rpi5")]
pub use bcm2712_ic::*;

#[cfg(feature = "bsp_rpi5")]
mod bcm2712_pcie;
#[cfg(feature = "bsp_rpi5")]
pub use bcm2712_pcie::*;
Loading
Loading