feat(wifi): implement a mutex for the wifi_controller and add it to the WifiService state

This commit is contained in:
2026-08-27 23:12:30 -05:00
parent 68412464ec
commit 15fad17fab
+41 -33
View File
@@ -1,27 +1,34 @@
use defmt::{error, info}; use defmt::{error, info};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_futures::select::{Either, select};
use embassy_net::{Runner, Stack}; use embassy_net::{Runner, Stack};
use embassy_sync::signal::Signal; use embassy_sync::{
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, rpc_service::RpcService}; blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, rpc_service::RpcService,
};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_hal::peripherals::WIFI; use esp_hal::peripherals::WIFI;
use esp_radio::wifi::sta::StationConfig; 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<CriticalSectionRawMutex, WifiService, 64> = RpcService::new(); pub static WIFI_SERVICE: RpcService<CriticalSectionRawMutex, WifiService, 64> = RpcService::new();
pub struct WifiService { pub struct WifiService {
pub net_stack: Stack<'static> pub net_stack: Stack<'static>,
wifi_controller: &'static Mutex<CriticalSectionRawMutex, WifiController<'static>>,
} }
impl WifiService { impl WifiService {
pub async fn set_station_config(config: esp_radio::wifi::Config) { pub async fn set_station_config(
WIFI_HANDLER_RPC.signal(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) { pub fn set_dhcp_config(&self, config: embassy_net::DhcpConfig) {
self.net_stack.set_config_v4(embassy_net::ConfigV4::Dhcp(config)); 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, seed,
); );
spawner.spawn(net_task(net_runner).unwrap()); let service = WifiService {
spawner.spawn(wifi_handler(wifi_controller).unwrap()); net_stack: net_stack,
wifi_controller: crate::mk_static!(Mutex<CriticalSectionRawMutex, WifiController<'static>>, 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(ip_logger(net_stack).unwrap());
spawner.spawn(handler(net_stack).unwrap());
net_stack net_stack
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn handler(net_stack: Stack<'static>) { async fn handler(mut service: WifiService) -> ! {
WIFI_SERVICE.run(&mut WifiService {net_stack: net_stack}).await; WIFI_SERVICE.run(&mut service).await
} }
static WIFI_HANDLER_RPC: Signal<CriticalSectionRawMutex, esp_radio::wifi::Config> = Signal::new();
#[embassy_executor::task] #[embassy_executor::task]
async fn wifi_handler(mut controller: WifiController<'static>) { async fn connection_handler(
let connection = async |controller: &mut WifiController<'static>| { controller: &'static Mutex<CriticalSectionRawMutex, WifiController<'static>>,
) -> ! {
loop {
info!("Connecting to WiFi..."); info!("Connecting to WiFi...");
match controller.connect_async().await { match controller.lock().await.connect_async().await {
Ok(info) => { Ok(info) => {
info!("Wifi connected to {:?}", info); info!("Wifi connected to {:?}", info);
// wait until we're no longer connected // wait until we're no longer connected
let info = controller.wait_for_disconnect_async().await.ok(); // TODO: reimplement the wait for disconnect
info!("Disconnected: {:?}", info); // let info = controller
// .lock()
// .await
// .wait_for_disconnect_async()
// .await
// .ok();
// info!("Disconnected: {:?}", info);
} }
Err(e) => { Err(e) => {
error!("Failed to connect to wifi: {:?}", 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] #[embassy_executor::task]
async fn ip_logger(net_stack: Stack<'static>) { async fn ip_logger(net_stack: Stack<'static>) -> ! {
loop { loop {
info!("Getting IP address..."); info!("Getting IP address...");
net_stack.wait_config_up().await; net_stack.wait_config_up().await;
@@ -120,6 +128,6 @@ async fn ip_logger(net_stack: Stack<'static>) {
} }
#[embassy_executor::task] #[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 runner.run().await
} }