-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BLE Device disconnects when second embassy task starts #222
Comments
That's an interesting project! Seems like something is blocking (for too long) and the BLE stack doesn't get a chance to process the HCI packets. I used the #[embassy_executor::task]
async fn second_task() {
loop {
Timer::after(Duration::from_secs(1)).await;
println!("ping");
}
} And launch the task together with the BLE task ( I see the output printed from the Maybe you could try to simplify your second task step by step until to get back to a "working" state. |
Thank you very much for your answer! #[embassy_executor::task]
pub async fn run(thermo: ThermoControl<ThermoToggler>) {
loop {
let requested_state = SHARED.wait().await;
let mut i = 0;
loop {
i += 1;
TEMPERATURE_SIGNAL.signal(i);
Timer::after(Duration::from_secs(1)).await;
}
}
} in order to signal notifier closure called by AttributeServer let mut notifier = async || {
let temperature = TEMPERATURE_SIGNAL.wait().await;
let mut data = [0u8; 2];
let temperature: &[u8] = unsafe { any_as_u8_slice(&temperature)};
data.copy_from_slice(temperature);
NotificationData::new(temperature_handle, &data)
};
srv.run(&mut notifier).await.unwrap(); Despite implementing this approach, the problem still persists - the symptoms are the same as before |
I tried to resemble what your code does by modifying the #![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
#![feature(async_closure)]
use core::cell::RefCell;
use bleps::{
ad_structure::{
create_advertising_data, AdStructure, BR_EDR_NOT_SUPPORTED, LE_GENERAL_DISCOVERABLE,
},
async_attribute_server::AttributeServer,
asynch::Ble,
attribute_server::NotificationData,
gatt,
};
use embassy_executor::Executor;
use embassy_executor::_export::StaticCell;
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, signal::Signal};
use embassy_time::{Duration, Timer};
use embedded_hal_async::digital::Wait;
use esp_backtrace as _;
use esp_println::{logger::init_logger, println};
use esp_wifi::{
ble::controller::asynch::BleConnector, initialize, EspWifiInitFor, EspWifiInitialization,
};
use examples_util::hal;
use examples_util::BootButton;
use hal::{
clock::{ClockControl, CpuClock},
embassy,
peripherals::*,
prelude::*,
radio::Bluetooth,
timer::TimerGroup,
Rng, Rtc, IO,
};
static SIGNAL: Signal<CriticalSectionRawMutex, u32> = Signal::new();
#[embassy_executor::task]
async fn second_task(mut pin: BootButton) {
let mut i = 0;
loop {
pin.wait_for_rising_edge().await.unwrap();
//Timer::after(Duration::from_millis(3000)).await;
println!("ping");
SIGNAL.signal(i);
i += 1;
}
}
#[embassy_executor::task]
async fn run(init: EspWifiInitialization, mut bluetooth: Bluetooth) {
let connector = BleConnector::new(&init, &mut bluetooth);
let mut ble = Ble::new(connector, esp_wifi::current_millis);
println!("Connector created");
loop {
println!("{:?}", ble.init().await);
println!("{:?}", ble.cmd_set_le_advertising_parameters().await);
println!(
"{:?}",
ble.cmd_set_le_advertising_data(
create_advertising_data(&[
AdStructure::Flags(LE_GENERAL_DISCOVERABLE | BR_EDR_NOT_SUPPORTED),
AdStructure::ServiceUuids16(&[Uuid::Uuid16(0x1809)]),
AdStructure::CompleteLocalName(examples_util::SOC_NAME),
])
.unwrap()
)
.await
);
println!("{:?}", ble.cmd_set_le_advertise_enable(true).await);
println!("started advertising");
let mut rf = |_offset: usize, data: &mut [u8]| {
data[..20].copy_from_slice(&b"Hello Bare-Metal BLE"[..]);
17
};
let mut wf = |offset: usize, data: &[u8]| {
println!("RECEIVED: {} {:x?}", offset, data);
};
let mut wf2 = |offset: usize, data: &[u8]| {
println!("RECEIVED: {} {:x?}", offset, data);
};
let mut rf3 = |_offset: usize, data: &mut [u8]| {
data[..5].copy_from_slice(&b"Hola!"[..]);
5
};
let mut wf3 = |offset: usize, data: &[u8]| {
println!("RECEIVED: Offset {}, data {:x?}", offset, data);
};
gatt!([service {
uuid: "937312e0-2354-11eb-9f10-fbc30a62cf38",
characteristics: [
characteristic {
uuid: "937312e0-2354-11eb-9f10-fbc30a62cf38",
read: rf,
write: wf,
},
characteristic {
uuid: "957312e0-2354-11eb-9f10-fbc30a62cf38",
write: wf2,
},
characteristic {
name: "my_characteristic",
uuid: "987312e0-2354-11eb-9f10-fbc30a62cf38",
notify: true,
read: rf3,
write: wf3,
},
],
},]);
let mut srv = AttributeServer::new(&mut ble, &mut gatt_attributes);
let mut notifier = async || {
let x = SIGNAL.wait().await;
let mut data = [0u8; 13];
data.copy_from_slice(b"Notification0");
data[data.len() - 1] = (x as u8) + b'0';
NotificationData::new(my_characteristic_handle, &data)
};
srv.run(&mut notifier).await.unwrap();
}
}
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
#[entry]
fn main() -> ! {
init_logger(log::LevelFilter::Info);
let peripherals = Peripherals::take();
let system = examples_util::system!(peripherals);
let mut peripheral_clock_control = system.peripheral_clock_control;
let clocks = examples_util::clocks!(system);
examples_util::rtc!(peripherals);
let timer = examples_util::timer!(peripherals, clocks, peripheral_clock_control);
let init = initialize(
EspWifiInitFor::Ble,
timer,
Rng::new(peripherals.RNG),
system.radio_clock_control,
&clocks,
)
.unwrap();
let button = examples_util::boot_button!(peripherals);
// Async requires the GPIO interrupt to wake futures
hal::interrupt::enable(
hal::peripherals::Interrupt::GPIO,
hal::interrupt::Priority::Priority1,
)
.unwrap();
let bluetooth = examples_util::get_bluetooth!(peripherals);
let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks, &mut peripheral_clock_control);
embassy::init(&clocks, timer_group0.timer0);
let executor = EXECUTOR.init(Executor::new());
executor.run(|spawner| {
spawner.spawn(run(init, bluetooth)).ok();
spawner.spawn(second_task(button)).ok();
});
} |
Thank you! Thanks to you, I realized that I hadn't enabled async and ble features while building the software. When I incorporated these, everything worked as expected. |
Problem: The BLE device disconnects when the second embassy task starts.
Hardware: WeAct ESP32-C3FH4 & Android 11 Phone with nrfConnect app.
Code: The code I am using can be found at: Thermo-esp Repo
Logs: Logs from ESP and nrfConnect can be found here: Logs
Description: I am creating a simple hotplate with two-state control, predefined heating modes, and a BLE connection. To implement this, I decided to use the embassy and created a separate task to control the hotplate. The control task does not perform any heavy lifting; it waits, reads data from the MAX6675 thermocouple frontend via SPI, performs some easy calculations, and toggles a pin. However, I have observed that when the control task is unblocked, it seems like the BLE stack task gets starved. The pooling of events appears to be unpredictable, with some events stopping, and then suddenly all events being processed at once with a DisconnectComplete event at the end. This behavior is clearly visible in the logs. After disconnect, I am still unable to reconnect to the device.
The text was updated successfully, but these errors were encountered: