taks / esp32-nimble

A wrapper for the ESP32 NimBLE Bluetooth stack.
Apache License 2.0
106 stars 32 forks source link

Unable to use ESP32 as both BLE client and server simultaneously #34

Open oleander opened 11 months ago

oleander commented 11 months ago

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:

  1. ESP32 connects to Bluetooth buttons via BLE (acting as a client).
  2. Registers for BLE events.
  3. Remaps these events and send them over BLE to a secondary device using the keyboard example provided in this repository (acting as a server).

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:

[dependencies]
esp-idf-svc = { version = "0.47", ... }
esp-idf-hal = { version = "0.42", ... }
esp-idf-sys = { version = "0.33", ... }
esp32-nimble = { git = "https://github.com/taks/esp32-nimble.git", branch = "develop" }
...

For the ESP32-C3, my .cargo/config.toml target configuration is:

[build]
target = "riscv32imc-esp-espidf"

Failed Attempts:

1. Starting the keyboard (server) after connecting to the BLE buttons (client)

Code:

client.on_connect(move |_client| {
  info!("Connected to device");
  let keyboard = Keyboard::new();
  *keyboard_ref_clone.lock() = Some(keyboard);
});

Error:

assert failed: ble_svc_gap_init ble_svc_gap.c:297 (rc == 0)
...

2. Creating the keyboard after the setup is complete, after subscribing to the client for notifications

Code:

characteristic.on_notify(move |_data| {
 info!("Received notification from device");
}).subscribe_notify(false).await.unwrap();

let keyboard_ref_clone = Arc::clone(&keyboard_ref);
let keyboard = Keyboard::new();
*keyboard_ref_clone.lock() = Some(keyboard);

Error:

assert failed: ble_svc_gap_init ble_svc_gap.c:297 (rc == 0)
...

3. Using lazy_static for the keyboard

Code:

lazy_static! {
  static ref KEYBOARD: Mutex<Keyboard> = Mutex::new(Keyboard::new());
}

// in main
characteristic.on_notify(move |data| {
  let mut keyboard = KEYBOARD.lock();
  keyboard.write("Message");
});

Error:

assert failed: ble_svc_gap_init ble_svc_gap.c:297 (rc == 0)
...

4. Just using the Keyboard example without connecting to the client

This works!

#[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 mut keyboard = Keyboard::new();
    loop {
      keyboard.write("Hello world");
      Timer::after(Duration::from_secs(1)).await;
    }
  });
}

5. Initialising the keyboard before scanning for devices

Code:

#[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();

  KEYBOARD.lock().write("Hello world");
  block_on(async {
    // ...
  });

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.

#![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 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");
      })
      .subscribe_notify(false)
      .await
      .expect("Failed to subscribe to notifications");

    info!("Waiting for notifications ...");

    loop {
      Timer::after(Duration::from_secs(1)).await;
    }
  });
}

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::Result::unwrap at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/result.rs:1075 0x3fca8aa8 - _heap_start at ??:?? 0x3fca8b64 - _heap_start at ??:?? 0x3fca8bf0 - _heap_start at ??:?? 0x3fca8cbc - _heap_start at ??:?? 3fca7440: 0x3fca8d48 0x3fca8dc0 0x3fca8e38 0x3fca8eb0 0x3fca8f7c 0x3fca9070 0x3fca9664 0x4205f202 0x3fca8d48 - _heap_start at ??:?? 0x3fca8dc0 - _heap_start at ??:?? 0x3fca8e38 - _heap_start at ??:?? 0x3fca8eb0 - _heap_start at ??:?? 0x3fca8f7c - _heap_start at ??:?? 0x3fca9070 - _heap_start at ??:?? 0x3fca9664 - _heap_start at ??:?? 0x4205f202 - os_memblock_put_from_cb at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c:287 3fca7460: 0x18120000 0x00000000 0x00000000 0x4205f22c 0x00000000 0x3fc945b0 0x3fc91a24 0x3fca7502 0x18120000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x4205f22c - os_memblock_put at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c:328 0x00000000 - at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x3fc91a24 - _ZN3std10sys_common11thread_info11THREAD_INFO7__getit5__KEY17h81085a841406b003E.llvm.13851875188132569457 at ??:?? 0x3fca7502 - _heap_start at ??:?? 3fca7480: 0xffffffff 0xffffffff 0x00000001 0x00000002 0x00000000 0x3fc94590 0x3fc945b0 0x420012f4 0xffffffff - USB_SERIAL_JTAG at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 0x00000001 - at ??:?? 0x00000002 - at ??:?? 0x00000000 - at ??:?? 0x3fc94590 - _noinit_start at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x420012f4 - core::ptr::read at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1180 3fca74a0: 0x0f000102 0x06000b00 0xaa490700 0x15f641f9 0xfbec0ca5 0x00000000 0x3fca0494 0x4038a194 0x0f000102 - at ??:?? 0x06000b00 - at ??:?? 0xaa490700 - USB_SERIAL_JTAG at ??:?? 0x15f641f9 - at ??:?? 0xfbec0ca5 - USB_SERIAL_JTAG at ??:?? 0x00000000 - at ??:?? 0x3fca0494 - _heap_start at ??:?? 0x4038a194 - xQueueGenericSend at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/queue.c:1043 3fca74c0: 0x00000003 0xff000fff 0x00000025 0x00000000 0x00000000 0x00000000 0x3fca0494 0x4038bd84 0x00000003 - at ??:?? 0xff000fff - USB_SERIAL_JTAG at ??:?? 0x00000025 - RV_STK_S1 at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca0494 - _heap_start at ??:?? 0x4038bd84 - xTaskPriorityDisinherit at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/tasks.c:4807 3fca74e0: 0x00000000 0x00000019 0x3fc945b0 0x4200d3ae 0x3c0a0a5c 0x3c0a0884 0x3fca7560 0x00000000 0x00000000 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x4200d3ae - core::cell::Cell::get at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/cell.rs:500 0x3c0a0a5c - anon.c4c334a0304349482020d54e395477f7.20.llvm.3730123182963330635 at ??:?? 0x3c0a0884 - anon.c4c334a0304349482020d54e395477f7.1.llvm.3730123182963330635 at ??:?? 0x3fca7560 - _heap_start at ??:?? 0x00000000 - at ??:?? 3fca7500: 0x3fc945b0 0x00000000 0x3fce0000 0x00000000 0x00000003 0x4204ed00 0x00000000 0xffffffff 0x3fc945b0 - _bss_start at ??:?? 0x00000000 - at ??:?? 0x3fce0000 - ets_ops_table_ptr at ??:?? 0x00000000 - at ??:?? 0x00000003 - at ??:?? 0x4204ed00 - semphr_take_wrapper at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/controller/esp32c3/bt.c:580 0x00000000 - at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 3fca7520: 0x00000000 0x00000001 0x3fc9a248 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x3fc9a248 - _heap_start at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 3fca7540: 0x00000000 0x00000000 0x3fc9a248 0x00000001 0x00000000 0x00000019 0x3fc945b0 0x42002d12 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fc9a248 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x00000000 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x42002d12 - std::sync::once::Once::call_once at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/std/src/sync/once.rs:149 3fca7560: 0x3fca7580 0x00000001 0x3fca763c 0x4200588e 0x00000000 0x00000000 0x3fca6740 0x3fc94590 0x3fca7580 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x3fca763c - _heap_start at ??:?? 0x4200588e - esp32_nimble::client::ble_client::BLEClient::handle_gap_event at ~/.cargo/git/checkouts/esp32-nimble-fc9d2c54a3bfa7fe/87fdceb/src/client/ble_client.rs:391 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x3fc94590 - _noinit_start at ??:?? 3fca7580: 0x00000000 0x00000019 0x3fca765c 0x4200585c 0x00000000 0x00000000 0x3fca6740 0x4038a194 0x00000000 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x3fca765c - _heap_start at ??:?? 0x4200585c - as core::ops::function::FnMut>::call_mut at ??:?? 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 3fca75a0: 0x00000000 0x00000001 0x3fc96224 0x00000000 0x3fca779c 0x3fca6740 0x00000001 0xffffffff 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x3fc96224 - ble_hs_conn_elem_mem at ??:?? 0x00000000 - at ??:?? 0x3fca779c - _heap_start at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x00000001 - at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 3fca75c0: 0x00000000 0x00000001 0x0000001b 0x00000001 0x3fca779c 0x3fca6740 0x00000001 0x4038a344 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x0000001b - RV_STK_T1 at ??:?? 0x00000001 - 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 3fca75e0: 0x3fca763c 0x3fca7638 0x3fc957b4 0x4205ecf8 0x00000000 0x3fca7638 0x3fc96224 0x42052888 0x3fca763c - _heap_start at ??:?? 0x3fca7638 - _heap_start 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 0x00000000 - at ??:?? 0x3fca7638 - _heap_start at ??:?? 0x3fc96224 - ble_hs_conn_elem_mem 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 3fca7600: 0x00000000 0x00000000 0x0000001b 0x00000001 0x00000000 0x3fc95ee8 0x3fca765c 0x420577a6 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x0000001b - RV_STK_T1 at ??:?? 0x00000001 - at ??:?? 0x00000000 - at ??:?? 0x3fc95ee8 - ble_l2cap_chan_mem at ??:?? 0x3fca765c - _heap_start at ??:?? 0x420577a6 - ble_gap_call_event_cb at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_gap.c:735 3fca7620: 0x00000000 0x3fc95ee8 0x3fca765c 0x42057a9c 0x00000000 0x00000000 0x3fc9a248 0x42005404 0x00000000 - at ??:?? 0x3fc95ee8 - ble_l2cap_chan_mem at ??:?? 0x3fca765c - _heap_start at ??:?? 0x42057a9c - ble_gap_call_conn_event_cb at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_gap.c:751 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fc9a248 - _heap_start at ??:?? 0x42005404 - esp32_nimble::client::ble_client::BLEClient::handle_gap_event at ~/.cargo/git/checkouts/esp32-nimble-fc9d2c54a3bfa7fe/87fdceb/src/client/ble_client.rs:237 3fca7640: 0x00000000 0x3fc95ee8 0x00000001 0x4205a00c 0x00000000 0x00000000 0x3fca6740 0x0000000c 0x00000000 - at ??:?? 0x3fc95ee8 - ble_l2cap_chan_mem at ??:?? 0x00000001 - at ??:?? 0x4205a00c - ble_gap_notify_rx_event at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_gap.c:6142 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x0000000c - RV_STK_GP at ??:?? 3fca7660: 0x3fca4d70 0x00010019 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x3fca4d70 - _heap_start at ??:?? 0x00010019 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 3fca7680: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x00000019 0x42062928 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x42062928 - ble_att_svr_rx_notify at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_att_svr.c:2484 ELF file SHA256: 0000000000000000 Rebooting... ESP-ROM:esp32c3-api1-20210207 Build:Feb 7 2021 rst:0x3 (RTC_SW_SYS_RST),boot:0xc (SPI_FAST_FLASH_BOOT) Saved PC:0x40381ad0 0x40381ad0 - esp_restart_noos_dig at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/esp_system/esp_system.c:53 SPIWP:0xee mode:DIO, clock div:2 load:0x3fcd5820,len:0x171c 0x3fcd5820 - _heap_start at ??:?? load:0x403cc710,len:0x968 0x403cc710 - _iram_end at ??:?? load:0x403ce710,len:0x2f68 0x403ce710 - _iram_end at ??:?? SHA-256 comparison failed: Calculated: 1d06b938c0222bf626e0bdf46178b1b37ab24d03f0360fc8fcf7153c2571deaf Expected: 68d7bdf643ba446b8ed7ae8423241d442fd052b2bc77091100ba06fd65dcf8d5 Attempting to boot anyway... entry 0x403cc710 0x403cc710 - _iram_end at ??:?? I (53) boot: ESP-IDF v5.1-beta1-378-gea5e0ff298-dirt 2nd stage bootloader I (53) boot: compile time Jun 7 2023 07:59:10 I (55) boot: chip revision: v0.4 I (59) boot.esp32c3: SPI Speed : 40MHz I (63) boot.esp32c3: SPI Mode : DIO I (68) boot.esp32c3: SPI Flash Size : 4MB I (73) boot: Enabling RNG early entropy source... I (78) boot: Partition Table: I (82) boot: ## Label Usage Type ST Offset Length I (89) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (97) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (104) boot: 2 factory factory app 00 00 00010000 003f0000 I (112) boot: End of partition table I (116) esp_image: segment 0: paddr=00010020 vaddr=3c0a0020 size=1b550h (111952) map I (149) esp_image: segment 1: paddr=0002b578 vaddr=3fc91a00 size=02b90h ( 11152) load I (152) esp_image: segment 2: paddr=0002e110 vaddr=40380000 size=01f08h ( 7944) load I (157) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=93dach (605612) map I (295) esp_image: segment 4: paddr=000c3dd4 vaddr=40381f08 size=0f920h ( 63776) load I (317) boot: Loaded app from partition at offset 0x10000 I (317) boot: Disabling RNG early entropy source... I (329) cpu_start: Unicore app I (329) cpu_start: Pro cpu up. I (338) cpu_start: Pro cpu start user code I (338) cpu_start: cpu freq: 160000000 I (338) cpu_start: Application information: I (341) cpu_start: Project name: libespidf I (346) cpu_start: App version: v1.1.1-9-g40f8558-dirty I (352) cpu_start: Compile time: Oct 24 2023 00:02:27 I (358) cpu_start: ELF file SHA256: 0000000000000000... I (364) cpu_start: ESP-IDF: v4.4.6-dirty I (370) cpu_start: Min chip rev: v0.3 I (374) cpu_start: Max chip rev: v0.99 I (379) cpu_start: Chip rev: v0.4 I (384) heap_init: Initializing. RAM available for dynamic allocation: I (391) heap_init: At 3FC96E80 len 00045890 (278 KiB): DRAM I (397) heap_init: At 3FCDC710 len 00002950 (10 KiB): STACK/DRAM I (404) heap_init: At 50000020 len 00001FE0 (7 KiB): RTCRAM I (411) spi_flash: detected chip: generic I (415) spi_flash: flash io: dio I (420) sleep: Configure to isolate all GPIO pins in sleep state I (426) sleep: Enable automatic switching of GPIO sleep configuration I (433) coexist: coexist rom version 9387209 I (438) cpu_start: Starting scheduler. I (443) u701: Setup connection to BLE buttons I (453) BLE_INIT: BT controller compile version [59725b5] I (453) system_api: Base MAC address is not set I (453) system_api: read default base MAC address from EFUSE I (463) BLE_INIT: Bluetooth MAC: ec:da:3b:15:fc:1e I (463) phy_init: phy_version 1110,9c20f0a,Jul 27 2023,10:42:54 I (513) esp32_nimble::ble_device: BLE Host Task Started I (523) NimBLE: GAP procedure initiated: stop advertising. I (523) esp32_nimble::ble_device: Device Address: EC:DA:3B:15:FC:1E I (523) NimBLE: GAP procedure initiated: discovery; I (533) NimBLE: own_addr_type=0 filter_policy=0 passive=0 limited=0 filter_duplicates=1 I (543) NimBLE: duration=forever I (543) NimBLE: I (2153) u701: Found device: "tob" I (2153) NimBLE: GAP procedure initiated: connect; I (2153) NimBLE: peer_addr_type=0 peer_addr= I (2153) NimBLE: 60:55:f9:ca:d6:0a I (2163) 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 (2173) NimBLE: I (2223) NimBLE: GATT procedure initiated: exchange mtu I (2303) esp32_nimble::client::ble_client: mtu update event; conn_handle=1 mtu=256 I (2303) NimBLE: GATT procedure initiated: discover all services I (2403) NimBLE: GATT procedure initiated: discover all characteristics; I (2403) NimBLE: start_handle=15 end_handle=34 I (2603) NimBLE: GATT procedure initiated: discover all characteristics; I (2603) NimBLE: start_handle=25 end_handle=34 I (2703) NimBLE: GATT procedure initiated: discover all descriptors; I (2703) NimBLE: chr_val_handle=25 end_handle=30 I (2803) NimBLE: GATT procedure initiated: write no rsp; I (2803) NimBLE: att_handle=26 len=2 I (2803) 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 0x3fca9470 0x3fca92c0 0x3fca779c 0x3fca6740 0x00000001 0x4038a344 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x3fca9470 - _heap_start at ??:?? 0x3fca92c0 - _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: 0x3fca90fc 0x00000000 0x00000000 0x42000000 0x3fc92904 0x00000001 0x3fca9470 0x3fca92c0 0x3fca90fc - _heap_start at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x42000000 - _iram_end at ??:?? 0x3fc92904 - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x00000001 - at ??:?? 0x3fca9470 - _heap_start at ??:?? 0x3fca92c0 - _heap_start at ??:?? 3fca73c0: 0x3fca90fc 0x00000001 0x3fc9283c 0x4204fd7e 0x00000000 0x00000000 0x3fc9283c 0x4200b6f0 0x3fca90fc - _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 0x3fca9470 0x3fca92c0 0x3fca90fc 0x00000001 0x3fc9283c 0x4200acde 0x3fc9283c - _ZN12esp32_nimble10ble_device15BLE_ADVERTISING17h8776a8e1a8464ad4E.llvm.4422737608252036301 at ??:?? 0x3fc927e8 - _ZN12esp32_nimble10ble_device10BLE_SERVER17ha606c21abf767d10E at ??:?? 0x3fca9470 - _heap_start at ??:?? 0x3fca92c0 - _heap_start at ??:?? 0x3fca90fc - _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: 0x3fca90fc 0x3fca8bb4 0x3fca8bac 0x420028ce 0x3fca8a64 0x3fca8b20 0x3fca8bac 0x3fca8c78 0x3fca90fc - _heap_start at ??:?? 0x3fca8bb4 - _heap_start at ??:?? 0x3fca8bac - _heap_start at ??:?? 0x420028ce - core::result::Result::unwrap at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/result.rs:1075 0x3fca8a64 - _heap_start at ??:?? 0x3fca8b20 - _heap_start at ??:?? 0x3fca8bac - _heap_start at ??:?? 0x3fca8c78 - _heap_start at ??:?? 3fca7440: 0x3fca8d04 0x3fca8d7c 0x3fca8df4 0x3fca8e6c 0x3fca8f38 0x3fca902c 0x3fca9620 0x4205f202 0x3fca8d04 - _heap_start at ??:?? 0x3fca8d7c - _heap_start at ??:?? 0x3fca8df4 - _heap_start at ??:?? 0x3fca8e6c - _heap_start at ??:?? 0x3fca8f38 - _heap_start at ??:?? 0x3fca902c - _heap_start at ??:?? 0x3fca9620 - _heap_start at ??:?? 0x4205f202 - os_memblock_put_from_cb at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c:287 3fca7460: 0x18120000 0x00000000 0x00000000 0x4205f22c 0x00000000 0x3fc945b0 0x3fc91a24 0x3fca7502 0x18120000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x4205f22c - os_memblock_put at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/porting/nimble/src/os_mempool.c:328 0x00000000 - at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x3fc91a24 - _ZN3std10sys_common11thread_info11THREAD_INFO7__getit5__KEY17h81085a841406b003E.llvm.13851875188132569457 at ??:?? 0x3fca7502 - _heap_start at ??:?? 3fca7480: 0xffffffff 0xffffffff 0x00000001 0x00000002 0x00000000 0x3fc94590 0x3fc945b0 0x420012f4 0xffffffff - USB_SERIAL_JTAG at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 0x00000001 - at ??:?? 0x00000002 - at ??:?? 0x00000000 - at ??:?? 0x3fc94590 - _noinit_start at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x420012f4 - core::ptr::read at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1180 3fca74a0: 0x0f000102 0x06000b00 0x16aa0700 0x2fb1e34b 0xa3eb235a 0x00000000 0x3fca0494 0x4038a194 0x0f000102 - at ??:?? 0x06000b00 - at ??:?? 0x16aa0700 - at ??:?? 0x2fb1e34b - at ??:?? 0xa3eb235a - USB_SERIAL_JTAG at ??:?? 0x00000000 - at ??:?? 0x3fca0494 - _heap_start at ??:?? 0x4038a194 - xQueueGenericSend at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/queue.c:1043 3fca74c0: 0x00000003 0xff000fff 0x00000025 0x00000000 0x00000000 0x00000000 0x3fca0494 0x4038bd84 0x00000003 - at ??:?? 0xff000fff - USB_SERIAL_JTAG at ??:?? 0x00000025 - RV_STK_S1 at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca0494 - _heap_start at ??:?? 0x4038bd84 - xTaskPriorityDisinherit at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/freertos/tasks.c:4807 3fca74e0: 0x00000000 0x00000019 0x3fc945b0 0x4200d3ae 0x3c0a0a5c 0x3c0a0884 0x3fca7560 0x00000000 0x00000000 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x4200d3ae - core::cell::Cell::get at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/core/src/cell.rs:500 0x3c0a0a5c - anon.c4c334a0304349482020d54e395477f7.20.llvm.3730123182963330635 at ??:?? 0x3c0a0884 - anon.c4c334a0304349482020d54e395477f7.1.llvm.3730123182963330635 at ??:?? 0x3fca7560 - _heap_start at ??:?? 0x00000000 - at ??:?? 3fca7500: 0x3fc945b0 0x00000000 0x3fce0000 0x00000000 0x00000003 0x4204ed00 0x00000000 0xffffffff 0x3fc945b0 - _bss_start at ??:?? 0x00000000 - at ??:?? 0x3fce0000 - ets_ops_table_ptr at ??:?? 0x00000000 - at ??:?? 0x00000003 - at ??:?? 0x4204ed00 - semphr_take_wrapper at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/controller/esp32c3/bt.c:580 0x00000000 - at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 3fca7520: 0x00000000 0x00000001 0x3fc9a248 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x3fc9a248 - _heap_start at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 3fca7540: 0x00000000 0x00000000 0x3fc9a248 0x00000001 0x00000000 0x00000019 0x3fc945b0 0x42002d12 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fc9a248 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x00000000 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x3fc945b0 - _bss_start at ??:?? 0x42002d12 - std::sync::once::Once::call_once at ~/.rustup/toolchains/esp/lib/rustlib/src/rust/library/std/src/sync/once.rs:149 3fca7560: 0x3fca7580 0x00000001 0x3fca763c 0x4200588e 0x00000000 0x00000000 0x3fca6740 0x3fc94590 0x3fca7580 - _heap_start at ??:?? 0x00000001 - at ??:?? 0x3fca763c - _heap_start at ??:?? 0x4200588e - esp32_nimble::client::ble_client::BLEClient::handle_gap_event at ~/.cargo/git/checkouts/esp32-nimble-fc9d2c54a3bfa7fe/87fdceb/src/client/ble_client.rs:391 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x3fc94590 - _noinit_start at ??:?? 3fca7580: 0x00000000 0x00000019 0x3fca765c 0x4200585c 0x00000000 0x00000000 0x3fca6740 0x4038a194 0x00000000 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x3fca765c - _heap_start at ??:?? 0x4200585c - as core::ops::function::FnMut>::call_mut at ??:?? 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 3fca75a0: 0x00000000 0x00000001 0x3fc96224 0x00000000 0x3fca779c 0x3fca6740 0x00000001 0xffffffff 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x3fc96224 - ble_hs_conn_elem_mem at ??:?? 0x00000000 - at ??:?? 0x3fca779c - _heap_start at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x00000001 - at ??:?? 0xffffffff - USB_SERIAL_JTAG at ??:?? 3fca75c0: 0x00000000 0x00000001 0x0000001b 0x00000001 0x3fca779c 0x3fca6740 0x00000001 0x4038a344 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x0000001b - RV_STK_T1 at ??:?? 0x00000001 - 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 3fca75e0: 0x3fca763c 0x3fca7638 0x3fc957b4 0x4205ecf8 0x00000000 0x3fca7638 0x3fc96224 0x42052888 0x3fca763c - _heap_start at ??:?? 0x3fca7638 - _heap_start 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 0x00000000 - at ??:?? 0x3fca7638 - _heap_start at ??:?? 0x3fc96224 - ble_hs_conn_elem_mem 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 3fca7600: 0x00000000 0x00000000 0x0000001b 0x00000001 0x00000000 0x3fc95ee8 0x3fca765c 0x420577a6 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x0000001b - RV_STK_T1 at ??:?? 0x00000001 - at ??:?? 0x00000000 - at ??:?? 0x3fc95ee8 - ble_l2cap_chan_mem at ??:?? 0x3fca765c - _heap_start at ??:?? 0x420577a6 - ble_gap_call_event_cb at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_gap.c:735 3fca7620: 0x00000000 0x3fc95ee8 0x3fca765c 0x42057a9c 0x00000000 0x00000000 0x3fc9a248 0x42005404 0x00000000 - at ??:?? 0x3fc95ee8 - ble_l2cap_chan_mem at ??:?? 0x3fca765c - _heap_start at ??:?? 0x42057a9c - ble_gap_call_conn_event_cb at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_gap.c:751 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fc9a248 - _heap_start at ??:?? 0x42005404 - esp32_nimble::client::ble_client::BLEClient::handle_gap_event at ~/.cargo/git/checkouts/esp32-nimble-fc9d2c54a3bfa7fe/87fdceb/src/client/ble_client.rs:237 3fca7640: 0x00000000 0x3fc95ee8 0x00000001 0x4205a00c 0x00000000 0x00000000 0x3fca6740 0x0000000c 0x00000000 - at ??:?? 0x3fc95ee8 - ble_l2cap_chan_mem at ??:?? 0x00000001 - at ??:?? 0x4205a00c - ble_gap_notify_rx_event at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_gap.c:6142 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x3fca6740 - _heap_start at ??:?? 0x0000000c - RV_STK_GP at ??:?? 3fca7660: 0x3fca4d70 0x00010019 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x3fca4d70 - _heap_start at ??:?? 0x00010019 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 3fca7680: 0x00000000 0x00000000 0x00000000 0x00000000 0x00000000 0x00000001 0x00000019 0x42062928 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000000 - at ??:?? 0x00000001 - at ??:?? 0x00000019 - RV_STK_T1 at ??:?? 0x42062928 - ble_att_svr_rx_notify at ~/Code/u701-rs/.embuild/espressif/esp-idf/v4.4.6/components/bt/host/nimble/nimble/nimble/host/src/ble_att_svr.c:2484 ```

Any guidance or assistance would be greatly appreciated. Thank you!

taks commented 11 months 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;
    }
  });
}
oleander commented 8 months ago

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.

Flow

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