diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7471c55abb3..bfaf5b9b620 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,25 +54,44 @@ jobs: # The `hello_rgb` example requires the `smartled` feature to be enabled args: -Zbuild-std=core --examples --manifest-path=${{ matrix.chip }}-hal/Cargo.toml --target=xtensa-${{ matrix.chip }}-none-elf --features=smartled - clippy: - name: Clippy + clippy-riscv: + name: Run clippy on RISC-V builds runs-on: ubuntu-latest strategy: fail-fast: false matrix: - chip: [esp32, esp32c3, esp32s2, esp32s3] + toolchain: [stable, nightly] steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: profile: minimal - toolchain: nightly - default: true + target: riscv32imc-unknown-none-elf + toolchain: ${{ matrix.toolchain }} components: clippy + default: true + - uses: Swatinem/rust-cache@v1 + - uses: actions-rs/cargo@v1 + with: + command: clippy + args: --manifest-path=esp32c3-hal/Cargo.toml --target=riscv32imc-unknown-none-elf -- --no-deps -D warnings --A clippy::too-many-arguments --A clippy::module-inception + + clippy-xtensa: + name: Run clippy on Xtensa builds + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + chip: [esp32, esp32s2, esp32s3] + steps: + - uses: actions/checkout@v2 + - uses: esp-rs/xtensa-toolchain@v1.2 + with: + default: true + ldproxy: false + buildtargets: ${{ matrix.chip }} - uses: Swatinem/rust-cache@v1 - uses: actions-rs/cargo@v1 with: command: clippy - # I find `clippy::too-many-arguments` to be rather rather arbitrary. - # As for `clippy::module-inception`... don't tell me what to do ;) - args: --manifest-path=${{ matrix.chip }}-hal/Cargo.toml -- --no-deps -D warnings --A clippy::too-many-arguments --A clippy::module-inception + args: -Zbuild-std=core --manifest-path=${{ matrix.chip }}-hal/Cargo.toml --target=xtensa-${{ matrix.chip }}-none-elf -- --no-deps -D warnings --A clippy::too-many-arguments --A clippy::module-inception diff --git a/.vscode/settings.json b/.vscode/settings.json index 7bb978cce08..f7586734f6f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,17 +1,12 @@ { "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. @@ -20,16 +15,14 @@ // 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", ], -} +} \ No newline at end of file diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index ad5559fb781..692bf062242 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -38,27 +38,21 @@ smart-leds-trait = { version = "0.2.1", optional = true } # Each supported device MUST have its PAC included below along with a # corresponding feature. We rename the PAC packages because we cannot # have dependencies and features with the same names. -# -# Please note: for now we use git-dependencies from the `with_source` branch however we pin the dependency -# to specific commits. -esp32_pac = { package = "esp32", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true } -esp32c3_pac = { package = "esp32c3", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true } -esp32s2_pac = { package = "esp32s2", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true } -esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.git", rev = "148dbb843cba3c311364aa994b8f3f773d15b04f", optional = true } +esp32_pac = { package = "esp32", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true } +esp32c3_pac = { package = "esp32c3", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true } +esp32s2_pac = { package = "esp32s2", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true } +esp32s3_pac = { package = "esp32s3", git = "https://github.com/esp-rs/esp-pacs.git", branch = "with_source", optional = true } [features] -esp32 = [ "esp32_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32", "xtensa-lx/esp32"] -esp32c3 = ["esp32c3_pac/rt", "risc_v", "single_core"] -esp32s2 = ["esp32s2_pac/rt", "xtensa", "single_core", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2"] -esp32s3 = ["esp32s3_pac/rt", "xtensa", "dual_core", "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3"] +esp32 = ["esp32_pac/rt" , "procmacros/xtensa", "multi_core" , "xtensa-lx-rt/esp32", "xtensa-lx/esp32"] +esp32c3 = ["esp32c3_pac/rt", "procmacros/riscv" , "single_core", "riscv", "riscv-atomic-emulation-trap"] +esp32s2 = ["esp32s2_pac/rt", "procmacros/xtensa", "single_core", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2"] +esp32s3 = ["esp32s3_pac/rt", "procmacros/xtensa", "multi_core" , "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3"] -# Architecture (should not be enabled directly, but instead by a PAC's feature) -risc_v = ["riscv", "riscv-atomic-emulation-trap"] -xtensa = ["procmacros/rtc_slow"] # Core Count (should not be enabled directly, but instead by a PAC's feature) single_core = [] -dual_core = [] +multi_core = [] # To support `ufmt` ufmt = ["ufmt-write"] @@ -68,3 +62,5 @@ smartled = ["smart-leds-trait"] # Implement the `embedded-hal==1.0.0-alpha.x` traits eh1 = ["embedded-hal-1"] +# To use vectored interrupts (calling the handlers defined in the PAC) +vectored = ["procmacros/interrupt"] diff --git a/esp-hal-common/src/interrupt/xtensa.rs b/esp-hal-common/src/interrupt/xtensa.rs index 76258b0de8f..5e7bb38afc6 100644 --- a/esp-hal-common/src/interrupt/xtensa.rs +++ b/esp-hal-common/src/interrupt/xtensa.rs @@ -1,21 +1,17 @@ +use xtensa_lx::interrupt::{self, InterruptNumber}; use xtensa_lx_rt::exception::Context; -use crate::{pac::Interrupt, Cpu}; - -extern "C" { - fn level1_interrupt(save_frame: &mut Context); - fn level2_interrupt(save_frame: &mut Context); - fn level3_interrupt(save_frame: &mut Context); - fn level4_interrupt(save_frame: &mut Context); - fn level5_interrupt(save_frame: &mut Context); - fn level6_interrupt(save_frame: &mut Context); - fn level7_interrupt(save_frame: &mut Context); -} +use crate::{ + pac::{self, Interrupt}, + Cpu, +}; /// Enumeration of available CPU interrupts /// It's possible to create one handler per priority level. (e.g /// `level1_interrupt`) #[allow(unused)] +#[derive(Debug, Copy, Clone)] +#[repr(u32)] pub enum CpuInterrupt { Interrupt0LevelPriority1 = 0, Interrupt1LevelPriority1, @@ -51,22 +47,32 @@ pub enum CpuInterrupt { Interrupt31EdgePriority5, } -/// 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_map_base = match core { - Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), - #[cfg(feature = "dual_core")] - Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map.as_ptr(), - #[cfg(feature = "single_core")] - Cpu::AppCpu => (*core0_interrupt_peripheral()).pro_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 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. +/// +/// Note: this only maps the interrupt to the CPU interrupt. The CPU interrupt +/// still needs to be enabled afterwards +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_map_base = match core { + Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), + #[cfg(feature = "multi_core")] + Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map.as_ptr(), + #[cfg(feature = "single_core")] + Cpu::AppCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), + }; + intr_map_base + .offset(interrupt_number) + .write_volatile(cpu_interrupt_number as u32); } /// Disable the given peripheral interrupt. @@ -75,7 +81,7 @@ pub fn disable(core: Cpu, interrupt: Interrupt) { let interrupt_number = interrupt as isize; let intr_map_base = match core { Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), - #[cfg(feature = "dual_core")] + #[cfg(feature = "multi_core")] Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map.as_ptr(), #[cfg(feature = "single_core")] Cpu::AppCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), @@ -111,7 +117,7 @@ pub fn get_status(core: Cpu) -> u128 { .bits() as u128) << 64 } - #[cfg(feature = "dual_core")] + #[cfg(feature = "multi_core")] Cpu::AppCpu => { ((*core1_interrupt_peripheral()) .app_intr_status_0 @@ -174,44 +180,380 @@ unsafe fn core1_interrupt_peripheral() -> *const crate::pac::interrupt_core1::Re crate::pac::INTERRUPT_CORE1::PTR } -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_1_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level1_interrupt(save_frame) }; -} +#[cfg(feature = "vectored")] +pub use vectored::*; -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_2_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level2_interrupt(save_frame) }; -} +#[cfg(feature = "vectored")] +pub mod vectored { + use procmacros::ram; -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_3_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level3_interrupt(save_frame) }; -} + use super::*; + use crate::get_core; -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_4_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level4_interrupt(save_frame) }; -} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + pub enum Error { + InvalidInterrupt, + } -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_5_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level5_interrupt(save_frame) }; -} + /// Interrupt priority levels. + #[derive(Copy, Clone, Debug, PartialEq, Eq)] + #[repr(u8)] + pub enum Priority { + None = 0, + Priority1, + Priority2, + Priority3, + } -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_6_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level6_interrupt(save_frame) }; + impl CpuInterrupt { + #[inline] + fn level(&self) -> Priority { + match self { + CpuInterrupt::Interrupt0LevelPriority1 + | CpuInterrupt::Interrupt1LevelPriority1 + | CpuInterrupt::Interrupt2LevelPriority1 + | CpuInterrupt::Interrupt3LevelPriority1 + | CpuInterrupt::Interrupt4LevelPriority1 + | CpuInterrupt::Interrupt5LevelPriority1 + | CpuInterrupt::Interrupt6Timer0Priority1 + | CpuInterrupt::Interrupt7SoftwarePriority1 + | CpuInterrupt::Interrupt8LevelPriority1 + | CpuInterrupt::Interrupt9LevelPriority1 + | CpuInterrupt::Interrupt10EdgePriority1 + | CpuInterrupt::Interrupt12LevelPriority1 + | CpuInterrupt::Interrupt13LevelPriority1 + | CpuInterrupt::Interrupt17LevelPriority1 + | CpuInterrupt::Interrupt18LevelPriority1 => Priority::Priority1, + + CpuInterrupt::Interrupt19LevelPriority2 + | CpuInterrupt::Interrupt20LevelPriority2 + | CpuInterrupt::Interrupt21LevelPriority2 => Priority::Priority2, + + CpuInterrupt::Interrupt11ProfilingPriority3 + | CpuInterrupt::Interrupt15Timer1Priority3 + | CpuInterrupt::Interrupt22EdgePriority3 + | CpuInterrupt::Interrupt27LevelPriority3 + | CpuInterrupt::Interrupt29SoftwarePriority3 + | CpuInterrupt::Interrupt23LevelPriority3 => Priority::Priority3, + + // we direct these to None because we do not support interrupts at this level + // through Rust + CpuInterrupt::Interrupt24LevelPriority4 + | CpuInterrupt::Interrupt25LevelPriority4 + | CpuInterrupt::Interrupt28EdgePriority4 + | CpuInterrupt::Interrupt30EdgePriority4 + | CpuInterrupt::Interrupt31EdgePriority5 + | CpuInterrupt::Interrupt16Timer2Priority5 + | CpuInterrupt::Interrupt26LevelPriority5 + | CpuInterrupt::Interrupt14NmiPriority7 => Priority::None, + } + } + } + + /// Get the interrupts configured for the core + #[inline] + fn get_configured_interrupts(core: Cpu) -> [u128; 7] { + unsafe { + let intr_map_base = match core { + Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), + #[cfg(feature = "multi_core")] + Cpu::AppCpu => (*core1_interrupt_peripheral()).app_mac_intr_map.as_ptr(), + #[cfg(feature = "single_core")] + Cpu::AppCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(), + }; + + let mut levels = [0u128; 7]; + + 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 level = cpu_interrupt.level() as u8 as usize; + levels[level] |= 1 << i; + } + + levels + } + } + + #[inline] + fn get_interrupt_count() -> usize { + cfg_if::cfg_if! { + if #[cfg(feature = "esp32")] { + 68 + } else if #[cfg(feature = "esp32s2")] { + 94 + } else if #[cfg(feature = "esp32s3")] { + 98 + } + } + } + + pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> { + let cpu_interrupt = + interrupt_level_to_cpu_interrupt(level, chip_specific::interrupt_is_edge(interrupt))?; + + unsafe { + map(get_core(), interrupt, cpu_interrupt); + + xtensa_lx::interrupt::enable_mask( + xtensa_lx::interrupt::get_mask() | 1 << cpu_interrupt as u32, + ); + } + Ok(()) + } + + fn interrupt_level_to_cpu_interrupt( + level: Priority, + is_edge: bool, + ) -> Result { + Ok(if is_edge { + match level { + Priority::None => return Err(Error::InvalidInterrupt), + Priority::Priority1 => CpuInterrupt::Interrupt10EdgePriority1, + Priority::Priority2 => return Err(Error::InvalidInterrupt), + Priority::Priority3 => CpuInterrupt::Interrupt22EdgePriority3, + } + } else { + match level { + Priority::None => return Err(Error::InvalidInterrupt), + Priority::Priority1 => CpuInterrupt::Interrupt1LevelPriority1, + Priority::Priority2 => CpuInterrupt::Interrupt19LevelPriority2, + Priority::Priority3 => CpuInterrupt::Interrupt23LevelPriority3, + } + }) + } + + // TODO use CpuInterrupt::LevelX.mask() // TODO make it const + const CPU_INTERRUPT_LEVELS: [u32; 8] = [ + 0b_0000_0000_0000_0000_0000_0000_0000_0000, // Dummy level 0 + 0b_0000_0000_0000_0110_0011_0111_1111_1111, // Level_1 + 0b_0000_0000_0011_1000_0000_0000_0000_0000, // Level 2 + 0b_0010_1000_1100_0000_1000_1000_0000_0000, // Level 3 + 0b_0101_0011_0000_0000_0000_0000_0000_0000, // Level 4 + 0b_1000_0100_0000_0001_0000_0000_0000_0000, // Level 5 + 0b_0000_0000_0000_0000_0000_0000_0000_0000, // Level 6 + 0b_0000_0000_0000_0000_0100_0000_0000_0000, // Level 7 + ]; + const CPU_INTERRUPT_INTERNAL: u32 = 0b_0010_0000_0000_0001_1000_1000_1100_0000; + const CPU_INTERRUPT_EDGE: u32 = 0b_0111_0000_0100_0000_0000_1100_1000_0000; + + #[inline] + fn cpu_interrupt_nr_to_cpu_interrupt_handler(number: u32) -> Option { + use xtensa_lx_rt::*; + // we're fortunate that all esp variants use the same CPU interrupt layout + Some(match number { + 6 => Timer0, + 7 => Software0, + 11 => Profiling, + 14 => NMI, + 15 => Timer1, + 16 => Timer2, + 29 => Software1, + _ => return None, + }) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_1_interrupt(level: u32, save_frame: &mut Context) { + handle_interrupts(level, save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_2_interrupt(level: u32, save_frame: &mut Context) { + handle_interrupts(level, save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_3_interrupt(level: u32, save_frame: &mut Context) { + handle_interrupts(level, save_frame) + } + + #[ram] + unsafe fn handle_interrupts(level: u32, save_frame: &mut Context) { + let cpu_interrupt_mask = + interrupt::get() & interrupt::get_mask() & CPU_INTERRUPT_LEVELS[level as usize]; + + if cpu_interrupt_mask & CPU_INTERRUPT_INTERNAL != 0 { + let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_INTERNAL; + let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros(); + + if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 { + interrupt::clear(1 << cpu_interrupt_nr); + } + if let Some(handler) = cpu_interrupt_nr_to_cpu_interrupt_handler(cpu_interrupt_nr) { + handler(level); + } + } else { + let interrupt_levels = get_configured_interrupts(crate::get_core()); + if (cpu_interrupt_mask & CPU_INTERRUPT_EDGE) != 0 { + let cpu_interrupt_mask = cpu_interrupt_mask & CPU_INTERRUPT_EDGE; + let cpu_interrupt_nr = cpu_interrupt_mask.trailing_zeros(); + interrupt::clear(1 << cpu_interrupt_nr); + + // for edge interrupts cannot rely on the interrupt status + // register, therefore call all registered + // handlers for current level + let mut interrupt_mask = + interrupt_levels[level as usize] & chip_specific::INTERRUPT_EDGE; + loop { + let interrupt_nr = interrupt_mask.trailing_zeros(); + if let Ok(interrupt) = pac::Interrupt::try_from(interrupt_nr as u16) { + handle_interrupt(level, interrupt, save_frame) + } else { + break; + } + interrupt_mask &= !(1u128 << interrupt_nr); + } + } else { + // finally check periperal sources and fire of handlers from pac + // peripheral mapped interrupts are cleared by the peripheral + let interrupt_mask = + get_status(crate::get_core()) & interrupt_levels[level as usize]; + 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 u16) { + handle_interrupt(level, interrupt, save_frame); + } + } + } + } + + #[ram] + unsafe fn handle_interrupt(level: u32, interrupt: Interrupt, save_frame: &mut Context) { + extern "C" { + // defined in each hal + fn DefaultHandler(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); + } else { + let handler: fn(&mut Context) = core::mem::transmute(handler); + handler(save_frame); + } + } + + #[cfg(feature = "esp32")] + mod chip_specific { + use super::*; + pub const INTERRUPT_EDGE: u128 = + 0b_0000_0000_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0000_0011_1111_1100_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0000_0000; + #[inline] + pub fn interrupt_is_edge(interrupt: Interrupt) -> bool { + use pac::Interrupt::*; + [ + TG0_T0_EDGE, + TG0_T1_EDGE, + TG0_WDT_EDGE, + TG0_LACT_EDGE, + TG1_T0_EDGE, + TG1_T1_EDGE, + TG1_WDT_EDGE, + TG1_LACT_EDGE, + ] + .contains(&interrupt) + } + } + + #[cfg(feature = "esp32s2")] + mod chip_specific { + use super::*; + pub const INTERRUPT_EDGE: u128 = + 0b_0000_0000_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0001_1111_1110_0000_0000_0000_0000_0000_0000_0000__0000_0000_0000_0000_0000_0000_0000_0000; + #[inline] + pub fn interrupt_is_edge(interrupt: Interrupt) -> bool { + use pac::Interrupt::*; + [ + TG0_T0_EDGE, + TG0_T1_EDGE, + TG0_WDT_EDGE, + TG0_LACT_EDGE, + TG1_T0_EDGE, + TG1_T1_EDGE, + TG1_WDT_EDGE, + TG1_LACT_EDGE, + ] + .contains(&interrupt) + } + } + + #[cfg(feature = "esp32s3")] + mod chip_specific { + use super::*; + pub const INTERRUPT_EDGE: u128 = 0; + #[inline] + pub fn interrupt_is_edge(_interrupt: Interrupt) -> bool { + false + } + } } -#[no_mangle] -#[link_section = ".rwtext"] -fn __level_7_interrupt(_level: u32, save_frame: &mut Context) { - unsafe { level7_interrupt(save_frame) }; +mod raw { + use super::*; + + extern "C" { + #[cfg(not(feature = "vectored"))] + fn level1_interrupt(save_frame: &mut Context); + #[cfg(not(feature = "vectored"))] + fn level2_interrupt(save_frame: &mut Context); + #[cfg(not(feature = "vectored"))] + fn level3_interrupt(save_frame: &mut Context); + fn level4_interrupt(save_frame: &mut Context); + fn level5_interrupt(save_frame: &mut Context); + fn level6_interrupt(save_frame: &mut Context); + fn level7_interrupt(save_frame: &mut Context); + } + + #[no_mangle] + #[link_section = ".rwtext"] + #[cfg(not(feature = "vectored"))] + unsafe fn __level_1_interrupt(_level: u32, save_frame: &mut Context) { + level1_interrupt(save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + #[cfg(not(feature = "vectored"))] + unsafe fn __level_2_interrupt(_level: u32, save_frame: &mut Context) { + level2_interrupt(save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + #[cfg(not(feature = "vectored"))] + unsafe fn __level_3_interrupt(_level: u32, save_frame: &mut Context) { + level3_interrupt(save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_4_interrupt(_level: u32, save_frame: &mut Context) { + level4_interrupt(save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_5_interrupt(_level: u32, save_frame: &mut Context) { + level5_interrupt(save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_6_interrupt(_level: u32, save_frame: &mut Context) { + level6_interrupt(save_frame) + } + + #[no_mangle] + #[link_section = ".rwtext"] + unsafe fn __level_7_interrupt(_level: u32, save_frame: &mut Context) { + level7_interrupt(save_frame) + } } diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 2f024723c62..dcde7b5d59d 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -37,8 +37,8 @@ pub mod efuse; pub mod gpio; pub mod i2c; -#[cfg_attr(feature = "risc_v", path = "interrupt/riscv.rs")] -#[cfg_attr(feature = "xtensa", path = "interrupt/xtensa.rs")] +#[cfg_attr(target_arch = "riscv32", path = "interrupt/riscv.rs")] +#[cfg_attr(target_arch = "xtensa", path = "interrupt/xtensa.rs")] pub mod interrupt; pub mod prelude; pub mod pulse_control; @@ -55,7 +55,7 @@ pub mod utils; pub use delay::Delay; pub use gpio::*; pub use interrupt::*; -pub use procmacros::ram; +pub use procmacros as macros; pub use pulse_control::PulseControl; pub use rng::Rng; #[cfg(not(feature = "esp32c3"))] @@ -87,3 +87,17 @@ pub enum Cpu { /// The second core AppCpu, } + +pub fn get_core() -> Cpu { + #[cfg(all(target_arch = "xtensa", feature = "multi_core"))] + match ((xtensa_lx::get_processor_id() >> 13) & 1) != 0 { + false => Cpu::ProCpu, + true => Cpu::AppCpu, + } + // #[cfg(all(target_arch = "riscv32", feature = "multi_core"))] + // TODO get hart_id + + // single core always has ProCpu only + #[cfg(feature = "single_core")] + Cpu::ProCpu +} diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index 7878557c14e..7d29d73eff8 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -60,3 +60,5 @@ pub mod eh1 { pub use crate::system::SystemExt; } + +pub use crate::macros::*; diff --git a/esp-hal-procmacros/Cargo.toml b/esp-hal-procmacros/Cargo.toml index f1ba3a65c24..c13d8e65212 100644 --- a/esp-hal-procmacros/Cargo.toml +++ b/esp-hal-procmacros/Cargo.toml @@ -22,3 +22,6 @@ proc-macro-error = "1.0.4" [features] rtc_slow = [] +xtensa = [] +riscv = [] +interrupt = [] \ No newline at end of file diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index cdc8213d2a2..eea31003673 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -2,6 +2,19 @@ use darling::FromMeta; use proc_macro::{self, Span, TokenStream}; use proc_macro_error::{abort, proc_macro_error}; use quote::quote; +#[cfg(feature = "interrupt")] +use syn::{ + parse, + spanned::Spanned, + AttrStyle, + Attribute, + Ident, + ItemFn, + Meta::Path, + ReturnType, + Type, + Visibility, +}; use syn::{parse_macro_input, AttributeArgs}; #[derive(Debug, Default, FromMeta)] @@ -88,3 +101,208 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream { }; output.into() } + +/// Marks a function as an interrupt handler +/// +/// Used to handle on of the [interrupts](enum.Interrupt.html). +/// +/// When specified between braces (`#[interrupt(example)]`) that interrupt will +/// be used and the function can have an arbitrary name. Otherwise the name of +/// the function must be the name of the interrupt. +/// +/// Example usage: +/// +/// ```rust +/// #[interrupt] +/// fn GPIO() { +/// // code +/// } +/// ``` +/// +/// The interrupt context can also be supplied by adding a argument to the +/// interrupt function for example, on Xtensa based chips: +/// +/// ```rust +/// fn GPIO(context: &mut xtensa_lx_rt::exeception::Context) { +/// // code +/// } +/// ``` +#[cfg(feature = "interrupt")] +#[proc_macro_attribute] +pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { + let mut f: ItemFn = syn::parse(input).expect("`#[interrupt]` must be applied to a function"); + + let attr_args = parse_macro_input!(args as AttributeArgs); + + if attr_args.len() > 1 { + abort!( + Span::call_site(), + "This attribute accepts zero or 1 arguments" + ) + } + + let ident = f.sig.ident.clone(); + let mut ident_s = &ident.clone(); + + if attr_args.len() == 1 { + match &attr_args[0] { + syn::NestedMeta::Meta(Path(x)) => { + ident_s = x.get_ident().unwrap(); + } + _ => { + abort!( + Span::call_site(), + format!( + "This attribute accepts a string attribute {:?}", + attr_args[0] + ) + ) + } + } + } + + // XXX should we blacklist other attributes? + + if let Err(error) = check_attr_whitelist(&f.attrs, WhiteListCaller::Interrupt) { + return error; + } + + let valid_signature = f.sig.constness.is_none() + && f.vis == Visibility::Inherited + && f.sig.abi.is_none() + && f.sig.generics.params.is_empty() + && f.sig.generics.where_clause.is_none() + && f.sig.variadic.is_none() + && match f.sig.output { + ReturnType::Default => true, + ReturnType::Type(_, ref ty) => match **ty { + Type::Tuple(ref tuple) => tuple.elems.is_empty(), + Type::Never(..) => true, + _ => false, + }, + } + && f.sig.inputs.len() <= 1; + + if !valid_signature { + return parse::Error::new( + f.span(), + "`#[interrupt]` handlers must have signature `[unsafe] fn([&mut Context]) [-> !]`", + ) + .to_compile_error() + .into(); + } + + f.sig.ident = Ident::new( + &format!("__esp_hal_internal_{}", f.sig.ident), + proc_macro2::Span::call_site(), + ); + f.block.stmts.extend(std::iter::once( + syn::parse2(quote! {{ + // Check that this interrupt actually exists + self::pac::Interrupt::#ident_s; + }}) + .unwrap(), + )); + + let tramp_ident = Ident::new( + &format!("{}_trampoline", f.sig.ident), + proc_macro2::Span::call_site(), + ); + let ident = &f.sig.ident; + + let (ref cfgs, ref attrs) = extract_cfgs(f.attrs.clone()); + + let export_name = ident_s.to_string(); + + #[cfg(feature = "xtensa")] + let context = quote! { + xtensa_lx_rt::exception::Context + }; + + #[cfg(feature = "riscv")] + let context = quote! { + crate::interrupt::TrapFrame + }; + + let context_call = + (f.sig.inputs.len() == 1).then_some(Ident::new("context", proc_macro2::Span::call_site())); + + quote!( + #(#cfgs)* + #(#attrs)* + #[doc(hidden)] + #[export_name = #export_name] + pub unsafe extern "C" fn #tramp_ident(context: &mut #context) { + #ident( + #context_call + ) + } + + #[inline(always)] + #f + ) + .into() +} + +#[cfg(feature = "interrupt")] +enum WhiteListCaller { + Interrupt, +} + +#[cfg(feature = "interrupt")] +fn check_attr_whitelist(attrs: &[Attribute], caller: WhiteListCaller) -> Result<(), TokenStream> { + let whitelist = &[ + "doc", + "link_section", + "cfg", + "allow", + "warn", + "deny", + "forbid", + "cold", + "ram", + "inline", + ]; + + 'o: for attr in attrs { + for val in whitelist { + if eq(&attr, &val) { + continue 'o; + } + } + + let err_str = match caller { + WhiteListCaller::Interrupt => { + "this attribute is not allowed on an interrupt handler controlled by esp-hal" + } + }; + + return Err(parse::Error::new(attr.span(), &err_str) + .to_compile_error() + .into()); + } + + Ok(()) +} + +/// Returns `true` if `attr.path` matches `name` +#[cfg(feature = "interrupt")] +fn eq(attr: &Attribute, name: &str) -> bool { + attr.style == AttrStyle::Outer && attr.path.is_ident(name) +} + +#[cfg(feature = "interrupt")] +fn extract_cfgs(attrs: Vec) -> (Vec, Vec) { + let mut cfgs = vec![]; + let mut not_cfgs = vec![]; + + for attr in attrs { + if eq(&attr, "cfg") { + cfgs.push(attr); + } else { + not_cfgs.push(attr); + } + } + + (cfgs, not_cfgs) +} diff --git a/esp32-hal/.vscode/settings.json b/esp32-hal/.vscode/settings.json deleted file mode 100644 index 54dd8e2321d..00000000000 --- a/esp32-hal/.vscode/settings.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "rust-analyzer.cargo.features": [], - "rust-analyzer.cargo.allFeatures": false, - "editor.formatOnSave": false, - "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 diff --git a/esp32-hal/Cargo.toml b/esp32-hal/Cargo.toml index 7075b4cdc02..212713fc1ac 100644 --- a/esp32-hal/Cargo.toml +++ b/esp32-hal/Cargo.toml @@ -43,12 +43,13 @@ smart-leds = "0.3" esp-println = { version = "0.2.0", features = ["esp32"] } [features] -default = ["rt"] +default = ["rt", "vectored"] bluetooth = [] eh1 = ["esp-hal-common/eh1"] rt = ["xtensa-lx-rt/esp32"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] +vectored = ["esp-hal-common/vectored"] [[example]] name = "hello_rgb" diff --git a/esp32-hal/examples/gpio_interrupt.rs b/esp32-hal/examples/gpio_interrupt.rs index c0dfd194d33..b8ee22de53b 100644 --- a/esp32-hal/examples/gpio_interrupt.rs +++ b/esp32-hal/examples/gpio_interrupt.rs @@ -6,27 +6,24 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use esp32_hal::{ clock::ClockControl, gpio::{Gpio0, IO}, gpio_types::{Event, Input, Pin, PullDown}, interrupt, - pac::{self, Peripherals, UART0}, + macros::ram, + pac::{self, Peripherals}, prelude::*, timer::TimerGroup, - Cpu, Delay, RtcCntl, - Serial, }; use panic_halt as _; use xtensa_lx::mutex::{Mutex, SpinLockMutex}; use xtensa_lx_rt::entry; -static mut SERIAL: SpinLockMutex>>> = - SpinLockMutex::new(RefCell::new(None)); static mut BUTTON: SpinLockMutex>>>> = SpinLockMutex::new(RefCell::new(None)); @@ -39,8 +36,6 @@ fn main() -> ! { let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut wdt = timer_group0.wdt; - // Disable the TIMG watchdog timer. - let serial0 = Serial::new(peripherals.UART0); let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); // Disable MWDT and RWDT (Watchdog) flash boot protection @@ -54,15 +49,14 @@ fn main() -> ! { button.listen(Event::FallingEdge); unsafe { - (&SERIAL).lock(|data| (*data).replace(Some(serial0))); (&BUTTON).lock(|data| (*data).replace(Some(button))); } interrupt::enable( - Cpu::ProCpu, pac::Interrupt::GPIO, - interrupt::CpuInterrupt::Interrupt1LevelPriority1, - ); + interrupt::vectored::Priority::Priority2, + ) + .unwrap(); led.set_high().unwrap(); @@ -70,32 +64,21 @@ fn main() -> ! { // loop. let mut delay = Delay::new(&clocks); - unsafe { - xtensa_lx::interrupt::enable_mask(1 << 1); - } - loop { led.toggle().unwrap(); delay.delay_ms(500u32); } } -#[no_mangle] -pub fn level1_interrupt() { +#[ram] +#[interrupt] +fn GPIO() { unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt").ok(); - }); - } + esp_println::println!( + "GPIO Interrupt with priority {}", + xtensa_lx::interrupt::get_level() + ); - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt1LevelPriority1, - ); - - unsafe { (&BUTTON).lock(|data| { let mut button = data.borrow_mut(); let button = button.as_mut().unwrap(); diff --git a/esp32-hal/examples/ram.rs b/esp32-hal/examples/ram.rs index e96bbd8e18a..1a89c8414cd 100644 --- a/esp32-hal/examples/ram.rs +++ b/esp32-hal/examples/ram.rs @@ -12,9 +12,9 @@ use core::fmt::Write; use esp32_hal::{ clock::ClockControl, + macros::ram, pac::{Peripherals, UART0}, prelude::*, - ram, timer::TimerGroup, Serial, }; diff --git a/esp32-hal/examples/serial_interrupts.rs b/esp32-hal/examples/serial_interrupts.rs index 238ebe95cc2..cd48c08b2a0 100644 --- a/esp32-hal/examples/serial_interrupts.rs +++ b/esp32-hal/examples/serial_interrupts.rs @@ -14,7 +14,6 @@ use esp32_hal::{ prelude::*, serial::config::AtCmdConfig, timer::TimerGroup, - Cpu, RtcCntl, Serial, }; @@ -53,11 +52,7 @@ fn main() -> ! { serial0.listen_at_cmd(); serial0.listen_rx_fifo_full(); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::UART0, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); + interrupt::enable(pac::Interrupt::UART0, interrupt::Priority::Priority2).unwrap(); timer0.start(1u64.secs()); @@ -65,11 +60,6 @@ fn main() -> ! { (&SERIAL).lock(|data| (*data).replace(Some(serial0))); } - unsafe { - xtensa_lx::interrupt::disable(); - xtensa_lx::interrupt::enable_mask(1 << 20); - } - loop { unsafe { (&SERIAL).lock(|data| { @@ -83,8 +73,8 @@ fn main() -> ! { } } -#[no_mangle] -pub fn level2_interrupt() { +#[interrupt] +fn UART0() { unsafe { (&SERIAL).lock(|data| { let mut serial = data.borrow_mut(); @@ -106,10 +96,6 @@ pub fn level2_interrupt() { serial.reset_at_cmd_interrupt(); serial.reset_rx_fifo_full_interrupt(); - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); }); } } diff --git a/esp32-hal/examples/timer_interrupt.rs b/esp32-hal/examples/timer_interrupt.rs index bb37b9e4c99..fcbd4774591 100644 --- a/esp32-hal/examples/timer_interrupt.rs +++ b/esp32-hal/examples/timer_interrupt.rs @@ -13,11 +13,10 @@ use esp32_hal::{ pac::{self, Peripherals, TIMG0, TIMG1, UART0}, prelude::*, timer::{Timer0, Timer1, TimerGroup}, - Cpu, RtcCntl, Serial, }; -use esp_hal_common::Timer; +use esp_hal_common::{Priority, Timer}; use panic_halt as _; use xtensa_lx::mutex::{Mutex, SpinLockMutex}; use xtensa_lx_rt::entry; @@ -58,31 +57,14 @@ fn main() -> ! { wdt1.disable(); rtc_cntl.set_wdt_global_enable(false); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T1_LEVEL, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); + interrupt::enable(pac::Interrupt::TG0_T0_LEVEL, Priority::Priority2).unwrap(); + interrupt::enable(pac::Interrupt::TG0_T1_LEVEL, Priority::Priority2).unwrap(); + interrupt::enable(pac::Interrupt::TG1_T0_LEVEL, Priority::Priority3).unwrap(); + interrupt::enable(pac::Interrupt::TG1_T1_LEVEL, Priority::Priority3).unwrap(); timer00.start(500u64.millis()); timer00.listen(); timer01.start(2500u64.millis()); timer01.listen(); - - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T1_LEVEL, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); timer10.start(1u64.secs()); timer10.listen(); timer11.start(3u64.secs()); @@ -96,22 +78,11 @@ fn main() -> ! { (&TIMER11).lock(|data| (*data).replace(Some(timer11))); } - unsafe { - xtensa_lx::interrupt::disable(); - xtensa_lx::interrupt::enable_mask(1 << 20); - xtensa_lx::interrupt::enable_mask(1 << 23); - } - loop {} } -#[no_mangle] -pub fn level2_interrupt() { - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); - +#[interrupt] +fn TG0_T0_LEVEL() { unsafe { (&TIMER00).lock(|data| { let mut timer = data.borrow_mut(); @@ -128,7 +99,12 @@ pub fn level2_interrupt() { }); } }); + } +} +#[interrupt] +fn TG0_T1_LEVEL() { + unsafe { (&TIMER01).lock(|data| { let mut timer = data.borrow_mut(); let timer = timer.as_mut().unwrap(); @@ -147,13 +123,8 @@ pub fn level2_interrupt() { } } -#[no_mangle] -pub fn level3_interrupt() { - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); - +#[interrupt] +fn TG1_T0_LEVEL() { unsafe { (&TIMER10).lock(|data| { let mut timer = data.borrow_mut(); @@ -170,7 +141,12 @@ pub fn level3_interrupt() { }); } }); + } +} +#[interrupt] +fn TG1_T1_LEVEL() { + unsafe { (&TIMER11).lock(|data| { let mut timer = data.borrow_mut(); let timer = timer.as_mut().unwrap(); diff --git a/esp32-hal/src/lib.rs b/esp32-hal/src/lib.rs index f6eda61d69e..86641cc49a0 100644 --- a/esp32-hal/src/lib.rs +++ b/esp32-hal/src/lib.rs @@ -8,10 +8,10 @@ pub use esp_hal_common::{ gpio as gpio_types, i2c, interrupt, + macros, pac, prelude, pulse_control, - ram, serial, spi, timer, diff --git a/esp32c3-hal/examples/ram.rs b/esp32c3-hal/examples/ram.rs index 2bdf2b51a55..3e7c81ab07d 100644 --- a/esp32c3-hal/examples/ram.rs +++ b/esp32c3-hal/examples/ram.rs @@ -12,9 +12,9 @@ use core::fmt::Write; use esp32c3_hal::{ clock::ClockControl, + macros::ram, pac::{Peripherals, UART0}, prelude::*, - ram, timer::TimerGroup, Serial, }; diff --git a/esp32c3-hal/src/lib.rs b/esp32c3-hal/src/lib.rs index 2b305017ca0..9abecd22fe4 100644 --- a/esp32c3-hal/src/lib.rs +++ b/esp32c3-hal/src/lib.rs @@ -9,10 +9,10 @@ pub use esp_hal_common::{ gpio as gpio_types, i2c, interrupt, + macros, pac, prelude, pulse_control, - ram, serial, spi, system, diff --git a/esp32s2-hal/Cargo.toml b/esp32s2-hal/Cargo.toml index 8b71e9ec0fb..dd80854544b 100644 --- a/esp32s2-hal/Cargo.toml +++ b/esp32s2-hal/Cargo.toml @@ -42,11 +42,12 @@ smart-leds = "0.3" esp-println = { version = "0.2.0", features = ["esp32s2"] } [features] -default = ["rt"] +default = ["rt", "vectored"] eh1 = ["esp-hal-common/eh1"] rt = ["xtensa-lx-rt/esp32s2"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] +vectored = ["esp-hal-common/vectored"] [[example]] name = "hello_rgb" diff --git a/esp32s2-hal/examples/gpio_interrupt.rs b/esp32s2-hal/examples/gpio_interrupt.rs index cc251dfd4dc..4d6018f46d1 100644 --- a/esp32s2-hal/examples/gpio_interrupt.rs +++ b/esp32s2-hal/examples/gpio_interrupt.rs @@ -6,27 +6,24 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use esp32s2_hal::{ clock::ClockControl, gpio::{Gpio0, IO}, gpio_types::{Event, Input, Pin, PullDown}, interrupt, - pac::{self, Peripherals, UART0}, + macros::ram, + pac::{self, Peripherals}, prelude::*, timer::TimerGroup, - Cpu, Delay, RtcCntl, - Serial, }; use panic_halt as _; use xtensa_lx::mutex::{CriticalSectionMutex, Mutex}; use xtensa_lx_rt::entry; -static mut SERIAL: CriticalSectionMutex>>> = - CriticalSectionMutex::new(RefCell::new(None)); static mut BUTTON: CriticalSectionMutex>>>> = CriticalSectionMutex::new(RefCell::new(None)); @@ -38,29 +35,28 @@ fn main() -> ! { let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut wdt = timer_group0.wdt; + let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); - let serial0 = Serial::new(peripherals.UART0); // Disable MWDT and RWDT (Watchdog) flash boot protection wdt.disable(); rtc_cntl.set_wdt_global_enable(false); - // Set GPIO4 as an output, and set its state high initially. + // Set GPIO15 as an output, and set its state high initially. let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let mut led = io.pins.gpio4.into_push_pull_output(); + let mut led = io.pins.gpio15.into_push_pull_output(); let mut button = io.pins.gpio0.into_pull_down_input(); button.listen(Event::FallingEdge); unsafe { - (&SERIAL).lock(|data| (*data).replace(Some(serial0))); (&BUTTON).lock(|data| (*data).replace(Some(button))); } interrupt::enable( - Cpu::ProCpu, pac::Interrupt::GPIO, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); + interrupt::vectored::Priority::Priority2, + ) + .unwrap(); led.set_high().unwrap(); @@ -68,32 +64,21 @@ fn main() -> ! { // loop. let mut delay = Delay::new(&clocks); - unsafe { - xtensa_lx::interrupt::enable_mask(1 << 19); - } - loop { led.toggle().unwrap(); delay.delay_ms(500u32); } } -#[no_mangle] -pub fn level2_interrupt() { +#[ram] +#[interrupt] +fn GPIO() { unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt").ok(); - }); - } + esp_println::println!( + "GPIO Interrupt with priority {}", + xtensa_lx::interrupt::get_level() + ); - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); - - unsafe { (&BUTTON).lock(|data| { let mut button = data.borrow_mut(); let button = button.as_mut().unwrap(); diff --git a/esp32s2-hal/examples/ram.rs b/esp32s2-hal/examples/ram.rs index 9f864e72a72..943839dc8a2 100644 --- a/esp32s2-hal/examples/ram.rs +++ b/esp32s2-hal/examples/ram.rs @@ -12,9 +12,9 @@ use core::fmt::Write; use esp32s2_hal::{ clock::ClockControl, + macros::ram, pac::{Peripherals, UART0}, prelude::*, - ram, timer::TimerGroup, Serial, }; diff --git a/esp32s2-hal/examples/serial_interrupts.rs b/esp32s2-hal/examples/serial_interrupts.rs index 45799bbae0b..5a4bcd00d5e 100644 --- a/esp32s2-hal/examples/serial_interrupts.rs +++ b/esp32s2-hal/examples/serial_interrupts.rs @@ -14,7 +14,6 @@ use esp32s2_hal::{ prelude::*, serial::config::AtCmdConfig, timer::TimerGroup, - Cpu, RtcCntl, Serial, }; @@ -36,8 +35,10 @@ fn main() -> ! { let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); let mut wdt1 = timer_group1.wdt; + let mut serial0 = Serial::new(peripherals.UART0); let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); @@ -51,11 +52,7 @@ fn main() -> ! { serial0.listen_at_cmd(); serial0.listen_rx_fifo_full(); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::UART0, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); + interrupt::enable(pac::Interrupt::UART0, interrupt::Priority::Priority2).unwrap(); timer0.start(1u64.secs()); @@ -63,11 +60,6 @@ fn main() -> ! { (&SERIAL).lock(|data| (*data).replace(Some(serial0))); } - unsafe { - xtensa_lx::interrupt::disable(); - xtensa_lx::interrupt::enable_mask(1 << 20); - } - loop { unsafe { (&SERIAL).lock(|data| { @@ -81,8 +73,8 @@ fn main() -> ! { } } -#[no_mangle] -pub fn level2_interrupt() { +#[interrupt] +fn UART0() { unsafe { (&SERIAL).lock(|data| { let mut serial = data.borrow_mut(); @@ -104,10 +96,6 @@ pub fn level2_interrupt() { serial.reset_at_cmd_interrupt(); serial.reset_rx_fifo_full_interrupt(); - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); }); } } diff --git a/esp32s2-hal/examples/systimer.rs b/esp32s2-hal/examples/systimer.rs index da9ce26c107..bb166479d95 100644 --- a/esp32s2-hal/examples/systimer.rs +++ b/esp32s2-hal/examples/systimer.rs @@ -4,26 +4,23 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use esp32s2_hal::{ clock::ClockControl, interrupt, - pac::{self, Peripherals, UART0}, + pac::{self, Peripherals}, prelude::*, systimer::{Alarm, SystemTimer, Target}, timer::TimerGroup, - Cpu, Delay, + interrupt::Priority, RtcCntl, - Serial, }; use panic_halt as _; -use xtensa_lx::mutex::{CriticalSectionMutex, Mutex}; +use xtensa_lx::mutex::{Mutex, CriticalSectionMutex}; use xtensa_lx_rt::entry; -static mut SERIAL: CriticalSectionMutex>>> = - CriticalSectionMutex::new(RefCell::new(None)); static mut ALARM0: CriticalSectionMutex>>> = CriticalSectionMutex::new(RefCell::new(None)); static mut ALARM1: CriticalSectionMutex>>> = @@ -40,7 +37,6 @@ fn main() -> ! { let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut wdt = timer_group0.wdt; let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); - let mut serial0 = Serial::new(peripherals.UART0); // Disable MWDT and RWDT (Watchdog) flash boot protection wdt.disable(); @@ -48,10 +44,6 @@ fn main() -> ! { let syst = SystemTimer::new(peripherals.SYSTIMER); - let now = SystemTimer::now(); - - writeln!(serial0, "Now: {}", now).ok(); - let alarm0 = syst.alarm0; alarm0.set_target(40_000_0000); alarm0.enable_interrupt(); @@ -65,57 +57,36 @@ fn main() -> ! { alarm2.enable_interrupt(); unsafe { - (&SERIAL).lock(|data| (*data).replace(Some(serial0))); (&ALARM0).lock(|data| (*data).replace(Some(alarm0))); (&ALARM1).lock(|data| (*data).replace(Some(alarm1))); (&ALARM2).lock(|data| (*data).replace(Some(alarm2))); } interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET0, - interrupt::CpuInterrupt::Interrupt0LevelPriority1, - ); - + Priority::Priority1, + ).unwrap(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET1, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); - + Priority::Priority2, + ).unwrap(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET2, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); + Priority::Priority2, + ).unwrap(); // Initialize the Delay peripheral, and use it to toggle the LED state in a // loop. let mut delay = Delay::new(&clocks); - unsafe { - xtensa_lx::interrupt::enable_mask(1 << 19 | 1 << 0 | 1 << 23); - } - loop { delay.delay_ms(500u32); } } -#[no_mangle] -pub fn level1_interrupt() { - unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt lvl1 (alarm0)").ok(); - }); - } - - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt0LevelPriority1, - ); +#[interrupt] +fn SYSTIMER_TARGET0() { + esp_println::println!("Interrupt lvl1 (alarm0)"); unsafe { (&ALARM0).lock(|data| { @@ -126,20 +97,9 @@ pub fn level1_interrupt() { } } -#[no_mangle] -pub fn level2_interrupt() { - unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt lvl2 (alarm1)").ok(); - }); - } - - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); +#[interrupt] +fn SYSTIMER_TARGET1() { + esp_println::println!("Interrupt lvl2 (alarm1)"); unsafe { (&ALARM1).lock(|data| { @@ -150,20 +110,9 @@ pub fn level2_interrupt() { } } -#[no_mangle] -pub fn level3_interrupt() { - unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt lvl3 (alarm2)").ok(); - }); - } - - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); +#[interrupt] +fn SYSTIMER_TARGET2() { + esp_println::println!("Interrupt lvl2 (alarm2)"); unsafe { (&ALARM2).lock(|data| { diff --git a/esp32s2-hal/examples/timer_interrupt.rs b/esp32s2-hal/examples/timer_interrupt.rs index 99e5f19c9c2..7e6c63005aa 100644 --- a/esp32s2-hal/examples/timer_interrupt.rs +++ b/esp32s2-hal/examples/timer_interrupt.rs @@ -13,11 +13,10 @@ use esp32s2_hal::{ pac::{self, Peripherals, TIMG0, TIMG1, UART0}, prelude::*, timer::{Timer0, Timer1, TimerGroup}, - Cpu, RtcCntl, Serial, }; -use esp_hal_common::Timer; +use esp_hal_common::{Priority, Timer}; use panic_halt as _; use xtensa_lx::mutex::{CriticalSectionMutex, Mutex}; use xtensa_lx_rt::entry; @@ -58,31 +57,14 @@ fn main() -> ! { wdt1.disable(); rtc_cntl.set_wdt_global_enable(false); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T1_LEVEL, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); + interrupt::enable(pac::Interrupt::TG0_T0_LEVEL, Priority::Priority2).unwrap(); + interrupt::enable(pac::Interrupt::TG0_T1_LEVEL, Priority::Priority2).unwrap(); + interrupt::enable(pac::Interrupt::TG1_T0_LEVEL, Priority::Priority3).unwrap(); + interrupt::enable(pac::Interrupt::TG1_T1_LEVEL, Priority::Priority3).unwrap(); timer00.start(500u64.millis()); timer00.listen(); timer01.start(2500u64.millis()); timer01.listen(); - - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T1_LEVEL, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); timer10.start(1u64.secs()); timer10.listen(); timer11.start(3u64.secs()); @@ -96,22 +78,11 @@ fn main() -> ! { (&TIMER11).lock(|data| (*data).replace(Some(timer11))); } - unsafe { - xtensa_lx::interrupt::disable(); - xtensa_lx::interrupt::enable_mask(1 << 20); - xtensa_lx::interrupt::enable_mask(1 << 23); - } - loop {} } -#[no_mangle] -pub fn level2_interrupt() { - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); - +#[interrupt] +fn TG0_T0_LEVEL() { unsafe { (&TIMER00).lock(|data| { let mut timer = data.borrow_mut(); @@ -128,7 +99,12 @@ pub fn level2_interrupt() { }); } }); + } +} +#[interrupt] +fn TG0_T1_LEVEL() { + unsafe { (&TIMER01).lock(|data| { let mut timer = data.borrow_mut(); let timer = timer.as_mut().unwrap(); @@ -147,13 +123,8 @@ pub fn level2_interrupt() { } } -#[no_mangle] -pub fn level3_interrupt() { - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); - +#[interrupt] +fn TG1_T0_LEVEL() { unsafe { (&TIMER10).lock(|data| { let mut timer = data.borrow_mut(); @@ -170,7 +141,12 @@ pub fn level3_interrupt() { }); } }); + } +} +#[interrupt] +fn TG1_T1_LEVEL() { + unsafe { (&TIMER11).lock(|data| { let mut timer = data.borrow_mut(); let timer = timer.as_mut().unwrap(); diff --git a/esp32s2-hal/src/lib.rs b/esp32s2-hal/src/lib.rs index d5769dcd75b..55314dc976a 100644 --- a/esp32s2-hal/src/lib.rs +++ b/esp32s2-hal/src/lib.rs @@ -7,10 +7,10 @@ pub use esp_hal_common::{ gpio as gpio_types, i2c::{self, I2C}, interrupt, + macros, pac, prelude, pulse_control, - ram, serial, spi, systimer, diff --git a/esp32s3-hal/Cargo.toml b/esp32s3-hal/Cargo.toml index 7992159b423..6b700051d0f 100644 --- a/esp32s3-hal/Cargo.toml +++ b/esp32s3-hal/Cargo.toml @@ -43,12 +43,13 @@ smart-leds = "0.3" esp-println = { version = "0.2.0", features = ["esp32s3"] } [features] -default = ["rt"] +default = ["rt", "vectored"] direct-boot = ["r0"] eh1 = ["esp-hal-common/eh1"] rt = ["xtensa-lx-rt/esp32s3"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] +vectored = ["esp-hal-common/vectored"] [[example]] name = "hello_rgb" diff --git a/esp32s3-hal/examples/gpio_interrupt.rs b/esp32s3-hal/examples/gpio_interrupt.rs index 223d8eb5b68..a98138b1622 100644 --- a/esp32s3-hal/examples/gpio_interrupt.rs +++ b/esp32s3-hal/examples/gpio_interrupt.rs @@ -6,27 +6,24 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use esp32s3_hal::{ clock::ClockControl, gpio::{Gpio0, IO}, gpio_types::{Event, Input, Pin, PullDown}, interrupt, - pac::{self, Peripherals, UART0}, + macros::ram, + pac::{self, Peripherals}, prelude::*, timer::TimerGroup, - Cpu, Delay, RtcCntl, - Serial, }; use panic_halt as _; use xtensa_lx::mutex::{Mutex, SpinLockMutex}; use xtensa_lx_rt::entry; -static mut SERIAL: SpinLockMutex>>> = - SpinLockMutex::new(RefCell::new(None)); static mut BUTTON: SpinLockMutex>>>> = SpinLockMutex::new(RefCell::new(None)); @@ -38,29 +35,28 @@ fn main() -> ! { let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut wdt = timer_group0.wdt; + let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); - let serial0 = Serial::new(peripherals.UART0); // Disable MWDT and RWDT (Watchdog) flash boot protection wdt.disable(); rtc_cntl.set_wdt_global_enable(false); - // Set GPIO4 as an output, and set its state high initially. + // Set GPIO15 as an output, and set its state high initially. let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let mut led = io.pins.gpio4.into_push_pull_output(); + let mut led = io.pins.gpio15.into_push_pull_output(); let mut button = io.pins.gpio0.into_pull_down_input(); button.listen(Event::FallingEdge); unsafe { - (&SERIAL).lock(|data| (*data).replace(Some(serial0))); (&BUTTON).lock(|data| (*data).replace(Some(button))); } interrupt::enable( - Cpu::ProCpu, pac::Interrupt::GPIO, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); + interrupt::vectored::Priority::Priority2, + ) + .unwrap(); led.set_high().unwrap(); @@ -68,32 +64,21 @@ fn main() -> ! { // loop. let mut delay = Delay::new(&clocks); - unsafe { - xtensa_lx::interrupt::enable_mask(1 << 19); - } - loop { led.toggle().unwrap(); delay.delay_ms(500u32); } } -#[no_mangle] -pub fn level2_interrupt() { +#[ram] +#[interrupt] +fn GPIO() { unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt").ok(); - }); - } + esp_println::println!( + "GPIO Interrupt with priority {}", + xtensa_lx::interrupt::get_level() + ); - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); - - unsafe { (&BUTTON).lock(|data| { let mut button = data.borrow_mut(); let button = button.as_mut().unwrap(); diff --git a/esp32s3-hal/examples/ram.rs b/esp32s3-hal/examples/ram.rs index 1d1f77f17c4..97f828dd560 100644 --- a/esp32s3-hal/examples/ram.rs +++ b/esp32s3-hal/examples/ram.rs @@ -12,9 +12,9 @@ use core::fmt::Write; use esp32s3_hal::{ clock::ClockControl, + macros::ram, pac::{Peripherals, UART0}, prelude::*, - ram, timer::TimerGroup, Serial, }; diff --git a/esp32s3-hal/examples/serial_interrupts.rs b/esp32s3-hal/examples/serial_interrupts.rs index 88dcbc1652b..0cca9e737c0 100644 --- a/esp32s3-hal/examples/serial_interrupts.rs +++ b/esp32s3-hal/examples/serial_interrupts.rs @@ -14,7 +14,6 @@ use esp32s3_hal::{ prelude::*, serial::config::AtCmdConfig, timer::TimerGroup, - Cpu, RtcCntl, Serial, }; @@ -53,11 +52,7 @@ fn main() -> ! { serial0.listen_at_cmd(); serial0.listen_rx_fifo_full(); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::UART0, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); + interrupt::enable(pac::Interrupt::UART0, interrupt::Priority::Priority2).unwrap(); timer0.start(1u64.secs()); @@ -65,11 +60,6 @@ fn main() -> ! { (&SERIAL).lock(|data| (*data).replace(Some(serial0))); } - unsafe { - xtensa_lx::interrupt::disable(); - xtensa_lx::interrupt::enable_mask(1 << 20); - } - loop { unsafe { (&SERIAL).lock(|data| { @@ -83,8 +73,8 @@ fn main() -> ! { } } -#[no_mangle] -pub fn level2_interrupt() { +#[interrupt] +fn UART0() { unsafe { (&SERIAL).lock(|data| { let mut serial = data.borrow_mut(); @@ -106,10 +96,6 @@ pub fn level2_interrupt() { serial.reset_at_cmd_interrupt(); serial.reset_rx_fifo_full_interrupt(); - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); }); } } diff --git a/esp32s3-hal/examples/systimer.rs b/esp32s3-hal/examples/systimer.rs index 12d33f17411..865b88b0936 100644 --- a/esp32s3-hal/examples/systimer.rs +++ b/esp32s3-hal/examples/systimer.rs @@ -4,26 +4,23 @@ #![no_std] #![no_main] -use core::{cell::RefCell, fmt::Write}; +use core::cell::RefCell; use esp32s3_hal::{ clock::ClockControl, interrupt, - pac::{self, Peripherals, UART0}, + pac::{self, Peripherals}, prelude::*, systimer::{Alarm, SystemTimer, Target}, timer::TimerGroup, - Cpu, Delay, + interrupt::Priority, RtcCntl, - Serial, }; use panic_halt as _; use xtensa_lx::mutex::{Mutex, SpinLockMutex}; use xtensa_lx_rt::entry; -static mut SERIAL: SpinLockMutex>>> = - SpinLockMutex::new(RefCell::new(None)); static mut ALARM0: SpinLockMutex>>> = SpinLockMutex::new(RefCell::new(None)); static mut ALARM1: SpinLockMutex>>> = @@ -40,7 +37,6 @@ fn main() -> ! { let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut wdt = timer_group0.wdt; let mut rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL); - let serial0 = Serial::new(peripherals.UART0); // Disable MWDT and RWDT (Watchdog) flash boot protection wdt.disable(); @@ -61,57 +57,36 @@ fn main() -> ! { alarm2.enable_interrupt(); unsafe { - (&SERIAL).lock(|data| (*data).replace(Some(serial0))); (&ALARM0).lock(|data| (*data).replace(Some(alarm0))); (&ALARM1).lock(|data| (*data).replace(Some(alarm1))); (&ALARM2).lock(|data| (*data).replace(Some(alarm2))); } interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET0, - interrupt::CpuInterrupt::Interrupt0LevelPriority1, - ); - + Priority::Priority1, + ).unwrap(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET1, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); - + Priority::Priority2, + ).unwrap(); interrupt::enable( - Cpu::ProCpu, pac::Interrupt::SYSTIMER_TARGET2, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); + Priority::Priority2, + ).unwrap(); // Initialize the Delay peripheral, and use it to toggle the LED state in a // loop. let mut delay = Delay::new(&clocks); - unsafe { - xtensa_lx::interrupt::enable_mask(1 << 19 | 1 << 0 | 1 << 23); - } - loop { delay.delay_ms(500u32); } } -#[no_mangle] -pub fn level1_interrupt() { - unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt lvl1 (alarm0)").ok(); - }); - } - - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt0LevelPriority1, - ); +#[interrupt] +fn SYSTIMER_TARGET0() { + esp_println::println!("Interrupt lvl1 (alarm0)"); unsafe { (&ALARM0).lock(|data| { @@ -122,20 +97,9 @@ pub fn level1_interrupt() { } } -#[no_mangle] -pub fn level2_interrupt() { - unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt lvl2 (alarm1)").ok(); - }); - } - - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt19LevelPriority2, - ); +#[interrupt] +fn SYSTIMER_TARGET1() { + esp_println::println!("Interrupt lvl2 (alarm1)"); unsafe { (&ALARM1).lock(|data| { @@ -146,20 +110,9 @@ pub fn level2_interrupt() { } } -#[no_mangle] -pub fn level3_interrupt() { - unsafe { - (&SERIAL).lock(|data| { - let mut serial = data.borrow_mut(); - let serial = serial.as_mut().unwrap(); - writeln!(serial, "Interrupt lvl3 (alarm2)").ok(); - }); - } - - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); +#[interrupt] +fn SYSTIMER_TARGET2() { + esp_println::println!("Interrupt lvl2 (alarm2)"); unsafe { (&ALARM2).lock(|data| { diff --git a/esp32s3-hal/examples/timer_interrupt.rs b/esp32s3-hal/examples/timer_interrupt.rs index f540df0f5e0..9311fdb1cc5 100644 --- a/esp32s3-hal/examples/timer_interrupt.rs +++ b/esp32s3-hal/examples/timer_interrupt.rs @@ -13,11 +13,10 @@ use esp32s3_hal::{ pac::{self, Peripherals, TIMG0, TIMG1, UART0}, prelude::*, timer::{Timer0, Timer1, TimerGroup}, - Cpu, RtcCntl, Serial, }; -use esp_hal_common::Timer; +use esp_hal_common::{Priority, Timer}; use panic_halt as _; use xtensa_lx::mutex::{Mutex, SpinLockMutex}; use xtensa_lx_rt::entry; @@ -58,31 +57,14 @@ fn main() -> ! { wdt1.disable(); rtc_cntl.set_wdt_global_enable(false); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG0_T1_LEVEL, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); + interrupt::enable(pac::Interrupt::TG0_T0_LEVEL, Priority::Priority2).unwrap(); + interrupt::enable(pac::Interrupt::TG0_T1_LEVEL, Priority::Priority2).unwrap(); + interrupt::enable(pac::Interrupt::TG1_T0_LEVEL, Priority::Priority3).unwrap(); + interrupt::enable(pac::Interrupt::TG1_T1_LEVEL, Priority::Priority3).unwrap(); timer00.start(500u64.millis()); timer00.listen(); timer01.start(2500u64.millis()); timer01.listen(); - - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T0_LEVEL, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); - interrupt::enable( - Cpu::ProCpu, - pac::Interrupt::TG1_T1_LEVEL, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); timer10.start(1u64.secs()); timer10.listen(); timer11.start(3u64.secs()); @@ -96,22 +78,11 @@ fn main() -> ! { (&TIMER11).lock(|data| (*data).replace(Some(timer11))); } - unsafe { - xtensa_lx::interrupt::disable(); - xtensa_lx::interrupt::enable_mask(1 << 20); - xtensa_lx::interrupt::enable_mask(1 << 23); - } - loop {} } -#[no_mangle] -pub fn level2_interrupt() { - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt20LevelPriority2, - ); - +#[interrupt] +fn TG0_T0_LEVEL() { unsafe { (&TIMER00).lock(|data| { let mut timer = data.borrow_mut(); @@ -128,7 +99,12 @@ pub fn level2_interrupt() { }); } }); + } +} +#[interrupt] +fn TG0_T1_LEVEL() { + unsafe { (&TIMER01).lock(|data| { let mut timer = data.borrow_mut(); let timer = timer.as_mut().unwrap(); @@ -147,13 +123,8 @@ pub fn level2_interrupt() { } } -#[no_mangle] -pub fn level3_interrupt() { - interrupt::clear( - Cpu::ProCpu, - interrupt::CpuInterrupt::Interrupt23LevelPriority3, - ); - +#[interrupt] +fn TG1_T0_LEVEL() { unsafe { (&TIMER10).lock(|data| { let mut timer = data.borrow_mut(); @@ -170,7 +141,12 @@ pub fn level3_interrupt() { }); } }); + } +} +#[interrupt] +fn TG1_T1_LEVEL() { + unsafe { (&TIMER11).lock(|data| { let mut timer = data.borrow_mut(); let timer = timer.as_mut().unwrap(); diff --git a/esp32s3-hal/src/lib.rs b/esp32s3-hal/src/lib.rs index c758b98ee3c..4c7f3beaae8 100644 --- a/esp32s3-hal/src/lib.rs +++ b/esp32s3-hal/src/lib.rs @@ -10,10 +10,10 @@ pub use esp_hal_common::{ gpio as gpio_types, i2c, interrupt, + macros, pac, prelude, pulse_control, - ram, serial, spi, systimer,