-
-
Notifications
You must be signed in to change notification settings - Fork 204
Description
Environment
- NimBLE-Arduino: 2.3.7
- arduino-esp32: 3.3.7 (ESP-IDF 5.3.x)
- Board: ESP32-C3 (RISC-V)
Description
On ESP32-C3 with arduino-esp32 3.3.7, NimBLEDevice::init() causes a hard crash immediately at boot:
Guru Meditation Error: Core 0 panic'ed (Instruction access fault)
MEPC : 0x00000000
This is separate from the btInUse() issue fixed in PR #1090 — that fix is also required, but even with it applied the
crash persists due to the bug described here.
Root cause
nimconfig.h has an operator precedence bug in the block that sets CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE. Because &&
binds more tightly than ||, the !defined() guard only applies to the CONFIG_IDF_TARGET_ESP32 term — the ESP32-C3 and
ESP32-S3 terms are unconditionally true regardless:
// Parsed as: (!defined(VHCI) && defined(ESP32)) || defined(ESP32C3) || defined(ESP32S3)
// For ESP32-C3: always true — !defined() guard is never evaluated
#if !defined(CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE) && defined(CONFIG_IDF_TARGET_ESP32) || \
defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)
#define CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE 1
#endifWith CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE=1, NimBLEDevice::init() calls esp_nimble_hci_init() (in esp_nimble_hci.c),
which calls esp_vhci_host_register_callback(). On ESP32-C3 with ESP-IDF 5.x the VHCI API no longer exists — the symbol
is a null weak reference resolving to 0x00000000 — so the CPU jumps to address zero and faults.
This can be confirmed with riscv32-esp-elf-nm against the arduino-esp32 3.3.7 ESP32-C3 libraries:
esp_vhci_host_register_callback is absent from all of them.
Fix
Two changes to src/nimconfig.h:
-
Add #include "esp_idf_version.h" in the #ifdef ESP_PLATFORM block (after sdkconfig.h) so ESP_IDF_VERSION_VAL is
available. -
Replace the buggy block with correct precedence and an IDF version check (since ESP32-C3/S3 with IDF ≥ 5.0 use
nimble_port_init() for HCI — there is no VHCI):#if !defined(CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE) #if defined(CONFIG_IDF_TARGET_ESP32) || \ ((defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3)) && \ ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0)) #define CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE 1 #else #define CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE 0 #endif #endif
This preserves the existing behaviour for classic ESP32 and for ESP32-C3/S3 on older IDF, while correctly disabling
VHCI for ESP32-C3/S3 on IDF 5.x.
Relationship to PR #1090
PR #1090 (merged Feb 2026) fixed the related btInUse() issue introduced in arduino-esp32 3.3.7. Both fixes are
required for ESP32-C3 with arduino-esp32 3.3.7: the btInUse() fix prevents BT controller memory being released before
NimBLE starts; this fix prevents the subsequent null-pointer call into the removed VHCI API.