From 2b1dbd9299ebbf96ac45a4723637100886c50ca0 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 25 Jul 2022 22:52:52 +0100 Subject: [PATCH 1/9] RISCV interrupt vectoring - Adds support for vectoring peripheral interrupts to PAC handlers - Currently supports level interrupts with priorities from 1-15 - Updated the gpio interrupt example to reflect the new changes --- .vscode/settings.json | 8 +- esp-hal-common/src/interrupt/riscv.rs | 221 +++++++++++++++++++++++-- esp32c3-hal/Cargo.toml | 3 +- esp32c3-hal/examples/gpio_interrupt.rs | 36 +--- esp32c3-hal/ld/hal-defaults.x | 2 + esp32c3-hal/src/lib.rs | 3 + 6 files changed, 223 insertions(+), 50 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f7586734f6f..163ac1012c1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,13 +15,13 @@ // developing for. This will propagate to the `esp-hal-common` crate too, // as it is a dependency. Changing target/project requires reloading // Rust Analyzer. - "rust-analyzer.cargo.target": "xtensa-esp32-none-elf", - // "rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf", + // "rust-analyzer.cargo.target": "xtensa-esp32-none-elf", + "rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf", // "rust-analyzer.cargo.target": "xtensa-esp32s2-none-elf", // "rust-analyzer.cargo.target": "xtensa-esp32s3-none-elf", "rust-analyzer.linkedProjects": [ - "esp32-hal/Cargo.toml", - // "esp32c3-hal/Cargo.toml", + // "esp32-hal/Cargo.toml", + "esp32c3-hal/Cargo.toml", // "esp32s2-hal/Cargo.toml", // "esp32s3-hal/Cargo.toml", ], diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 158b9afbbce..1d3e0796f5e 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -1,6 +1,9 @@ use riscv::register::mcause; -use crate::{pac::Interrupt, Cpu}; +use crate::{ + pac::{self, Interrupt}, + Cpu, +}; // User code shouldn't usually take the mutable TrapFrame or the TrapFrame in // general. However this makes things like preemtive multitasking easier in @@ -50,6 +53,8 @@ pub enum InterruptKind { /// Enumeration of available CPU interrupts. /// It is possible to create a handler for each of the interrupts. (e.g. /// `interrupt3`) +#[repr(u32)] +#[derive(Debug, Copy, Clone)] pub enum CpuInterrupt { Interrupt1 = 1, Interrupt2, @@ -85,6 +90,7 @@ pub enum CpuInterrupt { } /// Interrupt priority levels. +#[repr(u8)] pub enum Priority { None, Priority1, @@ -104,21 +110,22 @@ pub enum Priority { Priority15, } -/// Enable and assign a peripheral interrupt to an CPU interrupt. -pub fn enable(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { - unsafe { - let interrupt_number = interrupt as isize; - let cpu_interrupt_number = which as isize; - let intr = &*crate::pac::INTERRUPT_CORE0::PTR; - let intr_map_base = intr.mac_intr_map.as_ptr(); - intr_map_base - .offset(interrupt_number) - .write_volatile(cpu_interrupt_number as u32); +/// 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; + let intr = &*crate::pac::INTERRUPT_CORE0::PTR; + let intr_map_base = intr.mac_intr_map.as_ptr(); + intr_map_base + .offset(interrupt_number) + .write_volatile(cpu_interrupt_number as u32); - // enable interrupt - intr.cpu_int_enable - .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); - } + // enable interrupt + intr.cpu_int_enable + .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); } /// Disable the given peripheral interrupt. @@ -187,6 +194,187 @@ pub fn get_status(_core: Cpu) -> u128 { } } +#[cfg(feature = "vectored")] +pub use vectored::*; + +#[cfg(feature = "vectored")] +mod vectored { + use super::*; + + // Setup interrupts 1-15 ready for vectoring (level only) + #[doc(hidden)] + pub(crate) unsafe fn init_vectoring() { + let intr = &*crate::pac::INTERRUPT_CORE0::PTR; + + for i in 1..=15 { + set_kind( + crate::get_core(), + core::mem::transmute(i), + InterruptKind::Level, + ); + set_priority( + crate::get_core(), + core::mem::transmute(i), + core::mem::transmute(i as u8), + ); + // enable CPU interrupt + intr.cpu_int_enable + .modify(|r, w| w.bits((1 << i) | r.bits())); + } + } + + /// Get the interrupts configured for the core + #[inline] + fn get_configured_interrupts(_core: Cpu) -> [u128; 15] { + unsafe { + let intr = &*crate::pac::INTERRUPT_CORE0::PTR; + let intr_map_base = intr.mac_intr_map.as_ptr(); + let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); + + let mut prios = [0u128; 15]; + + for i in 0..get_interrupt_count() { + let i = i as isize; + let cpu_interrupt = intr_map_base.offset(i).read_volatile(); + // safety: cast is safe because of repr(u32) + let cpu_interrupt: CpuInterrupt = core::mem::transmute(cpu_interrupt); + let prio = intr_prio_base + .offset(cpu_interrupt as isize) + .read_volatile(); + + prios[prio as usize] |= 1 << i; + } + + prios + } + } + + #[inline] + fn get_interrupt_count() -> usize { + cfg_if::cfg_if! { + if #[cfg(feature = "esp32c3")] { + 62 + } + } + } + + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + 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. + pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> { + if matches!(level, Priority::None) { + return Err(Error::InvalidInterruptPriority); + } + // TODO how do we handle edge interrupts? + unsafe { + let cpu_interrupt = core::mem::transmute(level as u8 as u32); + map(crate::get_core(), interrupt, cpu_interrupt); + } + Ok(()) + } + + unsafe fn handle_interrupts(cpu_intr: CpuInterrupt, context: &mut TrapFrame) { + let status = get_status(crate::get_core()); + clear(crate::get_core(), cpu_intr); + + let configured_interrupts = get_configured_interrupts(crate::get_core()); + let mut interrupt_mask = status & configured_interrupts[cpu_intr as usize]; + while interrupt_mask != 0 { + let interrupt_nr = interrupt_mask.trailing_zeros(); + // Interrupt::try_from can fail if interrupt already de-asserted: + // silently ignore + if let Ok(interrupt) = pac::Interrupt::try_from(interrupt_nr as u8) { + handle_interrupt(interrupt, context) + } else { + break; + } + interrupt_mask &= !(1u128 << interrupt_nr); + } + } + + unsafe fn handle_interrupt(interrupt: Interrupt, save_frame: &mut TrapFrame) { + extern "C" { + // defined in riscv-rt + fn DefaultHandler(); + } + let handler = pac::__EXTERNAL_INTERRUPTS[interrupt as usize]._handler; + if handler as *const _ == DefaultHandler as *const unsafe extern "C" fn() { + DefaultHandler(); + } else { + let handler: fn(&mut TrapFrame) = core::mem::transmute(handler); + handler(save_frame); + } + } + + #[no_mangle] + pub unsafe fn interrupt1(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt1, context) + } + + #[no_mangle] + pub unsafe fn interrupt2(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt2, context) + } + #[no_mangle] + pub unsafe fn interrupt3(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt3, context) + } + #[no_mangle] + pub unsafe fn interrupt4(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt4, context) + } + #[no_mangle] + pub unsafe fn interrupt5(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt5, context) + } + #[no_mangle] + pub unsafe fn interrupt6(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt6, context) + } + #[no_mangle] + pub unsafe fn interrupt7(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt7, context) + } + #[no_mangle] + pub unsafe fn interrupt8(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt8, context) + } + #[no_mangle] + pub unsafe fn interrupt9(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt9, context) + } + #[no_mangle] + pub unsafe fn interrupt10(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt10, context) + } + #[no_mangle] + pub unsafe fn interrupt11(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt11, context) + } + #[no_mangle] + pub unsafe fn interrupt12(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt12, context) + } + #[no_mangle] + pub unsafe fn interrupt13(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt13, context) + } + #[no_mangle] + pub unsafe fn interrupt14(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt14, context) + } + #[no_mangle] + pub unsafe fn interrupt15(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt15, context) + } +} + /// Registers saved in trap handler #[doc(hidden)] #[allow(missing_docs)] @@ -385,5 +573,8 @@ pub fn _setup_interrupts() { unsafe { let vec_table = &_vector_table_hal as *const _ as usize; riscv::register::mtvec::write(vec_table, riscv::register::mtvec::TrapMode::Vectored); + + #[cfg(feature = "vectored")] + crate::interrupt::init_vectoring(); }; } diff --git a/esp32c3-hal/Cargo.toml b/esp32c3-hal/Cargo.toml index 0eb5000de79..6f4053bea17 100644 --- a/esp32c3-hal/Cargo.toml +++ b/esp32c3-hal/Cargo.toml @@ -43,12 +43,13 @@ smart-leds = "0.3" esp-println = { version = "0.2.0", features = ["esp32c3"] } [features] -default = ["rt"] +default = ["rt", "vectored"] direct-boot = [] eh1 = ["esp-hal-common/eh1"] rt = ["riscv-rt"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] +vectored = ["esp-hal-common/vectored"] [[example]] name = "hello_rgb" diff --git a/esp32c3-hal/examples/gpio_interrupt.rs b/esp32c3-hal/examples/gpio_interrupt.rs index ae7f0a6d6af..67980438c13 100644 --- a/esp32c3-hal/examples/gpio_interrupt.rs +++ b/esp32c3-hal/examples/gpio_interrupt.rs @@ -6,7 +6,7 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use bare_metal::Mutex; use esp32c3_hal::{ @@ -14,18 +14,15 @@ use esp32c3_hal::{ gpio::{Gpio9, IO}, gpio_types::{Event, Input, Pin, PullDown}, interrupt, - pac::{self, Peripherals, UART0}, + pac::{self, Peripherals}, prelude::*, timer::TimerGroup, - Cpu, Delay, RtcCntl, - Serial, }; use panic_halt as _; use riscv_rt::entry; -static mut SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); static mut BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); #[entry] @@ -41,7 +38,6 @@ fn main() -> ! { let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); let mut wdt1 = timer_group1.wdt; - let serial0 = Serial::new(peripherals.UART0); rtc_cntl.set_super_wdt_enable(false); rtc_cntl.set_wdt_enable(false); @@ -57,25 +53,10 @@ fn main() -> ! { button.listen(Event::FallingEdge); riscv::interrupt::free(|_cs| unsafe { - SERIAL.get_mut().replace(Some(serial0)); BUTTON.get_mut().replace(Some(button)); }); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::GPIO, - interrupt::CpuInterrupt::Interrupt3, - ); - interrupt::set_kind( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt3, - interrupt::InterruptKind::Level, - ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt3, - interrupt::Priority::Priority1, - ); + interrupt::enable(pac::Interrupt::GPIO, interrupt::Priority::Priority3).unwrap(); unsafe { riscv::interrupt::enable(); @@ -88,17 +69,12 @@ fn main() -> ! { } } -#[no_mangle] -pub fn interrupt3() { +#[interrupt] +fn GPIO() { riscv::interrupt::free(|cs| unsafe { - let mut serial = SERIAL.borrow(*cs).borrow_mut(); - let serial = serial.as_mut().unwrap(); let mut button = BUTTON.borrow(*cs).borrow_mut(); let button = button.as_mut().unwrap(); - - writeln!(serial, "Interrupt").ok(); - - interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt3); + esp_println::println!("GPIO interrupt"); button.clear_interrupt(); }); } diff --git a/esp32c3-hal/ld/hal-defaults.x b/esp32c3-hal/ld/hal-defaults.x index 469d127923f..a7bbdbb0bb7 100644 --- a/esp32c3-hal/ld/hal-defaults.x +++ b/esp32c3-hal/ld/hal-defaults.x @@ -29,3 +29,5 @@ PROVIDE(interrupt28 = DefaultHandler); PROVIDE(interrupt29 = DefaultHandler); PROVIDE(interrupt30 = DefaultHandler); PROVIDE(interrupt31 = DefaultHandler); + +INCLUDE "device.x" diff --git a/esp32c3-hal/src/lib.rs b/esp32c3-hal/src/lib.rs index 9abecd22fe4..f58a1fdaf88 100644 --- a/esp32c3-hal/src/lib.rs +++ b/esp32c3-hal/src/lib.rs @@ -310,3 +310,6 @@ pub fn mp_hook() -> bool { fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 { int_enable as u8 | ((nmi_enable as u8) << 1) } + +#[no_mangle] +extern "C" fn DefaultHandler(_interrupt: pac::Interrupt) {} From a61b6556e78a870d24ad26941e7e6b45c61390c5 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Mon, 25 Jul 2022 22:55:40 +0100 Subject: [PATCH 2/9] remove .vscode files --- .vscode/settings.json | 28 ---------------------------- esp32c3-hal/.vscode/settings.json | 16 ---------------- 2 files changed, 44 deletions(-) delete mode 100644 .vscode/settings.json delete mode 100644 esp32c3-hal/.vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 163ac1012c1..00000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "editor.formatOnSave": true, - "rust-analyzer.cargo.buildScripts.enable": true, - "rust-analyzer.cargo.noDefaultFeatures": true, - "rust-analyzer.checkOnSave.allTargets": false, - "rust-analyzer.imports.granularity.enforce": true, - "rust-analyzer.imports.granularity.group": "crate", - "rust-analyzer.procMacro.attributes.enable": false, - "rust-analyzer.procMacro.enable": true, - // ----------------------------------------------------------------------- - // Since we have to handle multiple toolchains AND multiple targets, we - // we need to give Rust Analyzer some directions. - // - // Enable ONE target and linked project based on which chip you are - // developing for. This will propagate to the `esp-hal-common` crate too, - // as it is a dependency. Changing target/project requires reloading - // Rust Analyzer. - // "rust-analyzer.cargo.target": "xtensa-esp32-none-elf", - "rust-analyzer.cargo.target": "riscv32imc-unknown-none-elf", - // "rust-analyzer.cargo.target": "xtensa-esp32s2-none-elf", - // "rust-analyzer.cargo.target": "xtensa-esp32s3-none-elf", - "rust-analyzer.linkedProjects": [ - // "esp32-hal/Cargo.toml", - "esp32c3-hal/Cargo.toml", - // "esp32s2-hal/Cargo.toml", - // "esp32s3-hal/Cargo.toml", - ], -} \ No newline at end of file diff --git a/esp32c3-hal/.vscode/settings.json b/esp32c3-hal/.vscode/settings.json deleted file mode 100644 index e0839ba9dec..00000000000 --- a/esp32c3-hal/.vscode/settings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "rust-analyzer.cargo.features": [], - "rust-analyzer.cargo.allFeatures": false, - "editor.formatOnSave": true, - "rust-analyzer.checkOnSave.allTargets": false, - "rust-analyzer.checkOnSave.allFeatures": false, - "rust-analyzer.checkOnSave.overrideCommand": [ - "cargo", - "check", - "--message-format=json", - "-Z", - "build-std=core", - "--examples" - ], - "rust-analyzer.cargo.buildScripts.enable": false -} \ No newline at end of file From acf75f41da3184e305bae92c4b10743103cc48d5 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 10:52:14 +0100 Subject: [PATCH 3/9] Support vectored edge interrupts This is as simple as making sure we clear the CPU interrupt whenever we receive one. This also documents further what APIs are safe to call when the `vectored` feature is enabled. --- esp-hal-common/src/interrupt/riscv.rs | 31 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 1d3e0796f5e..cafca78e2f4 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -139,6 +139,9 @@ pub fn disable(_core: Cpu, interrupt: Interrupt) { } /// Set the interrupt kind (i.e. level or edge) of an CPU interrupt +/// +/// This is safe to call when the `vectored` feature is enabled. The vectored +/// interrupt handler will take care of clearing edge interrupt bits. pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) { unsafe { let intr = &*crate::pac::INTERRUPT_CORE0::PTR; @@ -157,16 +160,18 @@ pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) { } /// Set the priority level of an CPU interrupt -pub fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) { - unsafe { - let intr = &*crate::pac::INTERRUPT_CORE0::PTR; - let cpu_interrupt_number = which as isize; - let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); +/// +/// Great care must be taken when using the `vectored` feature (enabled by +/// default). Avoid changing the priority of interrupts 1 - 15 when interrupt +/// vectoring is enabled. +pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) { + let intr = &*crate::pac::INTERRUPT_CORE0::PTR; + let cpu_interrupt_number = which as isize; + let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); - intr_prio_base - .offset(cpu_interrupt_number as isize) - .write_volatile(priority as u32); - } + intr_prio_base + .offset(cpu_interrupt_number as isize) + .write_volatile(priority as u32); } /// Clear a CPU interrupt @@ -217,7 +222,7 @@ mod vectored { core::mem::transmute(i), core::mem::transmute(i as u8), ); - // enable CPU interrupt + // enable the CPU interrupt intr.cpu_int_enable .modify(|r, w| w.bits((1 << i) | r.bits())); } @@ -271,7 +276,6 @@ mod vectored { if matches!(level, Priority::None) { return Err(Error::InvalidInterruptPriority); } - // TODO how do we handle edge interrupts? unsafe { let cpu_interrupt = core::mem::transmute(level as u8 as u32); map(crate::get_core(), interrupt, cpu_interrupt); @@ -281,6 +285,9 @@ mod vectored { unsafe fn handle_interrupts(cpu_intr: CpuInterrupt, context: &mut TrapFrame) { let status = get_status(crate::get_core()); + + // this has no effect on level interrupts, but the interrupt may be an edge one + // so we clear it anyway clear(crate::get_core(), cpu_intr); let configured_interrupts = get_configured_interrupts(crate::get_core()); @@ -291,8 +298,6 @@ mod vectored { // silently ignore if let Ok(interrupt) = pac::Interrupt::try_from(interrupt_nr as u8) { handle_interrupt(interrupt, context) - } else { - break; } interrupt_mask &= !(1u128 << interrupt_nr); } From 3331204640eac13a9cf7380c50947470b8762817 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 11:28:31 +0100 Subject: [PATCH 4/9] fix all examples to use vectoring --- esp32c3-hal/examples/serial_interrupts.rs | 18 ++--- esp32c3-hal/examples/systimer.rs | 83 ++++++----------------- esp32c3-hal/examples/timer_interrupt.rs | 64 +++-------------- 3 files changed, 34 insertions(+), 131 deletions(-) diff --git a/esp32c3-hal/examples/serial_interrupts.rs b/esp32c3-hal/examples/serial_interrupts.rs index 6d7214ff46b..fd5821465bb 100644 --- a/esp32c3-hal/examples/serial_interrupts.rs +++ b/esp32c3-hal/examples/serial_interrupts.rs @@ -56,21 +56,12 @@ fn main() -> ! { SERIAL.get_mut().replace(Some(serial0)); }); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::UART0, - interrupt::CpuInterrupt::Interrupt3, - ); + interrupt::enable(pac::Interrupt::UART0, interrupt::Priority::Priority1).unwrap(); interrupt::set_kind( Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt3, + interrupt::CpuInterrupt::Interrupt1, // Interrupt 1 handles priority one interrupts interrupt::InterruptKind::Edge, ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt3, - interrupt::Priority::Priority1, - ); unsafe { riscv::interrupt::enable(); @@ -88,8 +79,8 @@ fn main() -> ! { } } -#[no_mangle] -pub fn interrupt3() { +#[interrupt] +fn UART0() { riscv::interrupt::free(|cs| unsafe { let mut serial = SERIAL.borrow(*cs).borrow_mut(); let serial = serial.as_mut().unwrap(); @@ -110,6 +101,5 @@ pub fn interrupt3() { serial.reset_at_cmd_interrupt(); serial.reset_rx_fifo_full_interrupt(); - interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt3); }); } diff --git a/esp32c3-hal/examples/systimer.rs b/esp32c3-hal/examples/systimer.rs index dfd60cca1a2..172d7e82873 100644 --- a/esp32c3-hal/examples/systimer.rs +++ b/esp32c3-hal/examples/systimer.rs @@ -4,24 +4,22 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use bare_metal::Mutex; use esp32c3_hal::{ clock::ClockControl, interrupt, - pac::{self, Peripherals, UART0}, + pac::{self, Peripherals}, prelude::*, systimer::{Alarm, SystemTimer, Target}, timer::TimerGroup, Cpu, RtcCntl, - Serial, }; use panic_halt as _; use riscv_rt::entry; -static mut SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); static mut ALARM0: Mutex>>> = Mutex::new(RefCell::new(None)); static mut ALARM1: Mutex>>> = Mutex::new(RefCell::new(None)); static mut ALARM2: Mutex>>> = Mutex::new(RefCell::new(None)); @@ -40,18 +38,14 @@ fn main() -> ! { let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); let mut wdt1 = timer_group1.wdt; - let mut serial0 = Serial::new(peripherals.UART0); - rtc_cntl.set_super_wdt_enable(false); rtc_cntl.set_wdt_enable(false); wdt0.disable(); wdt1.disable(); - writeln!(serial0, "SYSTIMER Demo start!").ok(); - let syst = SystemTimer::new(peripherals.SYSTIMER); - writeln!(serial0, "SYSTIMER Current value = {}", SystemTimer::now()).ok(); + esp_println::println!("SYSTIMER Current value = {}", SystemTimer::now()); let alarm0 = syst.alarm0; alarm0.set_target(40_000_000); @@ -66,53 +60,22 @@ fn main() -> ! { alarm2.enable_interrupt(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET0, - interrupt::CpuInterrupt::Interrupt1, - ); + interrupt::Priority::Priority1, + ) + .unwrap(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET1, - interrupt::CpuInterrupt::Interrupt2, - ); + interrupt::Priority::Priority1, + ) + .unwrap(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET2, - interrupt::CpuInterrupt::Interrupt3, - ); - interrupt::set_kind( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt1, - interrupt::InterruptKind::Level, - ); - interrupt::set_kind( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt2, - interrupt::InterruptKind::Level, - ); - interrupt::set_kind( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt3, - interrupt::InterruptKind::Level, - ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt1, - interrupt::Priority::Priority1, - ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt2, - interrupt::Priority::Priority1, - ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt3, interrupt::Priority::Priority1, - ); + ) + .unwrap(); riscv::interrupt::free(|_cs| unsafe { - SERIAL.get_mut().replace(Some(serial0)); ALARM0.get_mut().replace(Some(alarm0)); ALARM1.get_mut().replace(Some(alarm1)); ALARM2.get_mut().replace(Some(alarm2)); @@ -125,12 +88,10 @@ fn main() -> ! { loop {} } -#[no_mangle] -pub fn interrupt1() { +#[interrupt] +fn SYSTIMER_TARGET0() { riscv::interrupt::free(|cs| unsafe { - let mut serial = SERIAL.borrow(*cs).borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt 1 = {}", SystemTimer::now()).ok(); + esp_println::println!("Interrupt 1 = {}", SystemTimer::now()); let mut alarm = ALARM0.borrow(*cs).borrow_mut(); let alarm = alarm.as_mut().unwrap(); @@ -140,12 +101,10 @@ pub fn interrupt1() { }); } -#[no_mangle] -pub fn interrupt2() { +#[interrupt] +fn SYSTIMER_TARGET1() { riscv::interrupt::free(|cs| unsafe { - let mut serial = SERIAL.borrow(*cs).borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt 2 = {}", SystemTimer::now()).ok(); + esp_println::println!("Interrupt 2 = {}", SystemTimer::now()); let mut alarm = ALARM1.borrow(*cs).borrow_mut(); let alarm = alarm.as_mut().unwrap(); @@ -155,12 +114,10 @@ pub fn interrupt2() { }); } -#[no_mangle] -pub fn interrupt3() { +#[interrupt] +fn SYSTIMER_TARGET2() { riscv::interrupt::free(|cs| unsafe { - let mut serial = SERIAL.borrow(*cs).borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt 3 = {}", SystemTimer::now()).ok(); + esp_println::println!("Interrupt 3 = {}", SystemTimer::now()); let mut alarm = ALARM2.borrow(*cs).borrow_mut(); let alarm = alarm.as_mut().unwrap(); diff --git a/esp32c3-hal/examples/timer_interrupt.rs b/esp32c3-hal/examples/timer_interrupt.rs index 81f398b5429..8253d61641f 100644 --- a/esp32c3-hal/examples/timer_interrupt.rs +++ b/esp32c3-hal/examples/timer_interrupt.rs @@ -5,24 +5,21 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use bare_metal::Mutex; use esp32c3_hal::{ clock::ClockControl, interrupt, - pac::{self, Peripherals, TIMG0, TIMG1, UART0}, + pac::{self, Peripherals, TIMG0, TIMG1}, prelude::*, timer::{Timer0, TimerGroup}, - Cpu, RtcCntl, - Serial, }; use esp_hal_common::Timer; use panic_halt as _; use riscv_rt::entry; -static mut SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); static mut TIMER0: Mutex>>>> = Mutex::new(RefCell::new(None)); static mut TIMER1: Mutex>>>> = Mutex::new(RefCell::new(None)); @@ -42,53 +39,20 @@ fn main() -> ! { let mut timer1 = timer_group1.timer0; let mut wdt1 = timer_group1.wdt; - let serial0 = Serial::new(peripherals.UART0); - rtc_cntl.set_super_wdt_enable(false); rtc_cntl.set_wdt_enable(false); wdt0.disable(); wdt1.disable(); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt1, - ); - interrupt::set_kind( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt1, - interrupt::InterruptKind::Level, - ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt1, - interrupt::Priority::Priority1, - ); - + interrupt::enable(pac::Interrupt::TG0_T0_LEVEL, interrupt::Priority::Priority1).unwrap(); timer0.start(500u64.millis()); timer0.listen(); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt11, - ); - interrupt::set_kind( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt11, - interrupt::InterruptKind::Level, - ); - interrupt::set_priority( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt11, - interrupt::Priority::Priority1, - ); - + interrupt::enable(pac::Interrupt::TG1_T0_LEVEL, interrupt::Priority::Priority1).unwrap(); timer1.start(1u64.secs()); timer1.listen(); riscv::interrupt::free(|_cs| unsafe { - SERIAL.get_mut().replace(Some(serial0)); TIMER0.get_mut().replace(Some(timer0)); TIMER1.get_mut().replace(Some(timer1)); }); @@ -100,36 +64,28 @@ fn main() -> ! { loop {} } -#[no_mangle] -pub fn interrupt1() { +#[interrupt] +fn TG0_T0_LEVEL() { riscv::interrupt::free(|cs| unsafe { - let mut serial = SERIAL.borrow(*cs).borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt 1").ok(); + esp_println::println!("Interrupt 1"); let mut timer0 = TIMER0.borrow(*cs).borrow_mut(); let timer0 = timer0.as_mut().unwrap(); - interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt1); timer0.clear_interrupt(); - timer0.start(500u64.millis()); }); } -#[no_mangle] -pub fn interrupt11() { +#[interrupt] +fn TG1_T0_LEVEL() { riscv::interrupt::free(|cs| unsafe { - let mut serial = SERIAL.borrow(*cs).borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt 11").ok(); + esp_println::println!("Interrupt 11"); let mut timer1 = TIMER1.borrow(*cs).borrow_mut(); let timer1 = timer1.as_mut().unwrap(); - interrupt::clear(Cpu::ProCpu, interrupt::CpuInterrupt::Interrupt11); timer1.clear_interrupt(); - timer1.start(1u64.secs()); }); } From a8d09c42f2b8898cadfcfddd40be33a2c2d689e4 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 11:45:56 +0100 Subject: [PATCH 5/9] doc & cleanup --- esp-hal-common/src/interrupt/riscv.rs | 28 ++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index cafca78e2f4..85e9e4e651b 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -1,3 +1,15 @@ +//! Interrupt handling - RISCV +//! +//! When the `vectored` feature is enabled, CPU interrupts 1 through 15 are +//! reserved for each of the possible interrupt priorities. +//! +//! ```rust +//! interrupt1() => Priority::Priority1 +//! interrupt2() => Priority::Priority2 +//! ... +//! interrupt15() => Priority::Priority15 +//! ``` + use riscv::register::mcause; use crate::{ @@ -122,8 +134,12 @@ pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { intr_map_base .offset(interrupt_number) .write_volatile(cpu_interrupt_number as u32); +} - // enable interrupt +/// Enable a CPU interrupt +pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { + let cpu_interrupt_number = which as isize; + let intr = &*crate::pac::INTERRUPT_CORE0::PTR; intr.cpu_int_enable .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); } @@ -206,11 +222,9 @@ pub use vectored::*; mod vectored { use super::*; - // Setup interrupts 1-15 ready for vectoring (level only) + // Setup interrupts 1-15 ready for vectoring #[doc(hidden)] pub(crate) unsafe fn init_vectoring() { - let intr = &*crate::pac::INTERRUPT_CORE0::PTR; - for i in 1..=15 { set_kind( crate::get_core(), @@ -222,9 +236,7 @@ mod vectored { core::mem::transmute(i), core::mem::transmute(i as u8), ); - // enable the CPU interrupt - intr.cpu_int_enable - .modify(|r, w| w.bits((1 << i) | r.bits())); + enable_cpu_interrupt(core::mem::transmute(i)); } } @@ -263,6 +275,7 @@ mod vectored { } } + /// Interrupt Error #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { InvalidInterruptPriority, @@ -279,6 +292,7 @@ mod vectored { unsafe { let cpu_interrupt = core::mem::transmute(level as u8 as u32); map(crate::get_core(), interrupt, cpu_interrupt); + enable_cpu_interrupt(cpu_interrupt); } Ok(()) } From 1897dc372ea303af334a421d11725455cb3b2691 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 11:49:48 +0100 Subject: [PATCH 6/9] run handlers from ram --- esp-hal-common/src/interrupt/riscv.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 85e9e4e651b..208f2385b9b 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -191,6 +191,7 @@ pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) } /// Clear a CPU interrupt +#[inline] pub fn clear(_core: Cpu, which: CpuInterrupt) { unsafe { let cpu_interrupt_number = which as isize; @@ -201,6 +202,7 @@ pub fn clear(_core: Cpu, which: CpuInterrupt) { } /// Get status of peripheral interrupts +#[inline] pub fn get_status(_core: Cpu) -> u128 { unsafe { ((*crate::pac::INTERRUPT_CORE0::PTR) @@ -220,6 +222,8 @@ pub use vectored::*; #[cfg(feature = "vectored")] mod vectored { + use procmacros::ram; + use super::*; // Setup interrupts 1-15 ready for vectoring @@ -297,6 +301,7 @@ mod vectored { Ok(()) } + #[ram] unsafe fn handle_interrupts(cpu_intr: CpuInterrupt, context: &mut TrapFrame) { let status = get_status(crate::get_core()); @@ -317,6 +322,7 @@ mod vectored { } } + #[ram] unsafe fn handle_interrupt(interrupt: Interrupt, save_frame: &mut TrapFrame) { extern "C" { // defined in riscv-rt @@ -332,63 +338,78 @@ mod vectored { } #[no_mangle] + #[ram] pub unsafe fn interrupt1(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt1, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt2(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt2, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt3(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt3, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt4(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt4, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt5(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt5, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt6(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt6, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt7(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt7, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt8(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt8, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt9(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt9, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt10(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt10, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt11(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt11, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt12(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt12, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt13(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt13, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt14(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt14, context) } #[no_mangle] + #[ram] pub unsafe fn interrupt15(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt15, context) } From 8375677432f218363919ca47026ceaca04aa3c8d Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 11:54:23 +0100 Subject: [PATCH 7/9] make xtensa::interrupt::vectored private, we rexport public items --- esp-hal-common/src/interrupt/xtensa.rs | 2 +- esp32-hal/examples/gpio_interrupt.rs | 2 +- esp32s2-hal/examples/gpio_interrupt.rs | 2 +- esp32s3-hal/examples/gpio_interrupt.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/esp-hal-common/src/interrupt/xtensa.rs b/esp-hal-common/src/interrupt/xtensa.rs index 5e7bb38afc6..6122eb4d2ec 100644 --- a/esp-hal-common/src/interrupt/xtensa.rs +++ b/esp-hal-common/src/interrupt/xtensa.rs @@ -184,7 +184,7 @@ unsafe fn core1_interrupt_peripheral() -> *const crate::pac::interrupt_core1::Re pub use vectored::*; #[cfg(feature = "vectored")] -pub mod vectored { +mod vectored { use procmacros::ram; use super::*; diff --git a/esp32-hal/examples/gpio_interrupt.rs b/esp32-hal/examples/gpio_interrupt.rs index b8ee22de53b..ca8cb31b906 100644 --- a/esp32-hal/examples/gpio_interrupt.rs +++ b/esp32-hal/examples/gpio_interrupt.rs @@ -54,7 +54,7 @@ fn main() -> ! { interrupt::enable( pac::Interrupt::GPIO, - interrupt::vectored::Priority::Priority2, + interrupt::Priority::Priority2, ) .unwrap(); diff --git a/esp32s2-hal/examples/gpio_interrupt.rs b/esp32s2-hal/examples/gpio_interrupt.rs index 4d6018f46d1..51616cf73da 100644 --- a/esp32s2-hal/examples/gpio_interrupt.rs +++ b/esp32s2-hal/examples/gpio_interrupt.rs @@ -54,7 +54,7 @@ fn main() -> ! { interrupt::enable( pac::Interrupt::GPIO, - interrupt::vectored::Priority::Priority2, + interrupt::Priority::Priority2, ) .unwrap(); diff --git a/esp32s3-hal/examples/gpio_interrupt.rs b/esp32s3-hal/examples/gpio_interrupt.rs index a98138b1622..f26cbbcc5aa 100644 --- a/esp32s3-hal/examples/gpio_interrupt.rs +++ b/esp32s3-hal/examples/gpio_interrupt.rs @@ -54,7 +54,7 @@ fn main() -> ! { interrupt::enable( pac::Interrupt::GPIO, - interrupt::vectored::Priority::Priority2, + interrupt::Priority::Priority2, ) .unwrap(); From 38beccd6dcd00c78aab007643e2db5cfee9f39f4 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 13:23:45 +0100 Subject: [PATCH 8/9] fix default handlers --- esp-hal-common/src/interrupt/riscv.rs | 9 +++++---- esp-hal-common/src/interrupt/xtensa.rs | 6 +++--- esp32-hal/src/lib.rs | 5 ++++- esp32c3-hal/src/lib.rs | 2 +- esp32s2-hal/src/lib.rs | 5 ++++- esp32s3-hal/src/lib.rs | 5 ++++- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 208f2385b9b..21c963719f4 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -325,12 +325,12 @@ mod vectored { #[ram] unsafe fn handle_interrupt(interrupt: Interrupt, save_frame: &mut TrapFrame) { extern "C" { - // defined in riscv-rt - fn DefaultHandler(); + // defined in each hal + fn EspDefaultHandler(); } let handler = pac::__EXTERNAL_INTERRUPTS[interrupt as usize]._handler; - if handler as *const _ == DefaultHandler as *const unsafe extern "C" fn() { - DefaultHandler(); + if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() { + EspDefaultHandler(); } else { let handler: fn(&mut TrapFrame) = core::mem::transmute(handler); handler(save_frame); @@ -462,6 +462,7 @@ pub struct TrapFrame { #[export_name = "_start_trap_rust_hal"] pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { extern "C" { + // defined in riscv-rt pub fn DefaultHandler(); } diff --git a/esp-hal-common/src/interrupt/xtensa.rs b/esp-hal-common/src/interrupt/xtensa.rs index 6122eb4d2ec..5826db7d280 100644 --- a/esp-hal-common/src/interrupt/xtensa.rs +++ b/esp-hal-common/src/interrupt/xtensa.rs @@ -429,12 +429,12 @@ mod vectored { unsafe fn handle_interrupt(level: u32, interrupt: Interrupt, save_frame: &mut Context) { extern "C" { // defined in each hal - fn DefaultHandler(level: u32, interrupt: Interrupt); + fn EspDefaultHandler(level: u32, interrupt: Interrupt); } let handler = pac::__INTERRUPTS[interrupt.number() as usize]._handler; - if handler as *const _ == DefaultHandler as *const unsafe extern "C" fn() { - DefaultHandler(level, interrupt); + if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() { + EspDefaultHandler(level, interrupt); } else { let handler: fn(&mut Context) = core::mem::transmute(handler); handler(save_frame); diff --git a/esp32-hal/src/lib.rs b/esp32-hal/src/lib.rs index 86641cc49a0..c8101b90941 100644 --- a/esp32-hal/src/lib.rs +++ b/esp32-hal/src/lib.rs @@ -36,7 +36,10 @@ pub mod analog { } #[no_mangle] -extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} +extern "C" fn EspDefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} + +#[no_mangle] +extern "C" fn DefaultHandler() {} /// Function initializes ESP32 specific memories (RTC slow and fast) and /// then calls original Reset function diff --git a/esp32c3-hal/src/lib.rs b/esp32c3-hal/src/lib.rs index f58a1fdaf88..475076ee9b3 100644 --- a/esp32c3-hal/src/lib.rs +++ b/esp32c3-hal/src/lib.rs @@ -312,4 +312,4 @@ fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 { } #[no_mangle] -extern "C" fn DefaultHandler(_interrupt: pac::Interrupt) {} +extern "C" fn EspDefaultHandler(_interrupt: pac::Interrupt) {} diff --git a/esp32s2-hal/src/lib.rs b/esp32s2-hal/src/lib.rs index 55314dc976a..b9218fb4d94 100644 --- a/esp32s2-hal/src/lib.rs +++ b/esp32s2-hal/src/lib.rs @@ -36,7 +36,10 @@ pub mod analog { } #[no_mangle] -extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} +extern "C" fn EspDefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} + +#[no_mangle] +extern "C" fn DefaultHandler() {} /// Function initializes ESP32 specific memories (RTC slow and fast) and /// then calls original Reset function diff --git a/esp32s3-hal/src/lib.rs b/esp32s3-hal/src/lib.rs index 4c7f3beaae8..eb1af2c02bb 100644 --- a/esp32s3-hal/src/lib.rs +++ b/esp32s3-hal/src/lib.rs @@ -34,7 +34,10 @@ pub use self::gpio::IO; pub mod gpio; #[no_mangle] -extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} +extern "C" fn EspDefaultHandler(_level: u32, _interrupt: pac::Interrupt) {} + +#[no_mangle] +extern "C" fn DefaultHandler() {} #[cfg(all(feature = "rt", feature = "direct-boot"))] #[doc(hidden)] From c06919a945f072acdeea2fbb3d6faec291fe07ef Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 26 Jul 2022 17:17:26 +0100 Subject: [PATCH 9/9] pass interrupt into EspDefaultHandler --- esp-hal-common/src/interrupt/riscv.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 21c963719f4..805a556eca4 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -326,11 +326,11 @@ mod vectored { unsafe fn handle_interrupt(interrupt: Interrupt, save_frame: &mut TrapFrame) { extern "C" { // defined in each hal - fn EspDefaultHandler(); + fn EspDefaultHandler(interrupt: Interrupt); } let handler = pac::__EXTERNAL_INTERRUPTS[interrupt as usize]._handler; if handler as *const _ == EspDefaultHandler as *const unsafe extern "C" fn() { - EspDefaultHandler(); + EspDefaultHandler(interrupt); } else { let handler: fn(&mut TrapFrame) = core::mem::transmute(handler); handler(save_frame);