Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: vectored interrupt improvements #121

Merged
merged 1 commit into from
Jul 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 6 additions & 13 deletions esp-hal-common/src/interrupt/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,16 +246,17 @@ mod vectored {

/// Get the interrupts configured for the core
#[inline]
fn get_configured_interrupts(_core: Cpu) -> [u128; 15] {
fn get_configured_interrupts(_core: Cpu, mut status: u128) -> [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;
while status != 0 {
let interrupt_nr = status.trailing_zeros();
let i = interrupt_nr 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);
Expand All @@ -264,21 +265,13 @@ mod vectored {
.read_volatile();

prios[prio as usize] |= 1 << i;
status &= !(1u128 << interrupt_nr);
}

prios
}
}

#[inline]
fn get_interrupt_count() -> usize {
cfg_if::cfg_if! {
if #[cfg(feature = "esp32c3")] {
62
}
}
}

/// Interrupt Error
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
Expand Down Expand Up @@ -309,7 +302,7 @@ mod vectored {
// so we clear it anyway
clear(crate::get_core(), cpu_intr);

let configured_interrupts = get_configured_interrupts(crate::get_core());
let configured_interrupts = get_configured_interrupts(crate::get_core(), status);
let mut interrupt_mask = status & configured_interrupts[cpu_intr as usize];
while interrupt_mask != 0 {
let interrupt_nr = interrupt_mask.trailing_zeros();
Expand Down
28 changes: 9 additions & 19 deletions esp-hal-common/src/interrupt/xtensa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ mod vectored {

/// Get the interrupts configured for the core
#[inline]
fn get_configured_interrupts(core: Cpu) -> [u128; 7] {
fn get_configured_interrupts(core: Cpu, mut status: u128) -> [u128; 7] {
unsafe {
let intr_map_base = match core {
Cpu::ProCpu => (*core0_interrupt_peripheral()).pro_mac_intr_map.as_ptr(),
Expand All @@ -264,32 +264,22 @@ mod vectored {

let mut levels = [0u128; 7];

for i in 0..get_interrupt_count() {
let i = i as isize;
while status != 0 {
let interrupt_nr = status.trailing_zeros();
let i = interrupt_nr 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;
status &= !(1u128 << interrupt_nr);
}

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))?;
Expand Down Expand Up @@ -389,7 +379,8 @@ mod vectored {
handler(level);
}
} else {
let interrupt_levels = get_configured_interrupts(crate::get_core());
let status = get_status(crate::get_core());
let interrupt_levels = get_configured_interrupts(crate::get_core(), status);
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();
Expand All @@ -412,8 +403,7 @@ mod vectored {
} 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_mask = status & interrupt_levels[level as usize];
let interrupt_nr = interrupt_mask.trailing_zeros();

// Interrupt::try_from can fail if interrupt already de-asserted:
Expand Down