//! Interrupt Test //! //! "Disabled" for now - see https://github.com/esp-rs/esp-hal/pull/1635#issuecomment-2137405251 //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 //% FEATURES: unstable #![no_std] #![no_main] use core::{arch::asm, cell::RefCell}; use critical_section::Mutex; use esp_hal::{ clock::CpuClock, interrupt::{ self, software::{SoftwareInterrupt, SoftwareInterruptControl}, CpuInterrupt, Priority, }, peripherals::Interrupt, }; use hil_test as _; static SWINT0: Mutex>>> = Mutex::new(RefCell::new(None)); #[allow(unused)] // TODO: Remove attribute when interrupt latency test re-enabled struct Context { sw0_trigger_addr: u32, } #[no_mangle] fn interrupt20() { unsafe { asm!("csrrwi x0, 0x7e1, 0 #disable timer") } critical_section::with(|cs| { SWINT0.borrow_ref(cs).as_ref().unwrap().reset(); }); let mut perf_counter: u32 = 0; unsafe { asm!( " csrr {x}, 0x7e2 ", options(nostack), x = inout(reg) perf_counter, ) }; defmt::info!("Performance counter:{}", perf_counter); // TODO these values should be adjusted to catch smaller regressions cfg_if::cfg_if! { if #[cfg(any(feature = "esp32c3", feature = "esp32c2"))] { assert!(perf_counter < 1100); } else { assert!(perf_counter < 750); } } } #[cfg(test)] #[embedded_test::tests(default_timeout = 3)] mod tests { use super::*; #[init] fn init() -> Context { let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); cfg_if::cfg_if! { if #[cfg(any(feature = "esp32c6", feature = "esp32h2"))] { let cpu_intr = &peripherals.INTPRI; } else { let cpu_intr = &peripherals.SYSTEM; } } let sw0_trigger_addr = cpu_intr.cpu_intr_from_cpu_0() as *const _ as u32; critical_section::with(|cs| { SWINT0 .borrow_ref_mut(cs) .replace(sw_ints.software_interrupt0) }); interrupt::enable_direct( Interrupt::FROM_CPU_INTR0, Priority::Priority3, CpuInterrupt::Interrupt20, ) .unwrap(); Context { sw0_trigger_addr } } #[test] #[rustfmt::skip] fn interrupt_latency(_ctx: Context) { // unsafe { // asm!( // " // csrrwi x0, 0x7e0, 1 #what to count, for cycles write 1 for instructions write 2 // csrrwi x0, 0x7e1, 0 #disable counter // csrrwi x0, 0x7e2, 0 #reset counter // " // ); // } // // interrupt is raised from assembly for max timer granularity. // unsafe { // asm!( // " // li {bit}, 1 # Flip flag (bit 0) // csrrwi x0, 0x7e1, 1 # enable timer // sw {bit}, 0({addr}) # trigger FROM_CPU_INTR0 // ", // options(nostack), // addr = in(reg) ctx.sw0_trigger_addr, // bit = out(reg) _, // ) // } } }