From 15fad17fab3c606e74ae818e37a3ee2d92808ab0 Mon Sep 17 00:00:00 2001 From: Reed Krantz Date: Thu, 27 Aug 2026 23:12:30 -0500 Subject: [PATCH] feat(wifi): implement a mutex for the wifi_controller and add it to the WifiService state --- src/wifi.rs | 74 +++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/src/wifi.rs b/src/wifi.rs index 6fecd56..12d2ecc 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -1,27 +1,34 @@ use defmt::{error, info}; use embassy_executor::Spawner; -use embassy_futures::select::{Either, select}; use embassy_net::{Runner, Stack}; -use embassy_sync::signal::Signal; -use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, rpc_service::RpcService}; +use embassy_sync::{ + blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, rpc_service::RpcService, +}; use embassy_time::{Duration, Timer}; use esp_hal::peripherals::WIFI; use esp_radio::wifi::sta::StationConfig; -use esp_radio::wifi::{ControllerConfig, Interface, WifiController}; +use esp_radio::wifi::{ControllerConfig, Interface, WifiController, WifiError}; pub static WIFI_SERVICE: RpcService = RpcService::new(); pub struct WifiService { - pub net_stack: Stack<'static> + pub net_stack: Stack<'static>, + wifi_controller: &'static Mutex>, } impl WifiService { - pub async fn set_station_config(config: esp_radio::wifi::Config) { - WIFI_HANDLER_RPC.signal(config); + pub async fn set_station_config( + &self, + config: esp_radio::wifi::Config, + ) -> Result<(), WifiError> { + let mut controller = self.wifi_controller.lock().await; + controller.set_config(&config)?; + Ok(()) } - pub async fn set_dhcp_config(&self, config: embassy_net::DhcpConfig) { - self.net_stack.set_config_v4(embassy_net::ConfigV4::Dhcp(config)); + pub fn set_dhcp_config(&self, config: embassy_net::DhcpConfig) { + self.net_stack + .set_config_v4(embassy_net::ConfigV4::Dhcp(config)); } } @@ -51,53 +58,54 @@ pub fn start_wifi(spawner: Spawner, wifi: WIFI<'static>) -> Stack<'static> { seed, ); - spawner.spawn(net_task(net_runner).unwrap()); - spawner.spawn(wifi_handler(wifi_controller).unwrap()); + let service = WifiService { + net_stack: net_stack, + wifi_controller: crate::mk_static!(Mutex>, Mutex::new(wifi_controller)), + }; + + spawner.spawn(net_handler(net_runner).unwrap()); + spawner.spawn(connection_handler(service.wifi_controller).unwrap()); + spawner.spawn(handler(service).unwrap()); spawner.spawn(ip_logger(net_stack).unwrap()); - spawner.spawn(handler(net_stack).unwrap()); net_stack } #[embassy_executor::task] -async fn handler(net_stack: Stack<'static>) { - WIFI_SERVICE.run(&mut WifiService {net_stack: net_stack}).await; +async fn handler(mut service: WifiService) -> ! { + WIFI_SERVICE.run(&mut service).await } -static WIFI_HANDLER_RPC: Signal = Signal::new(); - #[embassy_executor::task] -async fn wifi_handler(mut controller: WifiController<'static>) { - let connection = async |controller: &mut WifiController<'static>| { +async fn connection_handler( + controller: &'static Mutex>, +) -> ! { + loop { info!("Connecting to WiFi..."); - match controller.connect_async().await { + match controller.lock().await.connect_async().await { Ok(info) => { info!("Wifi connected to {:?}", info); // wait until we're no longer connected - let info = controller.wait_for_disconnect_async().await.ok(); - info!("Disconnected: {:?}", info); + // TODO: reimplement the wait for disconnect + // let info = controller + // .lock() + // .await + // .wait_for_disconnect_async() + // .await + // .ok(); + // info!("Disconnected: {:?}", info); } Err(e) => { error!("Failed to connect to wifi: {:?}", e); } } - }; - - loop { - if let Either::First(req) = - select(WIFI_HANDLER_RPC.wait(), connection(&mut controller)).await - { - if let Some(err) = controller.set_config(&req).err() { - error!("Wifi controller failed to set a new config: {:?}", err) - } - } } } #[embassy_executor::task] -async fn ip_logger(net_stack: Stack<'static>) { +async fn ip_logger(net_stack: Stack<'static>) -> ! { loop { info!("Getting IP address..."); net_stack.wait_config_up().await; @@ -120,6 +128,6 @@ async fn ip_logger(net_stack: Stack<'static>) { } #[embassy_executor::task] -async fn net_task(mut runner: Runner<'static, Interface<'static>>) { +async fn net_handler(mut runner: Runner<'static, Interface<'static>>) -> ! { runner.run().await }