Skip to content

Commit

Permalink
Merge pull request #121 from esp-rs/perf/improve-vectored-intr-latency
Browse files Browse the repository at this point in the history
perf: vectored interrupt improvements
  • Loading branch information
bjoernQ authored Jul 27, 2022
2 parents 1d02bf8 + de37989 commit 1bf89b3
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 32 deletions.
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

0 comments on commit 1bf89b3

Please sign in to comment.