You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When there are two parallel async tasks and each of those tasks tries to Peripherals::take() the code crashes on the very moment a second task invokes that method. It seems the issue is tied to atomics somehow however I'm not familiar nor with MCUs in general nor with ESP-IDF architecture to elaborate on that.
The MCU used: ESP32-PICO-D4 on a LILYGO dev board.
I have a demo program that setups a WiFi hotspot and runs UART listener in parallel, the idea is to have a board connected to another device via serial and control it from a laptop/phone for a limited timespan (kind of a first-time-setup scenario), however the panic could be reproduced on any other example which includes the parallel async tasks scenario. Here is my sample code (also adding demo.zip with a full project):
use core::convert::TryInto;use edge_executor::LocalExecutor;use embedded_svc::wifi::{self,AccessPointConfiguration,AuthMethod};use esp_idf_svc::{
eventloop::EspSystemEventLoop, hal::uart::AsyncUartRxDriver, nvs::EspDefaultNvsPartition,
timer::EspTaskTimerService, wifi::EspWifi,};use esp_idf_svc::{
hal::{
gpio,
prelude::Peripherals,
task,
timer::{TimerConfig,TimerDriver},
uart::{self},
units::Hertz,},
wifi::AsyncWifi,};use futures;use log::*;constSSID:&str = env!("WIFI_SSID");constPASSWORD:&str = env!("WIFI_PASS");fnmain() -> anyhow::Result<()>{
esp_idf_svc::sys::link_patches();
esp_idf_svc::log::EspLogger::initialize_default();let local_ex:LocalExecutor = Default::default();let wifi_task = local_ex.spawn(asyncmove{let _ = setup_wifi().await;});let uart_task = local_ex.spawn(asyncmove{let _ = read_uart(Hertz(400_000)).await;});
task::block_on(local_ex.run(async{ futures::join!(wifi_task, uart_task)}));Ok(())}asyncfnsetup_wifi(){println!("Accessing peripherals");let peripherals = Peripherals::take().expect("Can not access peripherals");let sys_loop = EspSystemEventLoop::take().expect("Can not access system loop");let nvs = EspDefaultNvsPartition::take().expect("Can not access NVS partition");let timer_service = EspTaskTimerService::new().expect("Can not create task timer service");letmut wifi = AsyncWifi::wrap(EspWifi::new(peripherals.modem, sys_loop.clone(),Some(nvs)).expect("Can not create ESP WiFi"),
sys_loop,
timer_service,).expect("Can not create WiFi");let wifi_configuration = wifi::Configuration::AccessPoint(AccessPointConfiguration{ssid:SSID.try_into().unwrap(),ssid_hidden:false,auth_method:AuthMethod::WPA2Personal,password:PASSWORD.try_into().unwrap(),
..Default::default()});
wifi.set_configuration(&wifi_configuration).expect("Can not set WiFi configuration");
wifi.start().await.expect("Can not start WiFi");
wifi.wait_netif_up().await.expect("Can not start net interface");info!("Created Wi-Fi with WIFI_SSID `{}` and WIFI_PASS `{}`",SSID,PASSWORD);println!("Initializing timer");letmut timer = TimerDriver::new(peripherals.timer01,&TimerConfig::new()).expect("Can not create timer driver");println!("Awaiting 10 seconds");
timer
.delay(timer.tick_hz()*10).await.expect("Can not delay");
wifi.stop().await.expect("Can not stop WiFi");}asyncfnread_uart<'t>(baudrate:Hertz){println!("Starting UART listener");let peripherals = Peripherals::take().unwrap();let rx = peripherals.pins.gpio13;let config = uart::config::Config::new().baudrate(baudrate);println!("Creating UART driver");let serial = AsyncUartRxDriver::new(
peripherals.uart1,
rx,Option::<gpio::Gpio0>::None,Option::<gpio::Gpio1>::None,&config,).expect("Can not create UART driver");letmut buf = [0_u8;1];loop{let _ = serial.read(&mut buf).await;println!("Read 0x{:02x}", buf[0]);}}
well take() can only called once. As it "takes out the peripheral tree", From that central struct you then hand out the handles where you need. If you call it a second time you will get a None. And since you are unwrapping it just panics
well take() can only called once. As it "takes out the peripheral tree", From that central struct you then hand out the handles where you need. If you call it a second time you will get a None. And since you are unwrapping it just panics
Thank you, I've just put the drivers creation on top of the main with a single call to the Peripherals::take and now it's working. Sorry for a false alarm, I'm closing the issue.
When there are two parallel async tasks and each of those tasks tries to
Peripherals::take()
the code crashes on the very moment a second task invokes that method. It seems the issue is tied to atomics somehow however I'm not familiar nor with MCUs in general nor with ESP-IDF architecture to elaborate on that.The MCU used: ESP32-PICO-D4 on a LILYGO dev board.
I have a demo program that setups a WiFi hotspot and runs UART listener in parallel, the idea is to have a board connected to another device via serial and control it from a laptop/phone for a limited timespan (kind of a first-time-setup scenario), however the panic could be reproduced on any other example which includes the parallel async tasks scenario. Here is my sample code (also adding demo.zip with a full project):
The trace I have:
The text was updated successfully, but these errors were encountered: