From 127f6956bdf00548f5dda9973e32f8da5b2aab0b Mon Sep 17 00:00:00 2001 From: Kirill Mikhailov Date: Wed, 13 Nov 2024 09:49:44 +0100 Subject: [PATCH] WIP (interrupts) --- esp-hal/src/interrupt/riscv.rs | 133 ++++++++++++++++++++++++++--- esp-hal/src/soc/esp32p4/mod.rs | 4 +- examples/.cargo/config.toml | 2 +- examples/src/bin/gpio_interrupt.rs | 4 +- examples/src/bin/systimer.rs | 2 +- 5 files changed, 130 insertions(+), 15 deletions(-) diff --git a/esp-hal/src/interrupt/riscv.rs b/esp-hal/src/interrupt/riscv.rs index f3a5a139c96..e9de5d9a705 100644 --- a/esp-hal/src/interrupt/riscv.rs +++ b/esp-hal/src/interrupt/riscv.rs @@ -194,14 +194,99 @@ pub static RESERVED_INTERRUPTS: &[usize] = INTERRUPT_TO_PRIORITY; #[link_section = ".trap.rust"] #[export_name = "_start_trap_rust_hal"] pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { - assert!( - mcause::read().is_exception(), - "Arrived into _start_trap_rust_hal but mcause is not an exception!" - ); - extern "C" { - fn ExceptionHandler(tf: *mut TrapFrame); + // assert!( + // mcause::read().is_exception(), + // "Arrived into _start_trap_rust_hal but mcause is not an exception!" + // ); + + if riscv::register::mcause::read().is_exception() { + extern "C" { + fn ExceptionHandler(tf: *mut TrapFrame); + } + ExceptionHandler(trap_frame); + } else { + extern "C" { + fn interrupt1(frame: &mut TrapFrame); + fn interrupt2(frame: &mut TrapFrame); + fn interrupt3(frame: &mut TrapFrame); + fn interrupt4(frame: &mut TrapFrame); + fn interrupt5(frame: &mut TrapFrame); + fn interrupt6(frame: &mut TrapFrame); + fn interrupt7(frame: &mut TrapFrame); + fn interrupt8(frame: &mut TrapFrame); + fn interrupt9(frame: &mut TrapFrame); + fn interrupt10(frame: &mut TrapFrame); + fn interrupt11(frame: &mut TrapFrame); + fn interrupt12(frame: &mut TrapFrame); + fn interrupt13(frame: &mut TrapFrame); + fn interrupt14(frame: &mut TrapFrame); + fn interrupt15(frame: &mut TrapFrame); + fn interrupt16(frame: &mut TrapFrame); + fn interrupt17(frame: &mut TrapFrame); + fn interrupt18(frame: &mut TrapFrame); + fn interrupt19(frame: &mut TrapFrame); + fn interrupt20(frame: &mut TrapFrame); + fn interrupt21(frame: &mut TrapFrame); + fn interrupt22(frame: &mut TrapFrame); + fn interrupt23(frame: &mut TrapFrame); + fn interrupt24(frame: &mut TrapFrame); + fn interrupt25(frame: &mut TrapFrame); + fn interrupt26(frame: &mut TrapFrame); + fn interrupt27(frame: &mut TrapFrame); + fn interrupt28(frame: &mut TrapFrame); + fn interrupt29(frame: &mut TrapFrame); + fn interrupt30(frame: &mut TrapFrame); + fn interrupt31(frame: &mut TrapFrame); + + // Defined in `esp-riscv-rt` + pub fn DefaultHandler(); + } + + let interrupt_priority = _handle_priority(); + + let code = riscv::register::mcause::read().code(); + + // #[cfg(clic)] + let code = (code & 0b1111_1111_1111) - 16 as usize; + + match code { + 1 => interrupt1(trap_frame.as_mut().unwrap()), + 2 => interrupt2(trap_frame.as_mut().unwrap()), + 3 => interrupt3(trap_frame.as_mut().unwrap()), + 4 => interrupt4(trap_frame.as_mut().unwrap()), + 5 => interrupt5(trap_frame.as_mut().unwrap()), + 6 => interrupt6(trap_frame.as_mut().unwrap()), + 7 => interrupt7(trap_frame.as_mut().unwrap()), + 8 => interrupt8(trap_frame.as_mut().unwrap()), + 9 => interrupt9(trap_frame.as_mut().unwrap()), + 10 => interrupt10(trap_frame.as_mut().unwrap()), + 11 => interrupt11(trap_frame.as_mut().unwrap()), + 12 => interrupt12(trap_frame.as_mut().unwrap()), + 13 => interrupt13(trap_frame.as_mut().unwrap()), + 14 => interrupt14(trap_frame.as_mut().unwrap()), + 15 => interrupt15(trap_frame.as_mut().unwrap()), + 16 => interrupt16(trap_frame.as_mut().unwrap()), + 17 => interrupt17(trap_frame.as_mut().unwrap()), + 18 => interrupt18(trap_frame.as_mut().unwrap()), + 19 => interrupt19(trap_frame.as_mut().unwrap()), + 20 => interrupt20(trap_frame.as_mut().unwrap()), + 21 => interrupt21(trap_frame.as_mut().unwrap()), + 22 => interrupt22(trap_frame.as_mut().unwrap()), + 23 => interrupt23(trap_frame.as_mut().unwrap()), + 24 => interrupt24(trap_frame.as_mut().unwrap()), + 25 => interrupt25(trap_frame.as_mut().unwrap()), + 26 => interrupt26(trap_frame.as_mut().unwrap()), + 27 => interrupt27(trap_frame.as_mut().unwrap()), + 28 => interrupt28(trap_frame.as_mut().unwrap()), + 29 => interrupt29(trap_frame.as_mut().unwrap()), + 30 => interrupt30(trap_frame.as_mut().unwrap()), + 31 => interrupt31(trap_frame.as_mut().unwrap()), + _ => DefaultHandler(), + }; + + _restore_priority(interrupt_priority); } - ExceptionHandler(trap_frame); + } #[doc(hidden)] @@ -833,19 +918,47 @@ mod clic { /// Get interrupt priority - called by assembly code #[inline] pub(super) unsafe extern "C" fn get_priority(cpu_interrupt: CpuInterrupt) -> Priority { - todo!() + let clic = &*crate::peripherals::CLIC::PTR; + let prio = clic + .int_ctrl(cpu_interrupt as usize) + .read() + .int_ctl() + .bits(); + + core::mem::transmute::(prio >> (8 - 3)) } #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _handle_priority() -> u32 { - todo!() + use super::mcause; + let clic = &*crate::peripherals::CLIC::PTR; + + let interrupt_id: usize = mcause::read().code(); // MSB is whether its exception or interrupt. + let interrupt_id = (interrupt_id & 0b1111_1111_1111) - EXTERNAL_INTERRUPT_OFFSET as usize; + + let interrupt_priority = clic.int_ctrl(interrupt_id).read().int_ctl().bits(); + + let prev_interrupt_priority = clic.int_thresh().read().cpu_int_thresh().bits(); + if interrupt_priority < 15 { + // leave interrupts disabled if interrupt is of max priority. + clic.int_thresh() + .write(|w| w.cpu_int_thresh().bits(interrupt_priority + 1)); + unsafe { + riscv::interrupt::enable(); + } + } + + prev_interrupt_priority as u32 } #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) { - todo!() + riscv::interrupt::disable(); + let clic = &*crate::peripherals::CLIC::PTR; + clic.int_thresh() + .write(|w| w.cpu_int_thresh().bits(stored_prio as u8)); } } diff --git a/esp-hal/src/soc/esp32p4/mod.rs b/esp-hal/src/soc/esp32p4/mod.rs index cdb1eeb4267..261e4f95237 100644 --- a/esp-hal/src/soc/esp32p4/mod.rs +++ b/esp-hal/src/soc/esp32p4/mod.rs @@ -36,9 +36,9 @@ pub(crate) mod registers { pub(crate) mod constants { /// Start address of the system's DRAM (low range). - pub const SOC_DRAM_LOW: usize = 0x4000_0000; + pub const SOC_DRAM_LOW: usize = 0x4FF0_0000; /// End address of the system's DRAM (high range). - pub const SOC_DRAM_HIGH: usize = 0x4C00_0000; + pub const SOC_DRAM_HIGH: usize = 0x4FFB_FFFF; /// RC FAST Clock value (Hertz). pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17500); } diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml index 937d8d06b19..bf7696070f7 100644 --- a/examples/.cargo/config.toml +++ b/examples/.cargo/config.toml @@ -9,7 +9,7 @@ esp32s2 = "run --release --features=esp32s2 --target=xtensa-esp32s2-none-elf" esp32s3 = "run --release --features=esp32s3 --target=xtensa-esp32s3-none-elf" [target.'cfg(target_arch = "riscv32")'] -runner = "espflash flash --monitor --no-stub" +runner = "espflash flash --monitor" rustflags = [ "-C", "link-arg=-Tlinkall.x", "-C", "force-frame-pointers", diff --git a/examples/src/bin/gpio_interrupt.rs b/examples/src/bin/gpio_interrupt.rs index befe9d6dc84..d1dd7f6e495 100644 --- a/examples/src/bin/gpio_interrupt.rs +++ b/examples/src/bin/gpio_interrupt.rs @@ -7,7 +7,7 @@ //! - LED => GPIO2 //! - BUTTON => GPIO0 (ESP32, ESP32-S2, ESP32-S3) / GPIO9 -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 +//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32p4 esp32s2 esp32s3 #![no_std] #![no_main] @@ -37,6 +37,8 @@ fn main() -> ! { cfg_if::cfg_if! { if #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] { let button = peripherals.GPIO0; + } else if #[cfg(feature = "esp32p4")] { + let button = peripherals.GPIO35; } else { let button = peripherals.GPIO9; } diff --git a/examples/src/bin/systimer.rs b/examples/src/bin/systimer.rs index e648e98d897..c6cef169222 100644 --- a/examples/src/bin/systimer.rs +++ b/examples/src/bin/systimer.rs @@ -2,7 +2,7 @@ //! //! It's an additional timer besides the TIMG peripherals. -//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 +//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32p4 esp32s2 esp32s3 #![no_std] #![no_main]