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
This commit is contained in:
Kirill Mikhailov 2024-10-04 14:16:52 +02:00 committed by GitHub
parent 00ad9b5eed
commit a4fe5e6e63
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 359 additions and 47 deletions

View File

@ -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

View File

@ -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;

View File

@ -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 {

View File

@ -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() {

View File

@ -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<hal::peripherals::RADIO_CLK> {
unsafe { RADIO_CLOCKS.take() }
}
/// **************************************************************************
/// Name: esp_semphr_create
///

View File

@ -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<hal::timer::Error> for InitializationError {

View File

@ -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;

View File

@ -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<RefCell<Option<TimeBase>>> = 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)

View File

@ -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<RefCell<Option<TimeBase>>> = 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();
});

View File

@ -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]

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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() {

View File

@ -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<RefCell<Option<TimeBase>>> = 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();
});

View File

@ -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();
}
/// **************************************************************************

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {