Open oleander opened 1 year ago
I have checked the code you have attached. I assume that the error is due to the initialization process on the BLE server side being executed while the BLE client code is running.
By creating the keyboard
right after block_on
, it worked without error in my environment.
The code I changed is as follows.
#![no_main]
#![feature(never_type)]
extern crate esp_idf_hal;
extern crate lazy_static;
extern crate log;
mod keyboard;
use embassy_time::Duration;
use embassy_time::Timer;
use esp32_nimble::utilities::{mutex::Mutex, BleUuid, BleUuid::Uuid16};
use esp32_nimble::{BLEClient, BLEDevice};
use esp_idf_hal::task::block_on;
use keyboard::Keyboard;
use log::{info, warn};
use std::sync::Arc;
const SERVICE_UUID: BleUuid = Uuid16(0x1812);
const CHAR_UUID: BleUuid = Uuid16(0x2A4D);
const BLE_BUTTONS_NAME: &str = "tob";
#[no_mangle]
fn app_main() {
esp_idf_sys::link_patches();
esp_idf_svc::log::EspLogger::initialize_default();
esp_idf_svc::timer::embassy_time::driver::link();
info!("Setup connection to BLE buttons");
block_on(async {
let keyboard = Mutex::new(Keyboard::new());
let device = BLEDevice::take();
let scan = device.get_scan();
let connect_device = Arc::new(Mutex::new(None));
let connect_device_clone = Arc::clone(&connect_device);
scan.active_scan(true).interval(490).window(450).on_result(move |found_device| {
if !found_device.is_advertising_service(&SERVICE_UUID) {
return;
}
if !found_device.name().starts_with(BLE_BUTTONS_NAME) {
return;
}
info!("Found device: {:?}", found_device.name());
*connect_device_clone.lock() = Some(found_device.clone());
BLEDevice::take().get_scan().stop().expect("Failed to stop scan");
});
scan.start(i32::MAX).await.expect("Failed to start scan");
let Some(device) = &*connect_device.lock() else {
return warn!("No device found");
};
let mut client = BLEClient::new();
client.connect(device.addr()).await.expect("Failed to connect to device");
let service = client.get_service(SERVICE_UUID).await.expect("Failed to get service");
let characteristic = service.get_characteristic(CHAR_UUID).await.expect("Failed to get characteristic");
characteristic
.on_notify(move |_data| {
info!("Received notification from device");
let mut keyboard = keyboard.lock();
if keyboard.connected() {
keyboard.write("Hello world");
}
})
.subscribe_notify(false)
.await
.expect("Failed to subscribe to notifications");
info!("Waiting for notifications ...");
loop {
Timer::after(Duration::from_secs(1)).await;
}
});
}
Thank you for your guidance. Your solution helped me overcome the initial challenge, but it led to a series of new issues, primarily stemming from race conditions within Nimble. Your code operates perfectly at first when the keyboard has not yet formed a cached connection with the phone. However, post-connection and subsequent ESP restarts trigger a race condition between the server (keyboard) and client, resulting in unpredictable outcomes.
To tackle this, I reverted to using Arduino-Nimble, which I am more familiar with. A pivotal realization was the need for the client and server to independently complete their connection sequences to prevent interference and undefined behaviour.
Initially, I mistakenly assumed that awaiting the onConnected
event from BLEClient
& BLEServer
was sufficient. However, the critical point in the process is completing the MTU (Maximum Transmission Unit) negotiation, the proper final step in the connection sequence.
In light of the ESP-IDF documentation on multi-connection GATT clients, I recognized the importance of waiting for the 'Configure MTU size' stage to conclude before safely alternating between client and server modes. This understanding is crucial for a stable connection process. The documentation provides a detailed explanation of the sequence, emphasizing the significance of each step, from initiating a connection request to negotiating connection parameters and, finally, the MTU configuration.
Using NimBLEClientCallbacks
and NimBLEServerCallbacks
, I implemented the onAuthenticationComplete
callback. This callback is essential as it signifies the end of the pairing process, a critical point to ensure the stability of the connection.
Below is an unrefined version of my Nimble-Arduino example. It uses two semaphores to maintain atomicity between a successful connection and the handshake of parameters. My ultimate goal is to adapt this solution to Rust, but that's a project for next year.
I am open to any feedback or insights you may have.
// src/main.cpp
#include <BleKeyboard.h>
#include <Arduino.h>
#include <BleKeyboard.h>
#include <NimBLEDevice.h>
#include <NimBLEScan.h>
#include <NimBLEUtils.h>
#include <esp_task_wdt.h>
#include <stdarg.h>
#include <stdlib.h>
#include <vector>
#define SCAN_DURATION 5 * 60 // in seconds
#define SCAN_INTERVAL 500 // in ms
#define SCAN_WINDOW 450 // in ms
#define SERIAL_BAUD_RATE 115200
#define DEVICE_BATTERY 100
#define CLIENT_NAME "My Client"
#define DEVICE_NAME "u701"
#define DEVICE_MANUFACTURER "HVA"
NimBLEAddress serverAddress(0xAAAAACCCBBBB, BLE_ADDR_RANDOM);
static NimBLEUUID serviceUUID("1812");
static NimBLEUUID charUUID("2a4d");
void restart(const char *format, ...) {
// ...
ESP.restart();
}
SemaphoreHandle_t incommingClientSemaphore = xSemaphoreCreateBinary();
SemaphoreHandle_t outgoingClientSemaphore = xSemaphoreCreateBinary();
BleKeyboard keyboard(DEVICE_NAME, DEVICE_MANUFACTURER, DEVICE_BATTERY);
static NimBLEClient *pClient;
static void onEvent(BLERemoteCharacteristic *_, uint8_t *data, size_t length, bool isNotify) {
if (!isNotify) {
return;
}
c_on_event(data, length);
}
class ClientCallbacks : public NimBLEClientCallbacks {
void onConnect(NimBLEClient *pClient) {
Serial.println("Connected to Terrain Command");
Serial.println("Update connection parameters");
pClient->updateConnParams(120, 120, 0, 1);
};
void onDisconnect(NimBLEClient *pClient) {
restart("Terrain Command disconnected");
};
bool onConnParamsUpdateRequest(NimBLEClient *pClient, const ble_gap_upd_params *params) {
Serial.println("Connection parameters update request received");
// ...
return true;
};
/** Pairing process complete, we can check the results in ble_gap_conn_desc */
void onAuthenticationComplete(ble_gap_conn_desc *desc) {
Serial.println("Connection with Terrain Command established");
// ...
Serial.println("Release Terrain Command semaphore (input) (semaphore)");
xSemaphoreGive(incommingClientSemaphore);
};
};
/** Define a class to handle the callbacks when advertisments are received */
class AdvertisedDeviceCallbacks : public NimBLEAdvertisedDeviceCallbacks {
void onResult(NimBLEAdvertisedDevice *advertisedDevice) {
Serial.print(".");
if (!advertisedDevice->isAdvertisingService(serviceUUID)) {
return;
} else if (advertisedDevice->getAddress() != serverAddress) {
return;
} else {
Serial.println("\nFound the Terrain Command");
}
auto addr = advertisedDevice->getAddress();
pClient = NimBLEDevice::createClient(addr);
advertisedDevice->getScan()->stop();
};
};
AdvertisedDeviceCallbacks advertisedDeviceCallbacks;
ClientCallbacks clientCallbacks;
extern "C" void main_app() {
esp_task_wdt_add(NULL);
initArduino();
Serial.begin(SERIAL_BAUD_RATE);
Serial.println("Starting ESP32 BLE Proxy");
NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND);
NimBLEDevice::setPower(ESP_PWR_LVL_N0);
NimBLEDevice::init(DEVICE_NAME);
// Setup HID keyboard and wait for the client to connect
// A wrapper around onAuthenticationComplete
keyboard.whenClientConnects([](ble_gap_conn_desc *_desc) {
Serial.println("Client connected to the keyboard");
Serial.println("Release keyboard semaphore (output) (semaphore)");
xSemaphoreGive(outgoingClientSemaphore);
});
Serial.println("Broadcasting BLE keyboard");
keyboard.begin();
Serial.println("Wait for the keyboard to connect (output) (semaphore)");
xSemaphoreTake(outgoingClientSemaphore, portMAX_DELAY);
Serial.println("Starting BLE scan for the Terrain Command");
auto pScan = NimBLEDevice::getScan();
pScan->setAdvertisedDeviceCallbacks(&advertisedDeviceCallbacks);
pScan->setInterval(SCAN_INTERVAL);
pScan->setWindow(SCAN_WINDOW);
pScan->setActiveScan(true);
pScan->setMaxResults(0);
pScan->start(SCAN_DURATION, false);
if (!pClient) {
restart("The Terrain Command was not found");
}
pClient->setClientCallbacks(&clientCallbacks, false);
// other config options
Serial.println("Wait for the Terrain Command to establish connection (input)");
if (!pClient->connect()) {
restart("Could not connect to the Terrain Command");
} else {
Serial.println("Successfully connected to the Terrain Command");
}
Serial.println("Wait for the Terrain Command to authenticate (input) (semaphore)");
xSemaphoreTake(incommingClientSemaphore, portMAX_DELAY);
Serial.println("Fetching service from the Terrain Command ...");
auto pSvc = pClient->getService(serviceUUID);
if (!pSvc) {
Serial.println("Failed to find our service UUID");
Serial.println("Will disconnect the device");
pClient->disconnect();
restart("Device has been manually disconnected");
}
Serial.println("Fetching all characteristics from the Terrain Command ...");
auto pChrs = pSvc->getCharacteristics(true);
if (!pChrs) {
Serial.println("Failed to find our characteristic UUID");
Serial.println("Will disconnect the device");
pClient->disconnect();
restart("Device has been manually disconnected");
}
for (auto &chr: *pChrs) {
if (!chr->canNotify()) {
Serial.println("Characteristic cannot notify, skipping");
continue;
}
if (!chr->getUUID().equals(charUUID)) {
Serial.println("Characteristic UUID does not match, skipping");
continue;
}
if (!chr->subscribe(true, onEvent, false)) {
Serial.println("Failed to subscribe to characteristic");
pClient->disconnect();
restart("Device has been manually disconnected");
}
Serial.println("Successfully subscribed to characteristic");
break;
}
Serial.println("Setup complete");
esp_task_wdt_deinit();
}
// .pio/build/release/defconfig
CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
CONFIG_ARDUINO_VARIANT="esp32c3"
CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y
CONFIG_ARDUHAL_LOG_COLORS=y
CONFIG_ARDUHAL_ESP_LOG=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
CONFIG_COMPILER_CXX_EXCEPTIONS=y
CONFIG_COMPILER_CXX_RTTI=y
CONFIG_BT_ENABLED=y
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=9
CONFIG_BT_NIMBLE_MAX_BONDS=30
CONFIG_BT_NIMBLE_MAX_CCCDS=30
CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=5
CONFIG_BT_NIMBLE_TASK_STACK_SIZE=7800
# CONFIG_BT_NIMBLE_SM_LEGACY is not set
# CONFIG_BT_NIMBLE_SM_SC is not set
CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="u701"
CONFIG_BT_NIMBLE_HS_FLOW_CTRL=y
CONFIG_BT_NIMBLE_RPA_TIMEOUT=30
# CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS is not set
# CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT is not set
CONFIG_ESP32C3_DEFAULT_CPU_FREQ_80=y
# CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set
CONFIG_ESP_TASK_WDT_PANIC=y
# CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 is not set
CONFIG_ESP_TIMER_PROFILING=y
CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD=y
CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y
CONFIG_FREERTOS_HZ=1000
CONFIG_MBEDTLS_ECP_RESTARTABLE=y
CONFIG_MBEDTLS_CMAC_C=y
# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set
CONFIG_NEWLIB_NANO_FORMAT=y
# CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP is not set
# CONFIG_SPI_FLASH_SUPPORT_TH_CHIP is not set
I'm trying to use my ESP32 as a BLE client and server simultaneously, but I've encountered some problems on the way.
The goal is:
While I can successfully receive notifications from the BLE buttons, I cannot send them to the keyboard. I have a working solution in C++ using NimBLE-Arduino & ESP32-BLE-Keyboard but am facing difficulties with this library.
I've tried the following versions of ESP IDF:
Hardware & Software:
Cargo.toml
:For the ESP32-C3, my
.cargo/config.toml
target configuration is:Failed Attempts:
1. Starting the keyboard (server) after connecting to the BLE buttons (client)
Code:
Error:
2. Creating the keyboard after the setup is complete, after subscribing to the client for notifications
Code:
Error:
3. Using lazy_static for the keyboard
Code:
Error:
4. Just using the Keyboard example without connecting to the client
This works!
5. Initialising the keyboard before scanning for devices
Code:
Error:
No error, but the ESP can no longer receive notifications.
Full Code:
I've attached the full code for you to look at, but without the failing examples above.
Here's the complete stack trace (IDF = 4.4.6):
ble_svc_gap_init ble_svc_gap.c:297
``` I (50) boot: ESP-IDF v5.1-beta1-378-gea5e0ff298-dirt 2nd stage bootloader I (50) boot: compile time Jun 7 2023 07:59:10 I (51) boot: chip revision: v0.4 I (55) boot.esp32c3: SPI Speed : 40MHz I (60) boot.esp32c3: SPI Mode : DIO I (65) boot.esp32c3: SPI Flash Size : 4MB I (69) boot: Enabling RNG early entropy source... I (75) boot: Partition Table: I (78) boot: ## Label Usage Type ST Offset Length I (86) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (93) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (101) boot: 2 factory factory app 00 00 00010000 003f0000 I (108) boot: End of partition table I (112) esp_image: segment 0: paddr=00010020 vaddr=3c0a0020 size=1ad50h (109904) map I (145) esp_image: segment 1: paddr=0002ad78 vaddr=3fc91a00 size=02b90h ( 11152) load I (148) esp_image: segment 2: paddr=0002d910 vaddr=40380000 size=02708h ( 9992) load I (153) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=92ad8h (600792) map I (290) esp_image: segment 4: paddr=000c2b00 vaddr=40382708 size=0f120h ( 61728) load I (311) boot: Loaded app from partition at offset 0x10000 I (312) boot: Disabling RNG early entropy source... I (323) cpu_start: Unicore app I (323) cpu_start: Pro cpu up. I (332) cpu_start: Pro cpu start user code I (332) cpu_start: cpu freq: 160000000 I (332) cpu_start: Application information: I (335) cpu_start: Project name: libespidf I (340) cpu_start: App version: v1.1.1-9-g40f8558-dirty I (347) cpu_start: Compile time: Oct 24 2023 00:40:10 I (353) cpu_start: ELF file SHA256: 0000000000000000... I (359) cpu_start: ESP-IDF: v4.4.6-dirty I (364) cpu_start: Min chip rev: v0.3 I (369) cpu_start: Max chip rev: v0.99 I (374) cpu_start: Chip rev: v0.4 I (378) heap_init: Initializing. RAM available for dynamic allocation: I (386) heap_init: At 3FC96E60 len 000458B0 (278 KiB): DRAM I (392) heap_init: At 3FCDC710 len 00002950 (10 KiB): STACK/DRAM I (398) heap_init: At 50000020 len 00001FE0 (7 KiB): RTCRAM I (406) spi_flash: detected chip: generic I (410) spi_flash: flash io: dio I (414) sleep: Configure to isolate all GPIO pins in sleep state I (420) sleep: Enable automatic switching of GPIO sleep configuration I (427) coexist: coexist rom version 9387209 I (432) cpu_start: Starting scheduler. I (437) u701: Setup connection to BLE buttons I (447) BLE_INIT: BT controller compile version [59725b5] I (447) system_api: Base MAC address is not set I (447) system_api: read default base MAC address from EFUSE I (457) BLE_INIT: Bluetooth MAC: ec:da:3b:15:fc:1e I (457) phy_init: phy_version 1110,9c20f0a,Jul 27 2023,10:42:54 I (517) esp32_nimble::ble_device: BLE Host Task Started I (517) NimBLE: GAP procedure initiated: stop advertising. I (527) esp32_nimble::ble_device: Device Address: EC:DA:3B:15:FC:1E I (527) NimBLE: GAP procedure initiated: discovery; I (527) NimBLE: own_addr_type=0 filter_policy=0 passive=0 limited=0 filter_duplicates=1 I (537) NimBLE: duration=forever I (547) NimBLE: I (587) u701: Found device: "tob" I (597) NimBLE: GAP procedure initiated: connect; I (597) NimBLE: peer_addr_type=0 peer_addr= I (597) NimBLE: 60:55:f9:ca:d6:0a I (597) NimBLE: scan_itvl=16 scan_window=16 itvl_min=24 itvl_max=40 latency=0 supervision_timeout=256 min_ce_len=0 max_ce_len=0 own_addr_type=0 I (607) NimBLE: I (657) NimBLE: GATT procedure initiated: exchange mtu I (747) esp32_nimble::client::ble_client: mtu update event; conn_handle=1 mtu=256 I (747) NimBLE: GATT procedure initiated: discover all services I (847) NimBLE: GATT procedure initiated: discover all characteristics; I (847) NimBLE: start_handle=15 end_handle=34 I (1047) NimBLE: GATT procedure initiated: discover all characteristics; I (1047) NimBLE: start_handle=25 end_handle=34 I (1147) NimBLE: GATT procedure initiated: discover all descriptors; I (1147) NimBLE: chr_val_handle=25 end_handle=30 I (1247) NimBLE: GATT procedure initiated: write no rsp; I (1247) NimBLE: att_handle=26 len=2 I (1247) u701: Waiting for notifications ... assert failed: ble_svc_gap_init ble_svc_gap.c:297 (rc == 0) Core 0 register dump: MEPC : 0x40381f40 RA : 0x40389904 SP : 0x3fca72a0 GP : 0x3fc92200 0x40381f40 - panic_abort at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/esp_system/panic.c:408 0x40389904 - __ubsan_include at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/esp_system/ubsan.c:294 0x3fca72a0 - _heap_start at ??:?? 0x3fc92200 - __global_pointer$ at ??:?? TP : 0x3fc8cab8 T0 : 0x37363534 T1 : 0x7271706f T2 : 0x33323130 0x3fc8cab8 - __eh_frame_hdr at ??:?? 0x37363534 - at ??:?? 0x7271706f - USB_SERIAL_JTAG at ??:?? 0x33323130 - at ??:?? S0/FP : 0x0000008c S1 : 0x00000001 A0 : 0x3fca72dc A1 : 0x3fc9396d 0x0000008c - RV_STK_MTVAL at ??:?? 0x00000001 - at ??:?? 0x3fca72dc - _heap_start at ??:?? 0x3fc9396d - _btdm_data_end at ??:?? A2 : 0x00000001 A3 : 0x00000029 A4 : 0x3fc94f30 A5 : 0x3fc94f38 0x00000001 - at ??:?? 0x00000029 - RV_STK_A0 at ??:?? 0x3fc94f30 - xIsrStack at ??:?? 0x3fc94f38 - xIsrStack at ??:?? A6 : 0x7a797877 A7 : 0x76757473 S2 : 0x00000009 S3 : 0x3fca73eb 0x7a797877 - USB_SERIAL_JTAG at ??:?? 0x76757473 - USB_SERIAL_JTAG at ??:?? 0x00000009 - RV_STK_SP at ??:?? 0x3fca73eb - _heap_start at ??:?? S4 : 0x3fc9396c S5 : 0x3fc927e8 S6 : 0x3fc9283c S7 : 0x3fca74a8 0x3fc9396c - _btdm_data_end at ??:?? 0x3fc927e8 - _ZN12esp32_nimble10ble_device10BLE_SERVER17ha606c21abf767d10E at ??:?? 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x3fca74a8 - _heap_start at ??:?? S8 : 0x00000001 S9 : 0x3fc927e8 S10 : 0x3fc95610 S11 : 0x00000000 0x00000001 - at ??:?? 0x3fc927e8 - _ZN12esp32_nimble10ble_device10BLE_SERVER17ha606c21abf767d10E at ??:?? 0x3fc95610 - _ZN3std6thread8ThreadId3new7COUNTER17h53a6e9131d7b68c7E.llvm.15977218726786850347 at ??:?? 0x00000000 - at ??:?? T3 : 0x6e6d6c6b T4 : 0x6a696867 T5 : 0x66656463 T6 : 0x62613938 0x6e6d6c6b - USB_SERIAL_JTAG at ??:?? 0x6a696867 - USB_SERIAL_JTAG at ??:?? 0x66656463 - USB_SERIAL_JTAG at ??:?? 0x62613938 - USB_SERIAL_JTAG at ??:?? MSTATUS : 0x00001881 MTVEC : 0x40380001 MCAUSE : 0x00000007 MTVAL : 0x00000000 0x00001881 - at ??:?? 0x40380001 - _vector_table at ??:?? 0x00000007 - RV_STK_RA at ??:?? 0x00000000 - at ??:?? MHARTID : 0x00000000 0x00000000 - at ??:?? Stack memory: 3fca72a0: 0x4038c8da 0x4038c908 0x3c0b32e0 0x40390032 0x3fc93a54 0x3c0b32e0 0x3fc93e6c 0x3c0b3363 0x4038c8da - vPortClearInterruptMask at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/port/riscv/port.c:308 0x4038c908 - vPortExitCritical at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/port/riscv/port.c:262 0x3c0b32e0 - __func__.7414 at ??:?? 0x40390032 - newlib_include_assert_impl at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/newlib/assert.c:97 0x3fc93a54 - __func__.2605 at ??:?? 0x3c0b32e0 - __func__.7414 at ??:?? 0x3fc93e6c - CSWTCH.170 at ??:?? 0x3c0b3363 - ble_svc_gap_defs at ??:?? 3fca72c0: 0x3fc93a64 0x3fca72d4 0x3fc93a68 0x3c0b3278 0x3fc9396c 0x00373932 0x00000000 0x65737361 0x3fc93a64 - __func__.2605 at ??:?? 0x3fca72d4 - _heap_start at ??:?? 0x3fc93a68 - __func__.2605 at ??:?? 0x3c0b3278 - ble_svc_gatt_defs at ??:?? 0x3fc9396c - _btdm_data_end at ??:?? 0x00373932 - at ??:?? 0x00000000 - at ??:?? 0x65737361 - USB_SERIAL_JTAG at ??:?? 3fca72e0: 0x66207472 0x656c6961 0x62203a64 0x735f656c 0x675f6376 0x695f7061 0x2074696e 0x5f656c62 0x66207472 - USB_SERIAL_JTAG at ??:?? 0x656c6961 - USB_SERIAL_JTAG at ??:?? 0x62203a64 - USB_SERIAL_JTAG at ??:?? 0x735f656c - USB_SERIAL_JTAG at ??:?? 0x675f6376 - USB_SERIAL_JTAG at ??:?? 0x695f7061 - USB_SERIAL_JTAG at ??:?? 0x2074696e - at ??:?? 0x5f656c62 - _rtc_force_slow_start at ??:?? 3fca7300: 0x5f637673 0x2e706167 0x39323a63 0x72282037 0x3d3d2063 0x00293020 0x00000000 0x4038bd84 0x5f637673 - _rtc_force_slow_start at ??:?? 0x2e706167 - at ??:?? 0x39323a63 - at ??:?? 0x72282037 - USB_SERIAL_JTAG at ??:?? 0x3d3d2063 - __eh_frame_hdr at ??:?? 0x00293020 - at ??:?? 0x00000000 - at ??:?? 0x4038bd84 - xTaskPriorityDisinherit at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/tasks.c:4807 3fca7320: 0x00000000 0x00000000 0x3fca6740 0x40389ba4 0x00000000 0x00000000 0x3fca6740 0x4038a194 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x40389ba4 - prvCopyDataToQueue at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/queue.c:2246 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x4038a194 - xQueueGenericSend at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/queue.c:1043 3fca7340: 0x00000000 0x00000000 0x3fca6740 0x00000000 0x00000000 0x00001800 0x3fc97570 0xffffffff 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00001800 - at ??:?? 0x3fc97570 - _heap_start at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 3fca7360: 0x00000000 0x00000001 0x3fca94b4 0x3fca9304 0x3fca779c 0x3fca6740 0x00000001 0x4038a344 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x3fca94b4 - _heap_start at ??:?? 0x3fca9304 - _heap_start at ??:?? 0x3fca779c - _heap_start at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x4038a344 - xQueueGiveMutexRecursive at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/queue.c:685 3fca7380: 0x3c0b3300 0x00000001 0x3fc957b4 0x4205ecf8 0x3fc9283c 0x00000001 0x0000000f 0x42052888 0x3c0b3300 - ble_svc_gap_defs at ??:?? 0x00000001 - at ??:?? 0x3fc957b4 - ble_hs_mutex at ??:?? 0x4205ecf8 - npl_freertos_mutex_release at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c:212 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x00000001 - at ??:?? 0x0000000f - RV_STK_GP at ??:?? 0x42052888 - ble_hs_unlock_nested at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_hs.c:195 3fca73a0: 0x3fca9140 0x00000000 0x00000000 0x42000000 0x3fc92904 0x00000001 0x3fca94b4 0x3fca9304 0x3fca9140 - _heap_start at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x42000000 - _iram_end at ??:?? 0x3fc92904 - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x00000001 - at ??:?? 0x3fca94b4 - _heap_start at ??:?? 0x3fca9304 - _heap_start at ??:?? 3fca73c0: 0x3fca9140 0x00000001 0x3fc9283c 0x4204fd7e 0x00000000 0x00000000 0x3fc9283c 0x4200b6f0 0x3fca9140 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x4204fd7e - ble_store_util_iter_count at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_store_util.c:194 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x4200b6f0 - esp32_nimble::server::ble_server::BLEServer::start at ~/.cargo/git/checkouts/esp32-nimble-fc9d2c54a3bfa7fe/87fdceb/src/server/ble_server.rs:88 3fca73e0: 0x0000000f 0x3fc9290c 0x3fc9283c 0x00000000 0x3fc95610 0x3fc9283c 0x00000001 0x3fca74a8 0x0000000f - RV_STK_GP at ??:?? 0x3fc9290c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x00000000 - at ??:?? 0x3fc95610 - _ZN3std6thread8ThreadId3new7COUNTER17h53a6e9131d7b68c7E.llvm.15977218726786850347 at ??:?? 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x00000001 - at ??:?? 0x3fca74a8 - _heap_start at ??:?? 3fca7400: 0x3fc9283c 0x3fc927e8 0x3fca94b4 0x3fca9304 0x3fca9140 0x00000001 0x3fc9283c 0x4200acde 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x3fc927e8 - _ZN12esp32_nimble10ble_device10BLE_SERVER17ha606c21abf767d10E at ??:?? 0x3fca94b4 - _heap_start at ??:?? 0x3fca9304 - _heap_start at ??:?? 0x3fca9140 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x4200acde - esp32_nimble::server::ble_advertising::BLEAdvertising::start_with_duration at ~/.cargo/git/checkouts/esp32-nimble-fc9d2c54a3bfa7fe/87fdceb/src/server/ble_advertising.rs:222 3fca7420: 0x3fca9140 0x3fca8bf8 0x3fca8bf0 0x420028ce 0x3fca8aa8 0x3fca8b64 0x3fca8bf0 0x3fca8cbc 0x3fca9140 - _heap_start at ??:?? 0x3fca8bf8 - _heap_start at ??:?? 0x3fca8bf0 - _heap_start at ??:?? 0x420028ce - core::result::ResultAny guidance or assistance would be greatly appreciated. Thank you!