218 lines
6.9 KiB
Rust
218 lines
6.9 KiB
Rust
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);
|
|
}
|
|
|
|
/// Enumeration of available CPU interrupts
|
|
/// It's possible to create one handler per priority level. (e.g
|
|
/// `level1_interrupt`)
|
|
#[allow(unused)]
|
|
pub enum CpuInterrupt {
|
|
Interrupt0LevelPriority1 = 0,
|
|
Interrupt1LevelPriority1,
|
|
Interrupt2LevelPriority1,
|
|
Interrupt3LevelPriority1,
|
|
Interrupt4LevelPriority1,
|
|
Interrupt5LevelPriority1,
|
|
Interrupt6Timer0Priority1,
|
|
Interrupt7SoftwarePriority1,
|
|
Interrupt8LevelPriority1,
|
|
Interrupt9LevelPriority1,
|
|
Interrupt10EdgePriority1,
|
|
Interrupt11ProfilingPriority3,
|
|
Interrupt12LevelPriority1,
|
|
Interrupt13LevelPriority1,
|
|
Interrupt14NmiPriority7,
|
|
Interrupt15Timer1Priority3,
|
|
Interrupt16Timer2Priority5,
|
|
Interrupt17LevelPriority1,
|
|
Interrupt18LevelPriority1,
|
|
Interrupt19LevelPriority2,
|
|
Interrupt20LevelPriority2,
|
|
Interrupt21LevelPriority2,
|
|
Interrupt22EdgePriority3,
|
|
Interrupt23LevelPriority3,
|
|
Interrupt24LevelPriority4,
|
|
Interrupt25LevelPriority4,
|
|
Interrupt26LevelPriority5,
|
|
Interrupt27LevelPriority3,
|
|
Interrupt28EdgePriority4,
|
|
Interrupt29SoftwarePriority3,
|
|
Interrupt30EdgePriority4,
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// Disable the given peripheral interrupt.
|
|
pub fn disable(core: Cpu, interrupt: Interrupt) {
|
|
unsafe {
|
|
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")]
|
|
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(0);
|
|
}
|
|
}
|
|
|
|
/// Clear the given CPU interrupt
|
|
pub fn clear(_core: Cpu, which: CpuInterrupt) {
|
|
unsafe {
|
|
xtensa_lx::interrupt::clear(1 << which as u32);
|
|
}
|
|
}
|
|
|
|
/// Get status of peripheral interrupts
|
|
pub fn get_status(core: Cpu) -> u128 {
|
|
unsafe {
|
|
match core {
|
|
Cpu::ProCpu => {
|
|
((*core0_interrupt_peripheral())
|
|
.pro_intr_status_0
|
|
.read()
|
|
.bits() as u128)
|
|
| ((*core0_interrupt_peripheral())
|
|
.pro_intr_status_1
|
|
.read()
|
|
.bits() as u128)
|
|
<< 32
|
|
| ((*core0_interrupt_peripheral())
|
|
.pro_intr_status_2
|
|
.read()
|
|
.bits() as u128)
|
|
<< 64
|
|
}
|
|
#[cfg(feature = "dual_core")]
|
|
Cpu::AppCpu => {
|
|
((*core1_interrupt_peripheral())
|
|
.app_intr_status_0
|
|
.read()
|
|
.bits() as u128)
|
|
| ((*core1_interrupt_peripheral())
|
|
.app_intr_status_1
|
|
.read()
|
|
.bits() as u128)
|
|
<< 32
|
|
| ((*core1_interrupt_peripheral())
|
|
.app_intr_status_2
|
|
.read()
|
|
.bits() as u128)
|
|
<< 64
|
|
}
|
|
#[cfg(feature = "single_core")]
|
|
Cpu::AppCpu => {
|
|
((*core0_interrupt_peripheral())
|
|
.pro_intr_status_0
|
|
.read()
|
|
.bits() as u128)
|
|
| ((*core0_interrupt_peripheral())
|
|
.pro_intr_status_1
|
|
.read()
|
|
.bits() as u128)
|
|
<< 32
|
|
| ((*core0_interrupt_peripheral())
|
|
.pro_intr_status_2
|
|
.read()
|
|
.bits() as u128)
|
|
<< 64
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "esp32")]
|
|
unsafe fn core0_interrupt_peripheral() -> *const crate::pac::dport::RegisterBlock {
|
|
crate::pac::DPORT::PTR
|
|
}
|
|
|
|
#[cfg(feature = "esp32")]
|
|
unsafe fn core1_interrupt_peripheral() -> *const crate::pac::dport::RegisterBlock {
|
|
crate::pac::DPORT::PTR
|
|
}
|
|
|
|
#[cfg(feature = "esp32s2")]
|
|
unsafe fn core0_interrupt_peripheral() -> *const crate::pac::interrupt::RegisterBlock {
|
|
crate::pac::INTERRUPT::PTR
|
|
}
|
|
|
|
#[cfg(feature = "esp32s3")]
|
|
unsafe fn core0_interrupt_peripheral() -> *const crate::pac::interrupt_core0::RegisterBlock {
|
|
crate::pac::INTERRUPT_CORE0::PTR
|
|
}
|
|
|
|
#[cfg(feature = "esp32s3")]
|
|
unsafe fn core1_interrupt_peripheral() -> *const crate::pac::interrupt_core1::RegisterBlock {
|
|
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) };
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[link_section = ".rwtext"]
|
|
fn __level_2_interrupt(_level: u32, save_frame: &mut Context) {
|
|
unsafe { level2_interrupt(save_frame) };
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[link_section = ".rwtext"]
|
|
fn __level_3_interrupt(_level: u32, save_frame: &mut Context) {
|
|
unsafe { level3_interrupt(save_frame) };
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[link_section = ".rwtext"]
|
|
fn __level_4_interrupt(_level: u32, save_frame: &mut Context) {
|
|
unsafe { level4_interrupt(save_frame) };
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[link_section = ".rwtext"]
|
|
fn __level_5_interrupt(_level: u32, save_frame: &mut Context) {
|
|
unsafe { level5_interrupt(save_frame) };
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[link_section = ".rwtext"]
|
|
fn __level_6_interrupt(_level: u32, save_frame: &mut Context) {
|
|
unsafe { level6_interrupt(save_frame) };
|
|
}
|
|
|
|
#[no_mangle]
|
|
#[link_section = ".rwtext"]
|
|
fn __level_7_interrupt(_level: u32, save_frame: &mut Context) {
|
|
unsafe { level7_interrupt(save_frame) };
|
|
}
|