From a4fe5e6e637b1197f4245c1cf81131c406324070 Mon Sep 17 00:00:00 2001 From: Kirill Mikhailov <62840029+playfulFence@users.noreply.github.com> Date: Fri, 4 Oct 2024 14:16:52 +0200 Subject: [PATCH] Adding a way to deinitialize the WiFi stack. (#2187) * WIP * cleanup * WIP (BLE) * WIP (BLE) * c2 ble deinit doesn't work with ble alone, works in coex (WIP) * fmt * cleanup * changelog entry changelog entry * WIP (do not check it) it's just to save things before weekend! * polishing, refactor * cleanup * lint * Addressing reviews * address reviews * utilize `EspWifiInitialization` in deinit * example -> description * reviews * reviews * fix memory leak + rebase * typo * fix * init -> initialize screwed up after rebase * make esp32c6/h2 buildable again * edit safety comment --- esp-wifi/CHANGELOG.md | 1 + esp-wifi/src/ble/btdm.rs | 22 ++++++- esp-wifi/src/ble/npl.rs | 87 +++++++++++++++++++++++-- esp-wifi/src/ble/os_adapter_esp32s3.rs | 20 ++++-- esp-wifi/src/common_adapter/mod.rs | 4 ++ esp-wifi/src/lib.rs | 90 ++++++++++++++++++++++++-- esp-wifi/src/preempt/mod.rs | 33 +++++++++- esp-wifi/src/timer/mod.rs | 15 +++++ esp-wifi/src/timer/riscv.rs | 25 +++++-- esp-wifi/src/timer/timer_esp32.rs | 8 +++ esp-wifi/src/timer/timer_esp32c2.rs | 8 +++ esp-wifi/src/timer/timer_esp32c3.rs | 9 +++ esp-wifi/src/timer/timer_esp32c6.rs | 8 +++ esp-wifi/src/timer/timer_esp32h2.rs | 8 +++ esp-wifi/src/timer/timer_esp32s2.rs | 4 ++ esp-wifi/src/timer/timer_esp32s3.rs | 14 +++- esp-wifi/src/timer/xtensa.rs | 25 +++++-- esp-wifi/src/wifi/os_adapter.rs | 5 +- examples/src/bin/wifi_access_point.rs | 4 +- examples/src/bin/wifi_bench.rs | 4 +- examples/src/bin/wifi_coex.rs | 4 +- examples/src/bin/wifi_dhcp.rs | 4 +- examples/src/bin/wifi_static_ip.rs | 4 +- 23 files changed, 359 insertions(+), 47 deletions(-) diff --git a/esp-wifi/CHANGELOG.md b/esp-wifi/CHANGELOG.md index 9fb61e3d5..0ae381427 100644 --- a/esp-wifi/CHANGELOG.md +++ b/esp-wifi/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Added `have-strchr` feature to disable including `strchr` (#2096) +- Adding a way to deinitialize the WiFi stack (#2187) ### Changed diff --git a/esp-wifi/src/ble/btdm.rs b/esp-wifi/src/ble/btdm.rs index 14e52eab5..879f82166 100644 --- a/esp-wifi/src/ble/btdm.rs +++ b/esp-wifi/src/ble/btdm.rs @@ -316,8 +316,15 @@ unsafe extern "C" fn task_create( 1 } -unsafe extern "C" fn task_delete(_task: *const ()) { - todo!(); +unsafe extern "C" fn task_delete(task: *const ()) { + trace!("task delete called for {:?}", task); + + let task = if task.is_null() { + crate::preempt::current_task() + } else { + task as *mut _ + }; + crate::preempt::schedule_task_deletion(task); } #[ram] @@ -514,6 +521,17 @@ pub(crate) fn ble_init() { } } +pub(crate) fn ble_deinit() { + extern "C" { + fn btdm_controller_deinit(); + } + + unsafe { + btdm_controller_deinit(); + crate::common_adapter::chip_specific::phy_disable(); + } +} + static mut BLE_HCI_READ_DATA: [u8; 256] = [0u8; 256]; static mut BLE_HCI_READ_DATA_INDEX: usize = 0; static mut BLE_HCI_READ_DATA_LEN: usize = 0; diff --git a/esp-wifi/src/ble/npl.rs b/esp-wifi/src/ble/npl.rs index a3ae83817..cc7cd914d 100644 --- a/esp-wifi/src/ble/npl.rs +++ b/esp-wifi/src/ble/npl.rs @@ -204,6 +204,15 @@ extern "C" { #[cfg(esp32c2)] pub(crate) fn ble_controller_init(cfg: *const esp_bt_controller_config_t) -> i32; + #[cfg(not(esp32c2))] + pub(crate) fn r_ble_controller_disable() -> i32; + + #[cfg(not(esp32c2))] + pub(crate) fn r_ble_controller_deinit() -> i32; + + #[cfg(esp32c2)] + pub(crate) fn ble_controller_deinit() -> i32; + #[cfg(not(esp32c2))] pub(crate) fn r_ble_controller_init(cfg: *const esp_bt_controller_config_t) -> i32; @@ -213,10 +222,14 @@ extern "C" { #[cfg(not(esp32c2))] pub(crate) fn r_ble_controller_enable(mode: u8) -> i32; + pub(crate) fn esp_unregister_ext_funcs(); + pub(crate) fn esp_register_ext_funcs(funcs: *const ExtFuncsT) -> i32; pub(crate) fn esp_register_npl_funcs(funcs: *const npl_funcs_t) -> i32; + pub(crate) fn esp_unregister_npl_funcs(); + #[cfg(esp32c2)] pub(crate) fn ble_get_npl_element_info( cfg: *const esp_bt_controller_config_t, @@ -406,8 +419,15 @@ unsafe extern "C" fn task_create( 1 } -unsafe extern "C" fn task_delete(_: *const c_void) { - todo!(); +unsafe extern "C" fn task_delete(task: *const c_void) { + trace!("task delete called for {:?}", task); + + let task = if task.is_null() { + crate::preempt::current_task() + } else { + task as *mut _ + }; + crate::preempt::schedule_task_deletion(task); } unsafe extern "C" fn osi_assert(ln: u32, fn_name: *const c_void, param1: u32, param2: u32) { @@ -795,8 +815,18 @@ unsafe extern "C" fn ble_npl_event_reset(event: *const ble_npl_event) { } } -unsafe extern "C" fn ble_npl_event_deinit(_event: *const ble_npl_event) { - todo!() +unsafe extern "C" fn ble_npl_event_deinit(event: *const ble_npl_event) { + trace!("ble_npl_event_deinit {:?}", event); + + let event = event.cast_mut(); + + if (*event).dummy == 0 { + panic!("Trying to deinitialize an uninitialized event"); + } else { + let idx = ((*event).dummy - 1) as usize; + EVENTS[idx] = None; + (*event).dummy = 0; + } } unsafe extern "C" fn ble_npl_event_init( @@ -908,8 +938,23 @@ unsafe extern "C" fn ble_npl_eventq_get( } } -unsafe extern "C" fn ble_npl_eventq_deinit(_queue: *const ble_npl_eventq) { - todo!() +unsafe extern "C" fn ble_npl_eventq_deinit(queue: *const ble_npl_eventq) { + trace!("ble_npl_eventq_deinit {:?}", queue); + + let queue = queue.cast_mut(); + if (*queue).dummy == 0 { + panic!("Trying to deinitialize an uninitialized queue"); + } else { + critical_section::with(|_| { + while let Some(event_idx) = EVENT_QUEUE.dequeue() { + if let Some(event) = EVENTS[event_idx - 1].as_mut() { + event.queued = false; + } + } + }); + + (*queue).dummy = 0; + } } unsafe extern "C" fn ble_npl_callout_init( @@ -1179,6 +1224,36 @@ pub(crate) fn ble_init() { } } +pub(crate) fn ble_deinit() { + unsafe { + // HCI deinit + npl::r_ble_hci_trans_cfg_hs(None, core::ptr::null(), None, core::ptr::null()); + + #[cfg(not(esp32c2))] + npl::r_ble_controller_disable(); + + #[cfg(not(esp32c2))] + let res = npl::r_ble_controller_deinit(); + + #[cfg(esp32c2)] + let res = npl::ble_controller_deinit(); + + if res != 0 { + panic!("ble_controller_deinit returned {}", res); + } + + npl::esp_unregister_npl_funcs(); + + npl::esp_unregister_ext_funcs(); + + crate::common_adapter::chip_specific::phy_disable(); + + CALLOUTS.iter_mut().for_each(|item| { + item.take(); + }); + } +} + #[cfg(esp32c2)] fn os_msys_buf_alloc() -> bool { unsafe { diff --git a/esp-wifi/src/ble/os_adapter_esp32s3.rs b/esp-wifi/src/ble/os_adapter_esp32s3.rs index 3ff7e5caa..00acc19bb 100644 --- a/esp-wifi/src/ble/os_adapter_esp32s3.rs +++ b/esp-wifi/src/ble/os_adapter_esp32s3.rs @@ -1,5 +1,8 @@ use super::*; -use crate::binary::include::esp_bt_controller_config_t; +use crate::{ + binary::include::esp_bt_controller_config_t, + hal::{interrupt, peripherals::Interrupt}, +}; pub static mut ISR_INTERRUPT_5: ( *mut crate::binary::c_types::c_void, @@ -292,13 +295,22 @@ pub(crate) fn create_ble_config() -> esp_bt_controller_config_t { pub(crate) unsafe extern "C" fn interrupt_on(intr_num: i32) -> i32 { trace!("interrupt_on {}", intr_num); + unwrap!(interrupt::enable( + Interrupt::try_from(intr_num as u16).unwrap(), + interrupt::Priority::Priority1, + )); - // NO-OP 0 } -pub(crate) unsafe extern "C" fn interrupt_off(_intr_num: i32) -> i32 { - todo!(); +pub(crate) unsafe extern "C" fn interrupt_off(intr_num: i32) -> i32 { + trace!("interrupt_off {}", intr_num); + interrupt::disable( + crate::hal::Cpu::ProCpu, + Interrupt::try_from(intr_num as u16).unwrap(), + ); + + 0 } pub(crate) fn btdm_controller_mem_init() { diff --git a/esp-wifi/src/common_adapter/mod.rs b/esp-wifi/src/common_adapter/mod.rs index a2a5a3849..be2b5d524 100644 --- a/esp-wifi/src/common_adapter/mod.rs +++ b/esp-wifi/src/common_adapter/mod.rs @@ -39,6 +39,10 @@ pub(crate) fn init_radio_clock_control(rcc: hal::peripherals::RADIO_CLK) { unsafe { RADIO_CLOCKS = Some(rcc) }; } +pub(crate) fn deinit_radio_clock_control() -> Option { + unsafe { RADIO_CLOCKS.take() } +} + /// ************************************************************************** /// Name: esp_semphr_create /// diff --git a/esp-wifi/src/lib.rs b/esp-wifi/src/lib.rs index 52f779dd0..3dd691d12 100644 --- a/esp-wifi/src/lib.rs +++ b/esp-wifi/src/lib.rs @@ -105,7 +105,12 @@ extern crate alloc; // MUST be the first module mod fmt; -use common_adapter::{chip_specific::phy_mem_init, init_radio_clock_control, RADIO_CLOCKS}; +use common_adapter::{ + chip_specific::phy_mem_init, + deinit_radio_clock_control, + init_radio_clock_control, + RADIO_CLOCKS, +}; use esp_config::*; use esp_hal as hal; #[cfg(not(feature = "esp32"))] @@ -117,9 +122,18 @@ use hal::{ timer::{timg::Timer as TimgTimer, AnyTimer, PeriodicTimer}, }; #[cfg(feature = "wifi")] -use wifi::WifiError; +use num_traits::FromPrimitive; -use crate::{common_adapter::init_rng, tasks::init_tasks, timer::setup_timer_isr}; +#[cfg(feature = "wifi")] +use crate::{ + binary::include::{self, esp_supplicant_deinit, esp_wifi_deinit_internal, esp_wifi_stop}, + wifi::WifiError, +}; +use crate::{ + common_adapter::init_rng, + tasks::init_tasks, + timer::{setup_timer_isr, shutdown_timer_isr}, +}; mod binary { pub use esp_wifi_sys::*; @@ -396,14 +410,13 @@ pub fn initialize( } info!("esp-wifi configuration {:?}", crate::CONFIG); - crate::common_adapter::chip_specific::enable_wifi_power_domain(); - phy_mem_init(); init_radio_clock_control(radio_clocks); init_rng(rng); init_tasks(); setup_timer_isr(timer.timer())?; + wifi_set_log_verbose(); init_clocks(); @@ -441,15 +454,80 @@ pub fn initialize( } } +/// Deinitializes WiFi and/or BLE +/// +/// After user calls this function, WiFi and/or BLE (depending on what has been +/// initialized) are fully stopped and deinitialized. After that, they should +/// not be used until they have been reinitialized with the `init` function. +/// +/// The function also disables the corresponding interrupts, deinitializes +/// the timer and radio clock, freeing these resources and returning them. +/// +/// Calling this while still using WiFi/BLE will cause crashes or undefined +/// behavior. +/// +/// # Safety +/// Actual implementation assumes that the user takes responsibility for how the +/// function is used. For example, after using this function, user should not +/// use BLE or WiFi stack or controller instances (it is possible to +/// reinitialize communication using the `init` function), not to call +/// `deinit_unsafe` before the first initialization, and so on. Also, there is +/// currently no way to track whether a peripheral has been initialized, +/// so deinitialization is done based on the activated feature (`wifi`, `ble` +/// and/or `coex`). +/// Before deinitializing, chips with NPL bluetooth (esp32c2, esp32c6, esp32h2) +/// users must make sure to stop BLE advertising before. +pub unsafe fn deinit_unchecked( + init: EspWifiInitialization, +) -> Result<(TimeBase, hal::peripherals::RADIO_CLK), InitializationError> { + // Disable coexistence + #[cfg(coex)] + { + unsafe { crate::wifi::os_adapter::coex_disable() }; + unsafe { crate::wifi::os_adapter::coex_deinit() }; + } + + // Deinitialize WiFi + #[cfg(feature = "wifi")] + if init.is_wifi() { + esp_wifi_result!(unsafe { esp_wifi_stop() })?; + esp_wifi_result!(unsafe { esp_wifi_deinit_internal() })?; + esp_wifi_result!(esp_supplicant_deinit())?; + } + + // Deinitialize BLE + #[cfg(feature = "ble")] + if init.is_ble() { + #[cfg(any(esp32, esp32c3, esp32s3))] + crate::ble::btdm::ble_deinit(); + + #[cfg(any(esp32c2, esp32c6, esp32h2))] + crate::ble::npl::ble_deinit(); + } + + shutdown_timer_isr().unwrap(); + crate::preempt::delete_all_tasks(); + + let timer = critical_section::with(|cs| crate::timer::TIMER.borrow_ref_mut(cs).take()) + .ok_or(InitializationError::TimerUnavailable)?; + + let radio_clocks = + deinit_radio_clock_control().ok_or(InitializationError::RadioClockUnavailable)?; + + Ok((timer, radio_clocks)) +} + #[derive(Debug, Clone, Copy)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] -/// Error which can be returned during [`initialize`]. +/// Error which can be returned during [`init`]. pub enum InitializationError { General(i32), #[cfg(feature = "wifi")] WifiError(WifiError), WrongClockConfig, Timer(hal::timer::Error), + TimerUnavailable, + RadioClockUnavailable, } impl From for InitializationError { diff --git a/esp-wifi/src/preempt/mod.rs b/esp-wifi/src/preempt/mod.rs index 27f3fa7e7..be24112b8 100644 --- a/esp-wifi/src/preempt/mod.rs +++ b/esp-wifi/src/preempt/mod.rs @@ -54,7 +54,7 @@ fn next_task() { /// Delete the given task. /// /// This will also free the memory (stack and context) allocated for it. -fn delete_task(task: *mut Context) { +pub(crate) fn delete_task(task: *mut Context) { critical_section::with(|cs| unsafe { let mut ptr = *CTX_NOW.borrow_ref_mut(cs); let initial = ptr; @@ -78,11 +78,40 @@ fn delete_task(task: *mut Context) { }); } +pub(crate) fn delete_all_tasks() { + critical_section::with(|cs| unsafe { + let mut ctx_now_ref = CTX_NOW.borrow_ref_mut(cs); + let current_task = *ctx_now_ref; + + if current_task.is_null() { + return; + } + + let mut task_to_delete = current_task; + + loop { + let next_task = (*task_to_delete).next; + + free((*task_to_delete).allocated_stack as *mut u8); + free(task_to_delete as *mut u8); + + if next_task == current_task { + break; + } + + task_to_delete = next_task; + } + + *ctx_now_ref = core::ptr::null_mut(); + + memory_fence(); + }); +} + pub fn current_task() -> *mut Context { critical_section::with(|cs| unsafe { *CTX_NOW.borrow_ref(cs) }) } -#[cfg(feature = "wifi")] pub fn schedule_task_deletion(task: *mut Context) { use crate::timer::yield_task; diff --git a/esp-wifi/src/timer/mod.rs b/esp-wifi/src/timer/mod.rs index a82404253..681ae3003 100644 --- a/esp-wifi/src/timer/mod.rs +++ b/esp-wifi/src/timer/mod.rs @@ -1,3 +1,7 @@ +use core::cell::RefCell; + +use critical_section::Mutex; + #[cfg_attr(esp32, path = "timer_esp32.rs")] #[cfg_attr(esp32c2, path = "timer_esp32c2.rs")] #[cfg_attr(esp32c3, path = "timer_esp32c3.rs")] @@ -16,6 +20,8 @@ pub use chip_specific::*; use crate::TimeBase; +pub(crate) static TIMER: Mutex>> = Mutex::new(RefCell::new(None)); + pub fn setup_timer_isr(timebase: TimeBase) -> Result<(), esp_hal::timer::Error> { setup_radio_isr(); @@ -27,6 +33,15 @@ pub fn setup_timer_isr(timebase: TimeBase) -> Result<(), esp_hal::timer::Error> Ok(()) } +pub fn shutdown_timer_isr() -> Result<(), esp_hal::timer::Error> { + shutdown_radio_isr(); + + disable_timer()?; + + disable_multitasking(); + Ok(()) +} + #[allow(unused)] pub fn micros_to_ticks(us: u64) -> u64 { us * (TICKS_PER_SECOND / 1_000_000) diff --git a/esp-wifi/src/timer/riscv.rs b/esp-wifi/src/timer/riscv.rs index 7e3b0bc0d..9a3061afc 100644 --- a/esp-wifi/src/timer/riscv.rs +++ b/esp-wifi/src/timer/riscv.rs @@ -1,6 +1,3 @@ -use core::cell::RefCell; - -use critical_section::Mutex; use esp_hal::interrupt::InterruptHandler; #[cfg(any(feature = "esp32c6", feature = "esp32h2"))] use peripherals::INTPRI as SystemPeripheral; @@ -18,13 +15,14 @@ use crate::{ }; /// The timer responsible for time slicing. -static ALARM0: Mutex>> = Mutex::new(RefCell::new(None)); const TIMESLICE_FREQUENCY: fugit::HertzU64 = fugit::HertzU64::from_raw(crate::CONFIG.tick_rate_hz as u64); // Time keeping pub const TICKS_PER_SECOND: u64 = 1_000_000; +use super::TIMER; + pub fn setup_timer(mut alarm0: TimeBase) -> Result<(), esp_hal::timer::Error> { // make sure the scheduling won't start before everything is setup riscv::interrupt::disable(); @@ -34,7 +32,16 @@ pub fn setup_timer(mut alarm0: TimeBase) -> Result<(), esp_hal::timer::Error> { alarm0.start(TIMESLICE_FREQUENCY.into_duration())?; critical_section::with(|cs| { alarm0.enable_interrupt(true); - ALARM0.borrow_ref_mut(cs).replace(alarm0); + TIMER.borrow_ref_mut(cs).replace(alarm0); + }); + + Ok(()) +} + +pub fn disable_timer() -> Result<(), esp_hal::timer::Error> { + critical_section::with(|cs| { + unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false); + unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel().unwrap(); }); Ok(()) @@ -51,10 +58,14 @@ pub fn setup_multitasking() { } } +pub fn disable_multitasking() { + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::FROM_CPU_INTR3); +} + extern "C" fn handler(trap_frame: &mut TrapFrame) { // clear the systimer intr critical_section::with(|cs| { - unwrap!(ALARM0.borrow_ref_mut(cs).as_mut()).clear_interrupt(); + unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).clear_interrupt(); }); task_switch(trap_frame); @@ -70,7 +81,7 @@ extern "C" fn FROM_CPU_INTR3(trap_frame: &mut TrapFrame) { } critical_section::with(|cs| { - let mut alarm0 = ALARM0.borrow_ref_mut(cs); + let mut alarm0 = TIMER.borrow_ref_mut(cs); let alarm0 = unwrap!(alarm0.as_mut()); alarm0.clear_interrupt(); }); diff --git a/esp-wifi/src/timer/timer_esp32.rs b/esp-wifi/src/timer/timer_esp32.rs index 09dc72507..bd33c2def 100644 --- a/esp-wifi/src/timer/timer_esp32.rs +++ b/esp-wifi/src/timer/timer_esp32.rs @@ -22,6 +22,14 @@ pub fn setup_radio_isr() { } } +pub fn shutdown_radio_isr() { + #[cfg(feature = "ble")] + { + interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::RWBT); + interrupt::disable(crate::hal::Cpu::ProCpu, peripherals::Interrupt::BT_BB); + } +} + #[cfg(feature = "ble")] #[allow(non_snake_case)] #[no_mangle] diff --git a/esp-wifi/src/timer/timer_esp32c2.rs b/esp-wifi/src/timer/timer_esp32c2.rs index 452790dcf..631c22902 100644 --- a/esp-wifi/src/timer/timer_esp32c2.rs +++ b/esp-wifi/src/timer/timer_esp32c2.rs @@ -20,6 +20,14 @@ pub fn setup_radio_isr() { } } +pub fn shutdown_radio_isr() { + #[cfg(feature = "ble")] + { + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_TIMER); + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC); + } +} + #[cfg(feature = "wifi")] #[no_mangle] extern "C" fn WIFI_MAC() { diff --git a/esp-wifi/src/timer/timer_esp32c3.rs b/esp-wifi/src/timer/timer_esp32c3.rs index 98be6c3ac..97749bbc1 100644 --- a/esp-wifi/src/timer/timer_esp32c3.rs +++ b/esp-wifi/src/timer/timer_esp32c3.rs @@ -24,6 +24,15 @@ pub fn setup_radio_isr() { } } +pub fn shutdown_radio_isr() { + #[cfg(feature = "ble")] + { + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBT); + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBLE); + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_BB); + } +} + #[cfg(feature = "wifi")] #[no_mangle] extern "C" fn WIFI_MAC() { diff --git a/esp-wifi/src/timer/timer_esp32c6.rs b/esp-wifi/src/timer/timer_esp32c6.rs index 224ad4cb0..4f4e40423 100644 --- a/esp-wifi/src/timer/timer_esp32c6.rs +++ b/esp-wifi/src/timer/timer_esp32c6.rs @@ -33,6 +33,14 @@ pub fn setup_radio_isr() { } } +pub fn shutdown_radio_isr() { + #[cfg(feature = "ble")] + { + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_TIMER); + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC); + } +} + #[cfg(feature = "wifi")] #[no_mangle] extern "C" fn WIFI_MAC() { diff --git a/esp-wifi/src/timer/timer_esp32h2.rs b/esp-wifi/src/timer/timer_esp32h2.rs index 35a74d36f..ade52f9fb 100644 --- a/esp-wifi/src/timer/timer_esp32h2.rs +++ b/esp-wifi/src/timer/timer_esp32h2.rs @@ -18,6 +18,14 @@ pub fn setup_radio_isr() { } } +pub fn shutdown_radio_isr() { + #[cfg(feature = "ble")] + { + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::LP_BLE_TIMER); + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_MAC); + } +} + #[cfg(feature = "ble")] #[no_mangle] extern "C" fn LP_BLE_TIMER() { diff --git a/esp-wifi/src/timer/timer_esp32s2.rs b/esp-wifi/src/timer/timer_esp32s2.rs index c5023d230..5a5052150 100644 --- a/esp-wifi/src/timer/timer_esp32s2.rs +++ b/esp-wifi/src/timer/timer_esp32s2.rs @@ -7,6 +7,10 @@ pub fn setup_radio_isr() { // ble not supported } +pub fn shutdown_radio_isr() { + // ble not supported +} + #[cfg(feature = "wifi")] #[no_mangle] extern "C" fn WIFI_MAC() { diff --git a/esp-wifi/src/timer/timer_esp32s3.rs b/esp-wifi/src/timer/timer_esp32s3.rs index 07d2bb9ec..ed5bbc064 100644 --- a/esp-wifi/src/timer/timer_esp32s3.rs +++ b/esp-wifi/src/timer/timer_esp32s3.rs @@ -1,22 +1,30 @@ #[cfg(any(feature = "wifi", feature = "ble"))] #[allow(unused_imports)] -use crate::hal::{interrupt, peripherals}; +use crate::hal::{interrupt, peripherals::Interrupt}; pub fn setup_radio_isr() { // wifi enabled in set_isr #[cfg(feature = "ble")] { unwrap!(interrupt::enable( - peripherals::Interrupt::BT_BB, + Interrupt::BT_BB, interrupt::Priority::Priority1, )); unwrap!(interrupt::enable( - peripherals::Interrupt::RWBLE, + Interrupt::RWBLE, interrupt::Priority::Priority1, )); } } +pub fn shutdown_radio_isr() { + #[cfg(feature = "ble")] + { + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::BT_BB); + interrupt::disable(crate::hal::Cpu::ProCpu, Interrupt::RWBLE); + } +} + #[cfg(feature = "wifi")] #[no_mangle] extern "C" fn WIFI_MAC() { diff --git a/esp-wifi/src/timer/xtensa.rs b/esp-wifi/src/timer/xtensa.rs index abe045f1f..94a3ca6cc 100644 --- a/esp-wifi/src/timer/xtensa.rs +++ b/esp-wifi/src/timer/xtensa.rs @@ -1,6 +1,3 @@ -use core::cell::RefCell; - -use critical_section::Mutex; use esp_hal::interrupt::InterruptHandler; use crate::{ @@ -10,10 +7,11 @@ use crate::{ }; /// The timer responsible for time slicing. -static TIMER1: Mutex>> = Mutex::new(RefCell::new(None)); const TIMESLICE_FREQUENCY: fugit::HertzU64 = fugit::HertzU64::from_raw(crate::CONFIG.tick_rate_hz as u64); +use super::TIMER; + // Time keeping pub const TICKS_PER_SECOND: u64 = 1_000_000; @@ -31,11 +29,20 @@ pub fn setup_timer(mut timer1: TimeBase) -> Result<(), esp_hal::timer::Error> { timer1.start(TIMESLICE_FREQUENCY.into_duration())?; critical_section::with(|cs| { timer1.enable_interrupt(true); - TIMER1.borrow_ref_mut(cs).replace(timer1); + TIMER.borrow_ref_mut(cs).replace(timer1); }); Ok(()) } +pub fn disable_timer() -> Result<(), esp_hal::timer::Error> { + critical_section::with(|cs| { + unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).enable_interrupt(false); + unwrap!(TIMER.borrow_ref_mut(cs).as_mut()).cancel().unwrap(); + }); + + Ok(()) +} + pub fn setup_multitasking() { unsafe { let enabled = xtensa_lx::interrupt::disable(); @@ -47,9 +54,15 @@ pub fn setup_multitasking() { } } +pub fn disable_multitasking() { + xtensa_lx::interrupt::disable_mask( + 1 << 29, // Disable Software1 + ); +} + fn do_task_switch(context: &mut TrapFrame) { critical_section::with(|cs| { - let mut timer = TIMER1.borrow_ref_mut(cs); + let mut timer = TIMER.borrow_ref_mut(cs); let timer = unwrap!(timer.as_mut()); timer.clear_interrupt(); }); diff --git a/esp-wifi/src/wifi/os_adapter.rs b/esp-wifi/src/wifi/os_adapter.rs index 5b13d69bf..6bf59c8bd 100644 --- a/esp-wifi/src/wifi/os_adapter.rs +++ b/esp-wifi/src/wifi/os_adapter.rs @@ -1704,7 +1704,10 @@ pub unsafe extern "C" fn wifi_delete_queue(queue: *mut crate::binary::c_types::c /// /// ************************************************************************* pub unsafe extern "C" fn coex_deinit() { - warn!("coex_deinit - not implemented"); + trace!("coex_deinit"); + + #[cfg(coex)] + crate::binary::include::coex_deinit(); } /// ************************************************************************** diff --git a/examples/src/bin/wifi_access_point.rs b/examples/src/bin/wifi_access_point.rs index d4171d51e..5cd51f3a1 100644 --- a/examples/src/bin/wifi_access_point.rs +++ b/examples/src/bin/wifi_access_point.rs @@ -53,10 +53,10 @@ fn main() -> ! { ) .unwrap(); - let wifi = peripherals.WIFI; + let mut wifi = peripherals.WIFI; let mut socket_set_entries: [SocketStorage; 3] = Default::default(); let (iface, device, mut controller, sockets) = - create_network_interface(&init, wifi, WifiApDevice, &mut socket_set_entries).unwrap(); + create_network_interface(&init, &mut wifi, WifiApDevice, &mut socket_set_entries).unwrap(); let mut wifi_stack = WifiStack::new(iface, device, sockets, current_millis); let client_config = Configuration::AccessPoint(AccessPointConfiguration { diff --git a/examples/src/bin/wifi_bench.rs b/examples/src/bin/wifi_bench.rs index ae9924840..ced3977ba 100644 --- a/examples/src/bin/wifi_bench.rs +++ b/examples/src/bin/wifi_bench.rs @@ -72,10 +72,10 @@ fn main() -> ! { ) .unwrap(); - let wifi = peripherals.WIFI; + let mut wifi = peripherals.WIFI; let mut socket_set_entries: [SocketStorage; 3] = Default::default(); let (iface, device, mut controller, sockets) = - create_network_interface(&init, wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); + create_network_interface(&init, &mut wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); let wifi_stack = WifiStack::new(iface, device, sockets, current_millis); let client_config = Configuration::Client(ClientConfiguration { diff --git a/examples/src/bin/wifi_coex.rs b/examples/src/bin/wifi_coex.rs index 3c70dba79..061a00e70 100644 --- a/examples/src/bin/wifi_coex.rs +++ b/examples/src/bin/wifi_coex.rs @@ -84,12 +84,12 @@ fn main() -> ! { ) .unwrap(); - let wifi = peripherals.WIFI; + let mut wifi = peripherals.WIFI; let bluetooth = peripherals.BT; let mut socket_set_entries: [SocketStorage; 2] = Default::default(); let (iface, device, mut controller, sockets) = - create_network_interface(&init, wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); + create_network_interface(&init, &mut wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); let wifi_stack = WifiStack::new(iface, device, sockets, current_millis); let client_config = Configuration::Client(ClientConfiguration { diff --git a/examples/src/bin/wifi_dhcp.rs b/examples/src/bin/wifi_dhcp.rs index 63006626a..0e62c64a5 100644 --- a/examples/src/bin/wifi_dhcp.rs +++ b/examples/src/bin/wifi_dhcp.rs @@ -61,10 +61,10 @@ fn main() -> ! { ) .unwrap(); - let wifi = peripherals.WIFI; + let mut wifi = peripherals.WIFI; let mut socket_set_entries: [SocketStorage; 3] = Default::default(); let (iface, device, mut controller, sockets) = - create_network_interface(&init, wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); + create_network_interface(&init, &mut wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); let wifi_stack = WifiStack::new(iface, device, sockets, current_millis); let client_config = Configuration::Client(ClientConfiguration { diff --git a/examples/src/bin/wifi_static_ip.rs b/examples/src/bin/wifi_static_ip.rs index 4f544626b..53ead8154 100644 --- a/examples/src/bin/wifi_static_ip.rs +++ b/examples/src/bin/wifi_static_ip.rs @@ -59,10 +59,10 @@ fn main() -> ! { ) .unwrap(); - let wifi = peripherals.WIFI; + let mut wifi = peripherals.WIFI; let mut socket_set_entries: [SocketStorage; 3] = Default::default(); let (iface, device, mut controller, sockets) = - create_network_interface(&init, wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); + create_network_interface(&init, &mut wifi, WifiStaDevice, &mut socket_set_entries).unwrap(); let mut wifi_stack = WifiStack::new(iface, device, sockets, current_millis); let client_config = Configuration::Client(ClientConfiguration {