Skip to content

Commit

Permalink
Deduplicate SoC/arch-specific task switching related code (esp-rs#284)
Browse files Browse the repository at this point in the history
* Clean up imports, refer to crate-relative hal

* Move timer* files to submodule, split out common code

* Deduplicate time-based task switching

* Extract common setup fn
  • Loading branch information
bugadani authored and bjoernQ committed May 23, 2024
1 parent 5ab768c commit 8a580cd
Show file tree
Hide file tree
Showing 14 changed files with 631 additions and 997 deletions.
30 changes: 8 additions & 22 deletions esp-wifi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,23 @@ use core::mem::MaybeUninit;

use common_adapter::RADIO_CLOCKS;
use critical_section::Mutex;

#[cfg(esp32)]
use esp32_hal as hal;
#[cfg(esp32c2)]
use esp32c2_hal as hal;
#[cfg(esp32c2)]
use esp32c2_hal::systimer::{Alarm, Target};
#[cfg(esp32c3)]
use esp32c3_hal as hal;
#[cfg(esp32c3)]
use esp32c3_hal::systimer::{Alarm, Target};
#[cfg(esp32c6)]
use esp32c6_hal as hal;
#[cfg(esp32c6)]
use esp32c6_hal::systimer::{Alarm, Target};
#[cfg(esp32s2)]
use esp32s2_hal as hal;
#[cfg(esp32s3)]
use esp32s3_hal as hal;

#[cfg(any(esp32c2, esp32c3, esp32c6))]
use hal::systimer::{Alarm, Target};

use common_adapter::init_radio_clock_control;
use hal::system::RadioClockController;

Expand All @@ -47,25 +45,13 @@ use crate::tasks::init_tasks;
use crate::timer::setup_timer_isr;
use common_adapter::chip_specific::phy_mem_init;

#[doc(hidden)]
pub mod binary {
mod binary {
pub use esp_wifi_sys::*;
}
mod compat;
mod preempt;

#[doc(hidden)]
pub mod compat;

#[doc(hidden)]
pub mod preempt;

#[doc(hidden)]
#[cfg_attr(esp32, path = "timer_esp32.rs")]
#[cfg_attr(esp32c3, path = "timer_esp32c3.rs")]
#[cfg_attr(esp32c2, path = "timer_esp32c2.rs")]
#[cfg_attr(esp32c6, path = "timer_esp32c6.rs")]
#[cfg_attr(esp32s3, path = "timer_esp32s3.rs")]
#[cfg_attr(esp32s2, path = "timer_esp32s2.rs")]
pub mod timer;
mod timer;

#[cfg(feature = "wifi")]
pub mod wifi;
Expand Down
22 changes: 22 additions & 0 deletions esp-wifi/src/timer/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#[cfg_attr(esp32, path = "timer_esp32.rs")]
#[cfg_attr(esp32c2, path = "timer_esp32c2.rs")]
#[cfg_attr(esp32c3, path = "timer_esp32c3.rs")]
#[cfg_attr(esp32c6, path = "timer_esp32c6.rs")]
#[cfg_attr(esp32s3, path = "timer_esp32s3.rs")]
#[cfg_attr(esp32s2, path = "timer_esp32s2.rs")]
mod chip_specific;

#[cfg_attr(any(esp32, esp32s2, esp32s3), path = "xtensa.rs")]
#[cfg_attr(any(esp32c2, esp32c3, esp32c6), path = "riscv.rs")]
mod arch_specific;

pub use arch_specific::*;
pub use chip_specific::*;

pub fn setup_timer_isr(timebase: TimeBase) {
setup_radio_isr();

setup_timer(timebase);

setup_multitasking();
}
98 changes: 98 additions & 0 deletions esp-wifi/src/timer/riscv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use core::cell::RefCell;

use critical_section::Mutex;

use crate::{
hal::{
interrupt::{self, TrapFrame},
peripherals::{self, Interrupt},
prelude::*,
riscv,
systimer::{Alarm, Periodic, SystemTimer, Target},
},
preempt::preempt::task_switch,
};

#[cfg(feature = "esp32c6")]
use peripherals::INTPRI as SystemPeripheral;
#[cfg(not(feature = "esp32c6"))]
use peripherals::SYSTEM as SystemPeripheral;

pub type TimeBase = Alarm<Target, 0>;

pub const TICKS_PER_SECOND: u64 = 16_000_000;

const TIMER_DELAY: fugit::HertzU32 = fugit::HertzU32::from_raw(crate::CONFIG.tick_rate_hz);

static ALARM0: Mutex<RefCell<Option<Alarm<Periodic, 0>>>> = Mutex::new(RefCell::new(None));

pub fn setup_timer(systimer: TimeBase) {
let alarm0 = systimer.into_periodic();
alarm0.set_period(TIMER_DELAY.into());
alarm0.clear_interrupt();
alarm0.interrupt_enable(true);

critical_section::with(|cs| ALARM0.borrow_ref_mut(cs).replace(alarm0));

unwrap!(interrupt::enable(
Interrupt::SYSTIMER_TARGET0,
interrupt::Priority::Priority1,
));
}

pub fn setup_multitasking() {
unwrap!(interrupt::enable(
Interrupt::FROM_CPU_INTR3,
interrupt::Priority::Priority1,
));

unsafe {
riscv::interrupt::enable();
}

while unsafe { crate::preempt::FIRST_SWITCH.load(core::sync::atomic::Ordering::Relaxed) } {}
}

#[interrupt]
fn SYSTIMER_TARGET0(trap_frame: &mut TrapFrame) {
// clear the systimer intr
critical_section::with(|cs| {
unwrap!(ALARM0.borrow_ref_mut(cs).as_mut()).clear_interrupt();
});

task_switch(trap_frame);
}

#[interrupt]
fn FROM_CPU_INTR3(trap_frame: &mut TrapFrame) {
unsafe {
// clear FROM_CPU_INTR3
(&*SystemPeripheral::PTR)
.cpu_intr_from_cpu_3
.modify(|_, w| w.cpu_intr_from_cpu_3().clear_bit());
}

critical_section::with(|cs| {
let mut alarm0 = ALARM0.borrow_ref_mut(cs);
let alarm0 = unwrap!(alarm0.as_mut());

alarm0.set_period(TIMER_DELAY.into());
alarm0.clear_interrupt();
});

task_switch(trap_frame);
}

pub fn yield_task() {
unsafe {
(&*SystemPeripheral::PTR)
.cpu_intr_from_cpu_3
.modify(|_, w| w.cpu_intr_from_cpu_3().set_bit());
}
}

/// Current systimer count value
/// A tick is 1 / 16_000_000 seconds
pub fn get_systimer_count() -> u64 {
SystemTimer::now()
}
97 changes: 97 additions & 0 deletions esp-wifi/src/timer/timer_esp32.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use crate::hal::{interrupt, macros::interrupt, peripherals};

pub fn setup_radio_isr() {
#[cfg(feature = "wifi")]
unwrap!(interrupt::enable(
peripherals::Interrupt::WIFI_MAC,
interrupt::Priority::Priority1,
));

#[cfg(feature = "ble")]
{
unwrap!(interrupt::enable(
peripherals::Interrupt::RWBT,
interrupt::Priority::Priority1
));
unwrap!(interrupt::enable(
peripherals::Interrupt::BT_BB,
interrupt::Priority::Priority1,
));

// It's a mystery why these interrupts are enabled now since it worked without this before
// Now at least without disabling these nothing will work
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::ETH_MAC);
interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::UART0);
}
}

#[cfg(feature = "ble")]
#[allow(non_snake_case)]
#[no_mangle]
fn Software0(_level: u32) {
unsafe {
let (fnc, arg) = crate::ble::btdm::ble_os_adapter_chip_specific::ISR_INTERRUPT_7;
trace!("interrupt Software0 {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}
}
}

#[cfg(feature = "wifi")]
#[interrupt]
fn WIFI_MAC() {
unsafe {
let (fnc, arg) = crate::wifi::os_adapter::ISR_INTERRUPT_1;
trace!("interrupt WIFI_MAC {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}
}
}

#[cfg(feature = "ble")]
#[interrupt]
fn RWBT() {
unsafe {
let (fnc, arg) = crate::ble::btdm::ble_os_adapter_chip_specific::ISR_INTERRUPT_5;
trace!("interrupt RWBT {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}
}
}

#[cfg(feature = "ble")]
#[interrupt]
fn RWBLE() {
unsafe {
let (fnc, arg) = crate::ble::btdm::ble_os_adapter_chip_specific::ISR_INTERRUPT_5;
trace!("interrupt RWBLE {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}
}
}

#[cfg(feature = "ble")]
#[interrupt]
fn BT_BB() {
unsafe {
let (fnc, arg) = crate::ble::btdm::ble_os_adapter_chip_specific::ISR_INTERRUPT_8;
trace!("interrupt BT_BB {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}
}
}
108 changes: 108 additions & 0 deletions esp-wifi/src/timer/timer_esp32c2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
use crate::{
binary,
hal::{interrupt, macros::interrupt, peripherals::Interrupt},
};

pub fn setup_radio_isr() {
#[cfg(feature = "wifi")]
{
unwrap!(interrupt::enable(
Interrupt::WIFI_MAC,
interrupt::Priority::Priority1
));
unwrap!(interrupt::enable(
Interrupt::WIFI_PWR,
interrupt::Priority::Priority1
));
}

#[cfg(feature = "ble")]
{
unwrap!(interrupt::enable(
Interrupt::LP_TIMER,
interrupt::Priority::Priority1
));
unwrap!(interrupt::enable(
Interrupt::BT_MAC,
interrupt::Priority::Priority1
));
}
}

#[cfg(feature = "wifi")]
#[interrupt]
fn WIFI_MAC() {
unsafe {
let (fnc, arg) = crate::wifi::os_adapter::ISR_INTERRUPT_1;

trace!("interrupt WIFI_MAC {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}

trace!("interrupt 1 done");
};
}

#[cfg(feature = "wifi")]
#[interrupt]
fn WIFI_PWR() {
unsafe {
let (fnc, arg) = crate::wifi::os_adapter::ISR_INTERRUPT_1;

trace!("interrupt WIFI_PWR {:?} {:?}", fnc, arg);

if !fnc.is_null() {
let fnc: fn(*mut binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
}

trace!("interrupt 1 done");
};
}

#[cfg(feature = "ble")]
#[interrupt]
fn LP_TIMER() {
unsafe {
trace!("LP_TIMER interrupt");

let (fnc, arg) = crate::ble::npl::ble_os_adapter_chip_specific::ISR_INTERRUPT_7;

trace!("interrupt LP_TIMER {:?} {:?}", fnc, arg);

if !fnc.is_null() {
trace!("interrupt LP_TIMER call");

let fnc: fn(*mut binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
trace!("LP_TIMER done");
}

trace!("interrupt LP_TIMER done");
};
}

#[cfg(feature = "ble")]
#[interrupt]
fn BT_MAC() {
unsafe {
trace!("BT_MAC interrupt");

let (fnc, arg) = crate::ble::npl::ble_os_adapter_chip_specific::ISR_INTERRUPT_4;

trace!("interrupt BT_MAC {:?} {:?}", fnc, arg);

if !fnc.is_null() {
trace!("interrupt BT_MAC call");

let fnc: fn(*mut binary::c_types::c_void) = core::mem::transmute(fnc);
fnc(arg);
trace!("BT_MAC done");
}

trace!("interrupt BT_MAC done");
};
}
Loading

0 comments on commit 8a580cd

Please sign in to comment.