diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a927afa28f..c3676eb1379 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: "esp32c3", "esp32c6", "esp32h2", - "esp32p4", + # "esp32p4", # Xtensa devices: "esp32", "esp32s2", @@ -179,7 +179,7 @@ jobs: cargo xtask build-package --features=esp32c3 --target=riscv32imc-unknown-none-elf esp-hal cargo xtask build-package --features=esp32c6 --target=riscv32imac-unknown-none-elf esp-hal cargo xtask build-package --features=esp32h2 --target=riscv32imac-unknown-none-elf esp-hal - cargo xtask build-package --features=esp32p4 --target=riscv32imafc-unknown-none-elf esp-hal + # cargo xtask build-package --features=esp32p4 --target=riscv32imafc-unknown-none-elf esp-hal - name: msrv (esp-lp-hal) run: | cargo xtask build-package --features=esp32c6 --target=riscv32imac-unknown-none-elf esp-lp-hal diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index bd3a8aa9eb9..7522afb5c07 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - ESP32-C6 / ESP32-H2: Implement `ETM` for general purpose timers (#1274) +- `interrupt::enable` now has a direct CPU enable counter part, `interrupt::enable_direct` (#1310) ### Fixed @@ -27,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - Remove package-level type exports (#1275) +- Removed `direct-vectoring` & `interrupt-preemption` features, as they are now enabled by default (#1310) ## [0.16.1] - 2024-03-12 diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 6581fcc23f1..daa50df8d92 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -131,13 +131,9 @@ esp32s2 = ["dep:esp32s2", "xtensa", "portable-atomic/critical-section", "procmac esp32s3 = ["dep:esp32s3", "xtensa", "procmacros/has-ulp-core", "xtensa-lx/spin", "xtensa-lx-rt?/esp32s3", "usb-otg"] #! ### RISC-V Exclusive Feature Flags -## Enable direct interrupt vectoring. -direct-vectoring = ["esp-riscv-rt/direct-vectoring"] ## Move the stack to start of RAM to get zero-cost stack overflow protection ## (ESP32-C6 and ESPS32-H2 only!). flip-link = ["esp-riscv-rt/fix-sp"] -## Enable interrupt preemption. -interrupt-preemption = ["esp-riscv-rt/interrupt-preemption"] ## Configuration for placing device drivers in the IRAM for faster access. place-spi-driver-in-ram = [] ## Initialize the `.data` section of memory. diff --git a/esp-hal/build.rs b/esp-hal/build.rs index a1d13e3518b..efc6e90ab4e 100644 --- a/esp-hal/build.rs +++ b/esp-hal/build.rs @@ -7,7 +7,7 @@ use std::{ str::FromStr, }; -use esp_metadata::{Arch, Chip, Config}; +use esp_metadata::{Chip, Config}; // Macros taken from: // https://github.com/TheDan64/inkwell/blob/36c3b10/src/lib.rs#L81-L110 @@ -113,21 +113,13 @@ fn main() -> Result<(), Box> { panic!("The target does not support PSRAM"); } - // Don't support "interrupt-preemption" and "direct-vectoring" on Xtensa and - // RISC-V with CLIC: - if (config.contains(&String::from("clic")) || config.arch() == Arch::Xtensa) - && (cfg!(feature = "direct-vectoring") || cfg!(feature = "interrupt-preemption")) - { - panic!("The target does not support interrupt-preemption and direct-vectoring"); - } - // Define all necessary configuration symbols for the configured device: config.define_symbols(); #[allow(unused_mut)] let mut config_symbols = config.all(); #[cfg(feature = "flip-link")] - config_symbols.push("flip-link"); + config_symbols.push("flip-link".to_owned()); // Place all linker scripts in `OUT_DIR`, and instruct Cargo how to find these // files: diff --git a/esp-hal/src/embassy/executor/interrupt.rs b/esp-hal/src/embassy/executor/interrupt.rs index 18f2164f4be..ad15c00b1d6 100644 --- a/esp-hal/src/embassy/executor/interrupt.rs +++ b/esp-hal/src/embassy/executor/interrupt.rs @@ -42,11 +42,7 @@ macro_rules! from_cpu { panic!("FROM_CPU_{} is already used by a different executor.", $irq); } - // unsafe block because of direct-vectoring on riscv - #[allow(unused_unsafe)] - unsafe { - unwrap!(interrupt::enable(peripherals::Interrupt::[], priority)); - } + unwrap!(interrupt::enable(peripherals::Interrupt::[], priority)); } fn number() -> usize { diff --git a/esp-hal/src/interrupt/mod.rs b/esp-hal/src/interrupt/mod.rs index f7b92eee38e..5652e0b8b5e 100644 --- a/esp-hal/src/interrupt/mod.rs +++ b/esp-hal/src/interrupt/mod.rs @@ -1,27 +1,18 @@ //! # Interrupt support //! -//! ## Overview -//! The `interrupt` driver is a crucial module for ESP chips. Its primary -//! purpose is to manage and handle interrupts, which are asynchronous events -//! requiring immediate attention from the CPU. Interrupts are essential in -//! various applications, such as real-time tasks, I/O communications, and -//! handling external events like hardware signals. -//! -//! The core functionality of the `interrupt` driver revolves around the -//! management of interrupts. When an interrupt occurs, it temporarily stops the -//! ongoing CPU operations, saves its current state, and starts executing the -//! corresponding interrupt service routine (ISR). The interrupt service routine -//! is a user-defined function that performs the necessary actions to handle the -//! specific interrupt. Once the ISR is executed, the driver restores the saved -//! CPU state and resumes normal program execution. -//! -//! In scenarios where multiple interrupts may occur simultaneously, the -//! interrupt driver determines the `priority` of each interrupt. This -//! prioritization ensures that critical or high-priority tasks are handled -//! first. It helps prevent delays in time-sensitive applications and allows the -//! system to allocate resources efficiently. This functionality is provided and -//! implemented by the `priority` enum. +//! Interrupt support functionality depends heavily on the features enabled. //! +//! When the `vectored` feature is enabled, the +//! [`enable`] method will map interrupt to a CPU +//! interrupt, and handle the `vector`ing to the peripheral interrupt, for +//! example `UART0`. +//! +//! It is also possible, but not recommended, to bind an interrupt directly to a +//! CPU interrupt. This can offer lower latency, at the cost of more complexity +//! in the interrupt handler. +//! +//! The `vectored` reserves a number of CPU interrupts, which cannot be used see +//! [`RESERVED_INTERRUPTS`]. //! //! ## Example //! ```no_run @@ -30,12 +21,20 @@ //! ... //! critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int)); //! +//! // enable the interrupt //! interrupt::enable( //! peripherals::Interrupt::FROM_CPU_INTR0, //! interrupt::Priority::Priority1, //! ) //! .unwrap(); //! +//! // trigger the interrupt +//! SWINT +//! .borrow_ref_mut(cs) +//! .as_mut() +//! .unwrap() +//! .raise(SoftwareInterrupt::SoftwareInterrupt0); +//! //! loop {} //! } //! diff --git a/esp-hal/src/interrupt/riscv.rs b/esp-hal/src/interrupt/riscv.rs index da13660588b..f941628fa79 100644 --- a/esp-hal/src/interrupt/riscv.rs +++ b/esp-hal/src/interrupt/riscv.rs @@ -29,6 +29,15 @@ use crate::{ Cpu, }; +/// Interrupt Error +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + InvalidInterruptPriority, + #[cfg(feature = "vectored")] + CpuInterruptReserved, +} + /// Interrupt kind #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum InterruptKind { @@ -127,6 +136,194 @@ impl Priority { #[cfg(feature = "vectored")] pub use vectored::*; +#[cfg(feature = "vectored")] +pub const RESERVED_INTERRUPTS: &[usize] = INTERRUPT_TO_PRIORITY; + +/// # Safety +/// +/// This function is called from an assembly trap handler. +#[doc(hidden)] +#[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); + } + ExceptionHandler(trap_frame); +} + +#[doc(hidden)] +#[no_mangle] +pub fn _setup_interrupts() { + extern "C" { + static _vector_table: *const u32; + } + + unsafe { + // disable all known interrupts + // at least after the 2nd stage bootloader there are some interrupts enabled + // (e.g. UART) + for peripheral_interrupt in 0..255 { + crate::soc::peripherals::Interrupt::try_from(peripheral_interrupt) + .map(|intr| { + #[cfg(multi_core)] + disable(Cpu::AppCpu, intr); + disable(Cpu::ProCpu, intr); + }) + .ok(); + } + + let vec_table = &_vector_table as *const _ as usize; + mtvec::write(vec_table, mtvec::TrapMode::Vectored); + + #[cfg(feature = "vectored")] + crate::interrupt::init_vectoring(); + }; + + #[cfg(plic)] + unsafe { + core::arch::asm!("csrw mie, {0}", in(reg) u32::MAX); + } +} + +/// Enable an interrupt by directly binding it to a available CPU interrupt +/// +/// Unless you are sure, you most likely want to use [`enable`] with the +/// `vectored` feature enabled instead. +/// +/// When the `vectored` feature is enabled, trying using a reserved interrupt +/// from [`RESERVED_INTERRUPTS`] will return an error. +pub fn enable_direct( + interrupt: Interrupt, + level: Priority, + cpu_interrupt: CpuInterrupt, +) -> Result<(), Error> { + #[cfg(feature = "vectored")] + if RESERVED_INTERRUPTS.contains(&(cpu_interrupt as _)) { + return Err(Error::CpuInterruptReserved); + } + if matches!(level, Priority::None) { + return Err(Error::InvalidInterruptPriority); + } + unsafe { + map(crate::get_core(), interrupt, cpu_interrupt); + set_priority(crate::get_core(), cpu_interrupt, level); + enable_cpu_interrupt(cpu_interrupt); + } + Ok(()) +} + +/// Disable the given peripheral interrupt. +pub fn disable(_core: Cpu, interrupt: Interrupt) { + unsafe { + let interrupt_number = interrupt as isize; + let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32; + + // set to 0 to disable the peripheral interrupt on chips with an interrupt + // controller other than PLIC use the disabled interrupt 31 otherwise + intr_map_base + .offset(interrupt_number) + .write_volatile(DISABLED_CPU_INTERRUPT); + } +} + +/// Get status of peripheral interrupts +#[inline] +pub fn get_status(_core: Cpu) -> u128 { + #[cfg(large_intr_status)] + unsafe { + ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_0() + .read() + .bits() as u128) + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_1() + .read() + .bits() as u128) + << 32 + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .int_status_reg_2() + .read() + .bits() as u128) + << 64 + } + + #[cfg(very_large_intr_status)] + unsafe { + ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_0() + .read() + .bits() as u128) + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_1() + .read() + .bits() as u128) + << 32 + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_2() + .read() + .bits() as u128) + << 64 + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_3() + .read() + .bits() as u128) + << 96 + } + + #[cfg(not(any(large_intr_status, very_large_intr_status)))] + unsafe { + ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_0() + .read() + .bits() as u128) + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_1() + .read() + .bits() as u128) + << 32 + } +} + +/// Assign a peripheral interrupt to an CPU interrupt. +/// +/// Great care must be taken when using the `vectored` feature, +/// do not use CPU interrupts in the [`RESERVED_INTERRUPTS`] when +/// the `vectored` feature is enabled. +pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { + let interrupt_number = interrupt as isize; + let cpu_interrupt_number = which as isize; + #[cfg(not(multi_core))] + let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32; + #[cfg(multi_core)] + let intr_map_base = match _core { + Cpu::ProCpu => crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32, + Cpu::AppCpu => crate::soc::registers::INTERRUPT_MAP_BASE_APP_CPU as *mut u32, + }; + + intr_map_base + .offset(interrupt_number) + .write_volatile(cpu_interrupt_number as u32 + EXTERNAL_INTERRUPT_OFFSET); +} + +/// Get cpu interrupt assigned to peripheral interrupt +#[inline] +unsafe fn get_assigned_cpu_interrupt(interrupt: Interrupt) -> Option { + let interrupt_number = interrupt as isize; + let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32; + + let cpu_intr = intr_map_base.offset(interrupt_number).read_volatile(); + if cpu_intr > 0 { + Some(core::mem::transmute(cpu_intr - EXTERNAL_INTERRUPT_OFFSET)) + } else { + None + } +} + #[cfg(feature = "vectored")] mod vectored { use procmacros::ram; @@ -174,18 +371,10 @@ mod vectored { } } - /// Interrupt Error - #[derive(Copy, Clone, Debug, PartialEq, Eq)] - #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub enum Error { - InvalidInterruptPriority, - } - /// Enables a interrupt at a given priority /// /// Note that interrupts still need to be enabled globally for interrupts /// to be serviced. - #[cfg(not(feature = "direct-vectoring"))] pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> { if matches!(level, Priority::None) { return Err(Error::InvalidInterruptPriority); @@ -206,31 +395,6 @@ mod vectored { ptr.write_volatile(handler); } - /// Enables an interrupt at a given priority, maps it to the given CPU - /// interrupt and assigns the given priority. - /// - /// This can be side-effectful since no guarantees can be made about the - /// CPU interrupt not already being in use. - /// - /// Note that interrupts still need to be enabled globally for interrupts - /// to be serviced. - #[cfg(feature = "direct-vectoring")] - pub unsafe fn enable( - interrupt: Interrupt, - level: Priority, - cpu_interrupt: CpuInterrupt, - ) -> Result<(), Error> { - if matches!(level, Priority::None) { - return Err(Error::InvalidInterruptPriority); - } - unsafe { - map(crate::get_core(), interrupt, cpu_interrupt); - set_priority(crate::get_core(), cpu_interrupt, level); - enable_cpu_interrupt(cpu_interrupt); - } - Ok(()) - } - #[ram] unsafe fn handle_interrupts(cpu_intr: CpuInterrupt, context: &mut TrapFrame) { let status = get_status(crate::get_core()); @@ -275,391 +439,123 @@ mod vectored { #[no_mangle] #[ram] - pub unsafe fn interrupt1(context: &mut TrapFrame) { + unsafe fn cpu_int_1_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt1, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt2(context: &mut TrapFrame) { + unsafe fn cpu_int_2_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt2, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt3(context: &mut TrapFrame) { + unsafe fn cpu_int_3_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt3, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt4(context: &mut TrapFrame) { + unsafe fn cpu_int_4_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt4, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt5(context: &mut TrapFrame) { + unsafe fn cpu_int_5_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt5, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt6(context: &mut TrapFrame) { + unsafe fn cpu_int_6_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt6, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt7(context: &mut TrapFrame) { + unsafe fn cpu_int_7_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt7, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt8(context: &mut TrapFrame) { + unsafe fn cpu_int_8_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt8, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt9(context: &mut TrapFrame) { + unsafe fn cpu_int_9_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt9, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt10(context: &mut TrapFrame) { + unsafe fn cpu_int_10_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt10, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt11(context: &mut TrapFrame) { + unsafe fn cpu_int_11_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt11, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt12(context: &mut TrapFrame) { + unsafe fn cpu_int_12_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt12, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt13(context: &mut TrapFrame) { + unsafe fn cpu_int_13_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt13, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt14(context: &mut TrapFrame) { + unsafe fn cpu_int_14_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt14, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt15(context: &mut TrapFrame) { + unsafe fn cpu_int_15_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt15, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt16(context: &mut TrapFrame) { + unsafe fn cpu_int_16_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt16, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt17(context: &mut TrapFrame) { + unsafe fn cpu_int_17_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt17, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt18(context: &mut TrapFrame) { + unsafe fn cpu_int_18_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt18, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt19(context: &mut TrapFrame) { + unsafe fn cpu_int_19_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt19, context) } } -/// # Safety -/// -/// This function is called from an assembly trap handler. -#[doc(hidden)] -#[link_section = ".trap.rust"] -#[export_name = "_start_trap_rust_hal"] -pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { - // User code shouldn't usually take the mutable TrapFrame or the TrapFrame in - // general. However this makes things like preemtive multitasking easier in - // future - 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 cause = mcause::read(); - if cause.is_exception() { - extern "C" { - fn ExceptionHandler(tf: *mut TrapFrame); - } - ExceptionHandler(trap_frame); - } else { - #[cfg(feature = "interrupt-preemption")] - let interrupt_priority = _handle_priority(); - - let code = mcause::read().code(); - - // with CLIC the MCAUSE register changed - // 31: Interrupt flag (same as before) - // - // 30: MINHV: Used to indicate whether the processor is fetching the vector - // interrupt entry address. This bit will be set high when the processor - // responds to the vector interrupt. Cleared to 0 after successfully obtaining - // the vector interrupt service routine entry address - // - // 29-28: MPP: This bit is the mirror image of MSTATUS.MPP[1:0], that is, - // reading and writing MCAUSE.MPP will produce the same result as - // reading and writing MSTATUS.MPP. - // - // 27: MPIE: This bit mirrors MSTATUS.MPIE - // - // 23-16: MPIL: This bit saves the interrupt priority level before the - // processor enters the interrupt service routine, that is, the MINTSTATUS.MIL - // bit is copied to this bit. When executing the MRET instruction and returning - // from an interrupt, the processor copies the MPIL bit to the MIL bit in the - // MINTSTATUS register. - // - // 11-0: Exception code: When the processor is configured in CLIC mode, this - // bit field is expanded to 12 bits, supporting up to 4096 interrupt ID number - // records. - // - // So we need to mask out bits other than > 12. We currently only support - // external interrupts so we subtract EXTERNAL_INTERRUPT_OFFSET - #[cfg(clic)] - let code = (code & 0b1111_1111_1111) - EXTERNAL_INTERRUPT_OFFSET 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(), - }; - - #[cfg(feature = "interrupt-preemption")] - _restore_priority(interrupt_priority); - } -} - -#[doc(hidden)] -#[no_mangle] -pub fn _setup_interrupts() { - extern "C" { - static _vector_table: *const u32; - } - - unsafe { - // disable all known interrupts - // at least after the 2nd stage bootloader there are some interrupts enabled - // (e.g. UART) - for peripheral_interrupt in 0..255 { - crate::soc::peripherals::Interrupt::try_from(peripheral_interrupt) - .map(|intr| { - #[cfg(multi_core)] - disable(Cpu::AppCpu, intr); - disable(Cpu::ProCpu, intr); - }) - .ok(); - } - - let vec_table = &_vector_table as *const _ as usize; - mtvec::write(vec_table, mtvec::TrapMode::Vectored); - - #[cfg(feature = "vectored")] - crate::interrupt::init_vectoring(); - }; - - #[cfg(plic)] - unsafe { - core::arch::asm!("csrw mie, {0}", in(reg) u32::MAX); - } -} - -/// Disable the given peripheral interrupt. -pub fn disable(_core: Cpu, interrupt: Interrupt) { - unsafe { - let interrupt_number = interrupt as isize; - let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32; - - // set to 0 to disable the peripheral interrupt on chips with an interrupt - // controller other than PLIC use the disabled interrupt 31 otherwise - intr_map_base - .offset(interrupt_number) - .write_volatile(DISABLED_CPU_INTERRUPT); - } -} - -/// Get status of peripheral interrupts -#[inline] -pub fn get_status(_core: Cpu) -> u128 { - #[cfg(large_intr_status)] - unsafe { - ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_0() - .read() - .bits() as u128) - | ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_1() - .read() - .bits() as u128) - << 32 - | ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .int_status_reg_2() - .read() - .bits() as u128) - << 64 - } - - #[cfg(very_large_intr_status)] - unsafe { - ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_0() - .read() - .bits() as u128) - | ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_1() - .read() - .bits() as u128) - << 32 - | ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_2() - .read() - .bits() as u128) - << 64 - | ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_3() - .read() - .bits() as u128) - << 96 - } - - #[cfg(not(any(large_intr_status, very_large_intr_status)))] - unsafe { - ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_0() - .read() - .bits() as u128) - | ((*crate::peripherals::INTERRUPT_CORE0::PTR) - .intr_status_reg_1() - .read() - .bits() as u128) - << 32 - } -} - -/// Assign a peripheral interrupt to an CPU interrupt. -/// -/// Great care must be taken when using the `vectored` feature (enabled by -/// default). Avoid interrupts 1 - 15 when interrupt vectoring is enabled. -pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { - let interrupt_number = interrupt as isize; - let cpu_interrupt_number = which as isize; - #[cfg(not(multi_core))] - let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32; - #[cfg(multi_core)] - let intr_map_base = match _core { - Cpu::ProCpu => crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32, - Cpu::AppCpu => crate::soc::registers::INTERRUPT_MAP_BASE_APP_CPU as *mut u32, - }; - - intr_map_base - .offset(interrupt_number) - .write_volatile(cpu_interrupt_number as u32 + EXTERNAL_INTERRUPT_OFFSET); -} - -/// Get cpu interrupt assigned to peripheral interrupt -#[inline] -unsafe fn get_assigned_cpu_interrupt(interrupt: Interrupt) -> Option { - let interrupt_number = interrupt as isize; - let intr_map_base = crate::soc::registers::INTERRUPT_MAP_BASE as *mut u32; - - let cpu_intr = intr_map_base.offset(interrupt_number).read_volatile(); - if cpu_intr > 0 { - Some(core::mem::transmute(cpu_intr - EXTERNAL_INTERRUPT_OFFSET)) - } else { - None - } -} - #[cfg(not(any(plic, clic)))] mod classic { use super::{CpuInterrupt, InterruptKind, Priority}; @@ -669,11 +565,11 @@ mod classic { pub(super) const EXTERNAL_INTERRUPT_OFFSET: u32 = 0; - pub(super) const PRIORITY_TO_INTERRUPT: [usize; 15] = - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + pub(super) const PRIORITY_TO_INTERRUPT: &[usize] = + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - pub(super) const INTERRUPT_TO_PRIORITY: [usize; 15] = - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + pub(super) const INTERRUPT_TO_PRIORITY: &[usize] = + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; /// Enable a CPU interrupt pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { @@ -749,7 +645,6 @@ mod classic { .read_volatile(); core::mem::transmute(prio as u8) } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _handle_priority() -> u32 { @@ -759,7 +654,7 @@ mod classic { let interrupt_priority = intr .cpu_int_pri_0() .as_ptr() - .offset(interrupt_id as isize) + .add(interrupt_id) .read_volatile(); let prev_interrupt_priority = intr.cpu_int_thresh().read().bits(); @@ -773,7 +668,6 @@ mod classic { } prev_interrupt_priority } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) { @@ -795,10 +689,10 @@ mod plic { // don't use interrupts reserved for CLIC (0,3,4,7) // for some reason also CPU interrupt 8 doesn't work by default since it's // disabled after reset - so don't use that, too - pub(super) const PRIORITY_TO_INTERRUPT: [usize; 15] = - [1, 2, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; + pub(super) const PRIORITY_TO_INTERRUPT: &[usize] = + &[1, 2, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; - pub(super) const INTERRUPT_TO_PRIORITY: [usize; 19] = [ + pub(super) const INTERRUPT_TO_PRIORITY: &[usize] = &[ 1, 2, 0, 0, 3, 4, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, ]; @@ -807,7 +701,6 @@ mod plic { const PLIC_MXINT_TYPE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x4; const PLIC_MXINT_CLEAR_REG: u32 = DR_REG_PLIC_MX_BASE + 0x8; const PLIC_MXINT0_PRI_REG: u32 = DR_REG_PLIC_MX_BASE + 0x10; - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] const PLIC_MXINT_THRESH_REG: u32 = DR_REG_PLIC_MX_BASE + 0x90; /// Enable a CPU interrupt pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { @@ -883,13 +776,12 @@ mod plic { .read_volatile(); core::mem::transmute(prio as u8) } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _handle_priority() -> u32 { use super::mcause; let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32; - let interrupt_id: isize = mcause::read().code().try_into().unwrap(); // MSB is whether its exception or interrupt. + let interrupt_id: isize = unwrap!(mcause::read().code().try_into()); // MSB is whether its exception or interrupt. let interrupt_priority = plic_mxint_pri_ptr.offset(interrupt_id).read_volatile(); let thresh_reg = PLIC_MXINT_THRESH_REG as *mut u32; @@ -904,7 +796,6 @@ mod plic { } prev_interrupt_priority } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) { @@ -923,11 +814,11 @@ mod clic { pub(super) const EXTERNAL_INTERRUPT_OFFSET: u32 = 16; - pub(super) const PRIORITY_TO_INTERRUPT: [usize; 15] = - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + pub(super) const PRIORITY_TO_INTERRUPT: &[usize] = + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - pub(super) const INTERRUPT_TO_PRIORITY: [usize; 15] = - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + pub(super) const INTERRUPT_TO_PRIORITY: &[usize] = + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; // The memory map for interrupt registers is on a per-core basis, // base points to the current core interrupt register, diff --git a/esp-hal/src/interrupt/xtensa.rs b/esp-hal/src/interrupt/xtensa.rs index 285dfe40042..6b1b4d7a6a0 100644 --- a/esp-hal/src/interrupt/xtensa.rs +++ b/esp-hal/src/interrupt/xtensa.rs @@ -9,6 +9,14 @@ use crate::{ Cpu, }; +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + InvalidInterrupt, + #[cfg(feature = "vectored")] + CpuInterruptReserved, +} + /// Enumeration of available CPU interrupts /// /// It's possible to create one handler per priority level. (e.g @@ -52,16 +60,41 @@ pub enum CpuInterrupt { Interrupt31EdgePriority5, } +pub const RESERVED_INTERRUPTS: &[usize] = &[ + CpuInterrupt::Interrupt1LevelPriority1 as _, + CpuInterrupt::Interrupt19LevelPriority2 as _, + CpuInterrupt::Interrupt23LevelPriority3 as _, + CpuInterrupt::Interrupt10EdgePriority1 as _, + CpuInterrupt::Interrupt22EdgePriority3 as _, +]; + +/// Enable an interrupt by directly binding it to a available CPU interrupt +/// +/// Unless you are sure, you most likely want to use [`enable`] with the +/// `vectored` feature enabled instead. +/// +/// When the `vectored` feature is enabled, trying using a reserved interrupt +/// from [`RESERVED_INTERRUPTS`] will return an error. +pub fn enable_direct(interrupt: Interrupt, cpu_interrupt: CpuInterrupt) -> Result<(), Error> { + #[cfg(feature = "vectored")] + if RESERVED_INTERRUPTS.contains(&(cpu_interrupt as _)) { + return Err(Error::CpuInterruptReserved); + } + unsafe { + map(crate::get_core(), interrupt, cpu_interrupt); + + xtensa_lx::interrupt::enable_mask( + xtensa_lx::interrupt::get_mask() | 1 << cpu_interrupt as u32, + ); + } + Ok(()) +} + /// Assign a peripheral interrupt to an CPU interrupt /// /// Great care **must** be taken when using this function with interrupt -/// vectoring (enabled by default). Avoid the following CPU interrupts: -/// - Interrupt1LevelPriority1 -/// - Interrupt19LevelPriority2 -/// - Interrupt23LevelPriority3 -/// - Interrupt10EdgePriority1 -/// - Interrupt22EdgePriority3 -/// As they are preallocated for interrupt vectoring. +/// vectoring (enabled by default). Avoid the interrupts listed in +/// [`RESERVED_INTERRUPTS`] as they are preallocated for interrupt vectoring. /// /// Note: this only maps the interrupt to the CPU interrupt. The CPU interrupt /// still needs to be enabled afterwards @@ -196,12 +229,6 @@ mod vectored { use super::*; use crate::get_core; - #[derive(Copy, Clone, Debug, PartialEq, Eq)] - #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub enum Error { - InvalidInterrupt, - } - /// Interrupt priority levels. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] diff --git a/esp-riscv-rt/Cargo.toml b/esp-riscv-rt/Cargo.toml index 76e2f35404b..6a6d9208332 100644 --- a/esp-riscv-rt/Cargo.toml +++ b/esp-riscv-rt/Cargo.toml @@ -35,22 +35,14 @@ zero-bss = [] ## Zero the `.rtc_fast.bss` section. zero-rtc-fast-bss = [] -#! ### Interrupt Feature Flags -## Enable direct interrupt vectoring. -direct-vectoring = [] -## Enable interrupt preemption. -interrupt-preemption = [] - # This feature is intended for testing; you probably don't want to enable it: ci = [ - "direct-vectoring", "fix-sp", "has-mie-mip", "init-data", "init-rtc-fast-data", "init-rtc-fast-text", "init-rw-text", - "interrupt-preemption", "zero-bss", "zero-rtc-fast-bss", ] diff --git a/esp-riscv-rt/src/lib.rs b/esp-riscv-rt/src/lib.rs index ee941243bff..226492c3e49 100644 --- a/esp-riscv-rt/src/lib.rs +++ b/esp-riscv-rt/src/lib.rs @@ -442,7 +442,7 @@ _abs_start: _start_trap_rust, then restores all saved registers before `mret` */ .section .trap, "ax" -.weak _start_trap +.weak _start_trap /* Exceptions call into _start_trap in vectored mode */ .weak _start_trap1 .weak _start_trap2 .weak _start_trap3 @@ -475,8 +475,40 @@ _abs_start: .weak _start_trap30 .weak _start_trap31 "#, -#[cfg(feature="direct-vectoring")] r#" +_start_trap: // Handle exceptions in vectored mode +"#, +#[cfg(feature="fix-sp")] +r#" + // move SP to some save place if it's pointing below the RAM + // otherwise we won't be able to do anything reasonable + // (since we don't have a working stack) + // + // most probably we will just print something and halt in this case + // we actually can't do anything else + csrw mscratch, t0 + la t0, _stack_end + bge sp, t0, 1f + + // use the reserved exception cause 14 to signal we detected a stack overflow + li t0, 14 + csrw mcause, t0 + + // set SP to the start of the stack + la sp, _stack_start + li t0, 4 // make sure stack start is in RAM + sub sp, sp, t0 + andi sp, sp, -16 // Force 16-byte alignment + + 1: + csrr t0, mscratch + // now SP is in RAM - continue +"#, +r#" + addi sp, sp, -40*4 + sw ra, 0(sp) + la ra, _start_trap_rust_hal /* Load the HAL trap handler */ + j _start_trap_direct _start_trap1: addi sp, sp, -40*4 sw ra, 0(sp) @@ -632,77 +664,7 @@ _start_trap31: sw ra, 0(sp) la ra, cpu_int_31_handler j _start_trap_direct -"#, -#[cfg(not(feature="direct-vectoring"))] -r#" -_start_trap1: -_start_trap2: -_start_trap3: -_start_trap4: -_start_trap5: -_start_trap6: -_start_trap7: -_start_trap8: -_start_trap9: -_start_trap10: -_start_trap11: -_start_trap12: -_start_trap13: -_start_trap14: -_start_trap15: -_start_trap16: -_start_trap17: -_start_trap18: -_start_trap19: -_start_trap20: -_start_trap21: -_start_trap22: -_start_trap23: -_start_trap24: -_start_trap25: -_start_trap26: -_start_trap27: -_start_trap28: -_start_trap29: -_start_trap30: -_start_trap31: - -"#, -r#" -_start_trap: -"#, -#[cfg(feature="fix-sp")] -r#" - // move SP to some save place if it's pointing below the RAM - // otherwise we won't be able to do anything reasonable - // (since we don't have a working stack) - // - // most probably we will just print something and halt in this case - // we actually can't do anything else - csrw mscratch, t0 - la t0, _stack_end - bge sp, t0, 1f - - // use the reserved exception cause 14 to signal we detected a stack overflow - li t0, 14 - csrw mcause, t0 - - // set SP to the start of the stack - la sp, _stack_start - li t0, 4 // make sure stack start is in RAM - sub sp, sp, t0 - andi sp, sp, -16 // Force 16-byte alignment - - 1: - csrr t0, mscratch - // now SP is in RAM - continue -"#, -r#" - addi sp, sp, -40*4 - sw ra, 0*4(sp)"#, -#[cfg(feature="direct-vectoring")] //for the directly vectored handlers the above is stacked beforehand -r#" - la ra, _start_trap_rust_hal #this runs on exception, use regular fault handler +la ra, _start_trap_rust_hal /* this runs on exception, use regular fault handler */ _start_trap_direct: "#, r#" @@ -749,7 +711,7 @@ r#" add a0, sp, zero "#, - #[cfg(all(feature="interrupt-preemption", feature="direct-vectoring"))] //store current priority, set threshold, enable interrupts + // store current priority, set threshold, enable interrupts r#" addi sp, sp, -4 #build stack sw ra, 0(sp) @@ -758,15 +720,11 @@ r#" sw a0, 0(sp) #reuse old stack, a0 is return of _handle_priority addi a0, sp, 4 #the proper stack pointer is an argument to the HAL handler "#, - #[cfg(not(feature="direct-vectoring"))] //jump to HAL handler - r#" - jal ra, _start_trap_rust_hal - "#, - #[cfg(feature="direct-vectoring")] //jump to handler loaded in direct handler + // jump to handler loaded in direct handler r#" jalr ra, ra #jump to label loaded in _start_trapx "#, - #[cfg(all(feature="interrupt-preemption", feature="direct-vectoring"))] //restore threshold + // restore threshold r#" lw a0, 0(sp) #load stored priority jal ra, _restore_priority @@ -866,10 +824,8 @@ _vector_table: j _start_trap29 j _start_trap30 j _start_trap31 - .option pop "#, -#[cfg(feature="direct-vectoring")] r#" #this is required for the linking step, these symbols for in-use interrupts should always be overwritten by the user. .section .trap, "ax" diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml index f717140031f..c5549ea3ebc 100644 --- a/examples/.cargo/config.toml +++ b/examples/.cargo/config.toml @@ -27,5 +27,8 @@ rustflags = [ # "-C", "linker=rust-lld", ] +[env] +ESP_LOGLEVEL = "info" + [unstable] build-std = ["alloc", "core"] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index f7c0dcdd957..4d1af639549 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -23,9 +23,9 @@ embedded-hal-bus = "0.1.0" embedded-io-async = "0.6.1" esp-alloc = "0.3.0" esp-backtrace = { version = "0.11.1", features = ["exception-handler", "panic-handler", "println"] } -esp-hal = { version = "0.16.0", path = "../esp-hal" } +esp-hal = { version = "0.16.0", path = "../esp-hal", features = ["log"] } esp-hal-smartled = { version = "0.9.0", path = "../esp-hal-smartled", optional = true } -esp-println = "0.9.1" +esp-println = { version = "0.9.1", features = ["log"] } heapless = "0.8.0" hex-literal = "0.4.1" hmac = { version = "0.12.1", default-features = false } @@ -39,6 +39,7 @@ ssd1306 = "0.8.4" static_cell = { version = "2.0.0", features = ["nightly"] } usb-device = "0.3.2" usbd-serial = "0.2.1" +log = "0.4" [features] esp32 = ["esp-hal/esp32", "esp-backtrace/esp32", "esp-println/esp32", "esp-hal-smartled/esp32"] @@ -63,9 +64,6 @@ embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"] embassy-time-timg0 = ["esp-hal/embassy-time-timg0"] embassy-generic-timers = ["embassy-time/generic-queue-8"] -direct-vectoring = ["esp-hal/direct-vectoring"] -interrupt-preemption = ["esp-hal/interrupt-preemption"] - opsram-2m = ["esp-hal/opsram-2m"] psram-2m = ["esp-hal/psram-2m"] diff --git a/examples/src/bin/direct_vectoring.rs b/examples/src/bin/direct_vectoring.rs index ab09e5836f1..463ce9853ad 100644 --- a/examples/src/bin/direct_vectoring.rs +++ b/examples/src/bin/direct_vectoring.rs @@ -2,7 +2,6 @@ #![no_std] //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 -//% FEATURES: direct-vectoring use core::{arch::asm, cell::RefCell}; @@ -33,14 +32,13 @@ fn main() -> ! { let sw_int = system.software_interrupt_control; critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int)); + interrupt::enable_direct( + Interrupt::FROM_CPU_INTR0, + Priority::Priority3, + CpuInterrupt::Interrupt20, + ) + .unwrap(); unsafe { - interrupt::enable( - Interrupt::FROM_CPU_INTR0, - Priority::Priority3, - CpuInterrupt::Interrupt1, - ) - .unwrap(); - asm!( " csrrwi x0, 0x7e0, 1 #what to count, for cycles write 1 for instructions write 2 @@ -69,7 +67,7 @@ fn main() -> ! { } #[no_mangle] -fn cpu_int_1_handler() { +fn cpu_int_20_handler() { unsafe { asm!("csrrwi x0, 0x7e1, 0 #disable timer") } critical_section::with(|cs| { SWINT diff --git a/examples/src/bin/embassy_wait.rs b/examples/src/bin/embassy_wait.rs index 56a8c4c1151..9824007e9a0 100644 --- a/examples/src/bin/embassy_wait.rs +++ b/examples/src/bin/embassy_wait.rs @@ -33,7 +33,10 @@ async fn main(_spawner: Spawner) { embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] let mut input = io.pins.gpio0.into_pull_down_input(); + #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] + let mut input = io.pins.gpio9.into_pull_down_input(); loop { esp_println::println!("Waiting..."); diff --git a/examples/src/bin/interrupt_preemption.rs b/examples/src/bin/interrupt_preemption.rs index e80515c76c4..f9542ed0a49 100644 --- a/examples/src/bin/interrupt_preemption.rs +++ b/examples/src/bin/interrupt_preemption.rs @@ -4,9 +4,6 @@ //! priority. Should show higher-numbered software interrupts happening during //! the handling of lower-numbered ones. -//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 -//% FEATURES: interrupt-preemption - #![no_std] #![no_main] @@ -34,7 +31,7 @@ fn main() -> ! { interrupt::enable(Interrupt::FROM_CPU_INTR0, Priority::Priority1).unwrap(); interrupt::enable(Interrupt::FROM_CPU_INTR1, Priority::Priority2).unwrap(); interrupt::enable(Interrupt::FROM_CPU_INTR2, Priority::Priority2).unwrap(); - interrupt::enable(Interrupt::FROM_CPU_INTR3, Priority::Priority15).unwrap(); + interrupt::enable(Interrupt::FROM_CPU_INTR3, Priority::Priority3).unwrap(); // Raise mid priority interrupt. //