-
Notifications
You must be signed in to change notification settings - Fork 354
Open
Labels
bugSomething isn't workingSomething isn't workingchip:esp32s3Issue related to ESP32-S3 chipIssue related to ESP32-S3 chippackage:esp-radioIssues related to the esp-wifi packageIssues related to the esp-wifi package
Description
Bug description
esp32s3 BLE sometime can not advertise after ESP wakeup from light sleep
To Reproduce
Repeat below step multiple times. After waking up from light sleep, the phone sometime can scan the ESP, sometime can not, and sometime the phone has to wait for very long time to can see the ESP (couple minutes)
- Initialize peripherals and ble
- Use phone to scan and connect to ESP
- Disconnect
- Stop advertising
- Enter light sleep
- wakeup from light sleep
This is the test code (base on wifi_embassy_ble example)
//! Embassy BLE Example
//!
//! - starts Bluetooth advertising
//! - offers one service with three characteristics (one is read/write, one is write only, one is
//! read/write/notify)
//! - pressing the boot-button on a dev-board will send a notification if it is subscribed
//% FEATURES: embassy esp-wifi esp-wifi/ble esp-hal/unstable
//% CHIPS: esp32 esp32s3 esp32c2 esp32c3 esp32c6 esp32h2
// Embassy offers another compatible BLE crate [trouble](https://github.com/embassy-rs/trouble/tree/main/examples/esp32) with esp32 examples.
#![no_std]
#![no_main]
use core::cell::RefCell;
use bleps::{
ad_structure::{
AdStructure,
BR_EDR_NOT_SUPPORTED,
LE_GENERAL_DISCOVERABLE,
create_advertising_data,
},
async_attribute_server::AttributeServer,
asynch::Ble,
attribute_server::NotificationData,
gatt,
};
use embassy_executor::Spawner;
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{
clock::CpuClock,
gpio::{Input, InputConfig, Pull},
time,
timer::timg::TimerGroup,
};
use esp_println::println;
use esp_wifi::{EspWifiController, ble::controller::BleConnector, init};
esp_bootloader_esp_idf::esp_app_desc!();
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
#[esp_hal_embassy::main]
async fn main(spawner: Spawner) -> ! {
esp_println::logger::init_logger_from_env();
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
let rtc = esp_hal::rtc_cntl::Rtc::new(peripherals.LPWR);
let timer = esp_hal::rtc_cntl::sleep::TimerWakeupSource::new(core::time::Duration::from_secs(5));
esp_alloc::heap_allocator!(size: 72 * 1024);
let timg0 = TimerGroup::new(peripherals.TIMG0);
let esp_wifi_ctrl = &*mk_static!(EspWifiController<'static>, init(timg0.timer0).unwrap());
let config = InputConfig::default().with_pull(Pull::Down);
cfg_if::cfg_if! {
if #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] {
let button = Input::new(peripherals.GPIO0, config);
} else {
let button = Input::new(peripherals.GPIO9, config);
}
}
cfg_if::cfg_if! {
if #[cfg(feature = "esp32")] {
let timg1 = TimerGroup::new(peripherals.TIMG1);
esp_hal_embassy::init(timg1.timer0);
} else {
use esp_hal::timer::systimer::SystemTimer;
let systimer = SystemTimer::new(peripherals.SYSTIMER);
esp_hal_embassy::init(systimer.alarm0);
}
}
let connector = BleConnector::new(&esp_wifi_ctrl, peripherals.BT);
let now = || time::Instant::now().duration_since_epoch().as_millis();
let ble = Ble::new(connector, now);
println!("Connector created");
spawner.spawn(ble_task(
ble,
rtc,
button,
timer
)).ok();
loop {
embassy_time::Timer::after(embassy_time::Duration::from_secs(1)).await;
println!("Waiting for button press...");
}
}
#[embassy_executor::task]
async fn ble_task(
mut ble: Ble<BleConnector<'static>>,
mut rtc: esp_hal::rtc_cntl::Rtc<'static>,
button: Input<'static>,
timer: esp_hal::rtc_cntl::sleep::TimerWakeupSource<>,
) {
let mut sleep_config = esp_hal::rtc_cntl::sleep::RtcSleepConfig::default();
sleep_config.set_modem_pd_en(false);
sleep_config.set_int_8m_pd_en(false);
sleep_config.set_rtc_peri_pd_en(false);
sleep_config.set_dig_peri_pd_en(false);
sleep_config.set_rtc_fastmem_pd_en(false);
sleep_config.set_rtc_slowmem_pd_en(false);
sleep_config.set_rtc_regulator_fpu(true);
sleep_config.set_xtal_fpu(true);
sleep_config.set_rtc_mem_inf_follow_cpu(true);
sleep_config.set_cpu_pd_en(false);
sleep_config.set_deep_slp(false);
sleep_config.set_deep_slp_reject(false);
sleep_config.set_light_slp_reject(false);
let pin_ref = RefCell::new(button);
let pin_ref = &pin_ref;
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(esp_hal::chip!()),
])
.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: {} {:?}", offset, data);
};
let mut wf2 = |offset: usize, data: &[u8]| {
println!("RECEIVED: {} {:?}", 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 {:?}", 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 rng = bleps::no_rng::NoRng;
let mut srv = AttributeServer::new(&mut ble, &mut gatt_attributes, &mut rng);
let counter = RefCell::new(0u8);
let counter = &counter;
let mut notifier = || {
// TODO how to check if notifications are enabled for the characteristic?
// maybe pass something into the closure which just can query the characteristic
// value probably passing in the attribute server won't work?
async {
pin_ref.borrow_mut().wait_for_rising_edge().await;
let mut data = [0u8; 13];
data.copy_from_slice(b"Notification0");
{
let mut counter = counter.borrow_mut();
data[data.len() - 1] += *counter;
*counter = (*counter + 1) % 10;
}
NotificationData::new(my_characteristic_handle, &data)
}
};
srv.run(&mut notifier).await.unwrap();
println!("stop advertising");
println!("{:?}",ble.cmd_set_le_advertise_enable(false).await);
println!("Enter sleep mode");
embassy_time::Timer::after(embassy_time::Duration::from_millis(1000)).await;
rtc.sleep(&sleep_config, &[&timer]);
embassy_time::Timer::after(embassy_time::Duration::from_millis(1000)).await;
println!("wakeup!");
}
}This is the output log
After waking up, it says it starts to advertise. But the phone can not see it
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:2
load:0x3fce2810,len:0x15a0
load:0x403c8700,len:0x4
load:0x403c8704,len:0xd24
load:0x403cb700,len:0x2f04
entry 0x403c8928
I (30) boot: ESP-IDF v5.4.1-426-g3ad36321ea 2nd stage bootloader
I (30) boot: compile time Apr 24 2025 15:55:11
I (30) boot: Multicore bootloader
I (32) boot: chip revision: v0.1
I (34) boot: efuse block revision: v1.2
I (38) boot.esp32s3: Boot SPI Speed : 40MHz
I (42) boot.esp32s3: SPI Mode : DIO
I (46) boot.esp32s3: SPI Flash Size : 8MB
I (49) boot: Enabling RNG early entropy source...
I (54) boot: Partition Table:
I (56) boot: ## Label Usage Type ST Offset Length
I (63) boot: 0 nvs WiFi data 01 02 00009000 00004000
I (69) boot: 1 otadata OTA data 01 00 0000d000 00002000
I (76) boot: 2 phy_init RF data 01 01 0000f000 00001000
I (82) boot: 3 factory factory app 00 00 00010000 00100000
I (89) boot: 4 ota_0 OTA app 00 10 00110000 00100000
I (95) boot: 5 ota_1 OTA app 00 11 00210000 00100000
I (102) boot: End of partition table
I (105) boot: Defaulting to factory image
I (109) esp_image: segment 0: paddr=00010020 vaddr=3c000020 size=0b250h ( 45648) map
I (128) esp_image: segment 1: paddr=0001b278 vaddr=3fc8f418 size=0105ch ( 4188) load
I (129) esp_image: segment 2: paddr=0001c2dc vaddr=40378000 size=03d3ch ( 15676) load
I (136) esp_image: segment 3: paddr=00020020 vaddr=42010020 size=31638h (202296) map
I (189) esp_image: segment 4: paddr=00051660 vaddr=4037bd3c size=036d8h ( 14040) load
I (196) boot: Loaded app from partition at offset 0x10000
I (196) boot: Disabling RNG early entropy source...
INFO - esp-wifi configuration EspWifiConfig { rx_queue_size: 5, tx_queue_size: 3, static_rx_buf_num: 10, dynamic_rx_buf_num: 32, static_tx_buf_num: 0, dynamic_tx_buf_num: 32, ampdu_rx_enable: true, ampdu_tx_enable: true, amsdu_tx_enable: false, rx_ba_win: 6, max_burst_size: 1, country_code: "CN", country_code_operating_class: 0, mtu: 1492, tick_rate_hz: 100, listen_interval: 3, beacon_timeout: 6, ap_beacon_timeout: 300, failure_retry_cnt: 1, scan_method: 0 }
Connector created
Ok(CommandComplete { num_packets: 5, opcode: 3075, data: [0] })
Ok(CommandComplete { num_packets: 5, opcode: 8198, data: [0] })
Ok(CommandComplete { num_packets: 5, opcode: 8200, data: [0] })
Ok(CommandComplete { num_packets: 5, opcode: 8202, data: [0] })
started advertising
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
WARN - Ignoring unknown le-meta event 03 data = [00, 01, 00, 06, 00, 00, 00, f4, 01]
WARN - Ignoring unknown le-meta event 03 data = [00, 01, 00, 27, 00, 00, 00, f4, 01]
Waiting for button press...
Waiting for button press...
Waiting for button press...
stop advertising
Ok(CommandComplete { num_packets: 5, opcode: 8202, data: [0] })
Enter sleep mode
Waiting for button press...
Waiting for button press...
wakeup!
Ok(CommandComplete { num_packets: 5, opcode: 3075, data: [0] })
Ok(CommandComplete { num_packets: 5, opcode: 8198, data: [0] })
Ok(CommandComplete { num_packets: 5, opcode: 8200, data: [0] })
Ok(CommandComplete { num_packets: 5, opcode: 8202, data: [0] })
started advertising
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...
Waiting for button press...Expected behavior
After wakeup, the BLE should be able to advertise normally
Environment
- Target device: ESP32-S3
- Crate name and version:
esp-hal
branch: main
commit: 818d309
link: https://github.com/esp-rs/esp-hal/tree/818d30972db7dd6fc50a732efa3f1a0e5c19a7e3
TuEmb
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingchip:esp32s3Issue related to ESP32-S3 chipIssue related to ESP32-S3 chippackage:esp-radioIssues related to the esp-wifi packageIssues related to the esp-wifi package
Type
Projects
Status
Todo