diff --git a/esphome/components/bluetooth_connection/bluetooth_connection_rp2.cpp b/esphome/components/bluetooth_connection/bluetooth_connection_rp2.cpp index c23a00f674..ce7d7e7af5 100644 --- a/esphome/components/bluetooth_connection/bluetooth_connection_rp2.cpp +++ b/esphome/components/bluetooth_connection/bluetooth_connection_rp2.cpp @@ -609,8 +609,11 @@ void RP2GattClient::release_scan_inhibit_() { void RP2GattClient::fail_connection_(uint8_t reason) { { // Timeout escalation can fire with the completion event lost; release the - // stack-wide connect slot so pending engines can proceed (a still-busy - // stack answers them with DISALLOWED and they keep pending). + // stack-wide connect slot so pending engines can proceed. Until the old + // completion is processed, gap_connect answers any peer with DISALLOWED + // (the request-level guard in hci.c); a cancel idles that request + // immediately, and a late addressed completion from the old procedure is + // then dropped by the owner-peer cross-check in the handler. BluetoothLock lock; if (connect_owner == this) { connect_owner = nullptr; diff --git a/esphome/components/bluetooth_connection/btstack_memory_rp2.cpp b/esphome/components/bluetooth_connection/btstack_memory_rp2.cpp index 508f7aa7e8..cc6c633222 100644 --- a/esphome/components/bluetooth_connection/btstack_memory_rp2.cpp +++ b/esphome/components/bluetooth_connection/btstack_memory_rp2.cpp @@ -70,23 +70,19 @@ extern "C" hci_connection_t *__real_btstack_memory_hci_connection_get(void); extern "C" void __real_btstack_memory_hci_connection_free(hci_connection_t *hci_connection); namespace { -// Never called: the linker silently ignores --wrap for an unreferenced -// symbol, and __real_* only resolves while --wrap is in effect — so these -// references turn "pools compiled but a flag not emitted" into a link error -// instead of a silent fallback to the prebuilt one-client pool. One anchor -// per wrapped symbol, so dropping any single flag fails loudly. -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -[[gnu::used]] void (*const WRAP_ACTIVE_CHECKS[])() = { - reinterpret_cast(&__real_btstack_memory_gatt_client_get), - reinterpret_cast(&__real_btstack_memory_gatt_client_free), - reinterpret_cast(&__real_btstack_memory_hci_connection_get), - reinterpret_cast(&__real_btstack_memory_hci_connection_free), -}; +// Fails the link if the corresponding --wrap flag is missing: __real_* only +// exists while --wrap is in effect, and each wrap function anchors its own +// symbol so dropping any single flag fails loudly. A code reference is used +// because the framework links with --gc-sections, which discards an +// unreferenced data anchor regardless of [[gnu::used]] (and this toolchain +// does not emit SHF_GNU_RETAIN for [[gnu::retain]]). +template void anchor_wrap(T *symbol) { asm volatile("" ::"r"(symbol)); } } // namespace extern "C" { gatt_client_t *__wrap_btstack_memory_gatt_client_get(void) { + anchor_wrap(&__real_btstack_memory_gatt_client_get); void *buffer = btstack_memory_pool_get(&gatt_client_pool); if (buffer != nullptr) { memset(buffer, 0, sizeof(gatt_client_t)); @@ -95,10 +91,12 @@ gatt_client_t *__wrap_btstack_memory_gatt_client_get(void) { } void __wrap_btstack_memory_gatt_client_free(gatt_client_t *gatt_client) { + anchor_wrap(&__real_btstack_memory_gatt_client_free); btstack_memory_pool_free(&gatt_client_pool, gatt_client); } hci_connection_t *__wrap_btstack_memory_hci_connection_get(void) { + anchor_wrap(&__real_btstack_memory_hci_connection_get); void *buffer = btstack_memory_pool_get(&hci_connection_pool); if (buffer != nullptr) { memset(buffer, 0, sizeof(hci_connection_t)); @@ -107,6 +105,7 @@ hci_connection_t *__wrap_btstack_memory_hci_connection_get(void) { } void __wrap_btstack_memory_hci_connection_free(hci_connection_t *hci_connection) { + anchor_wrap(&__real_btstack_memory_hci_connection_free); btstack_memory_pool_free(&hci_connection_pool, hci_connection); } diff --git a/tests/components/bluetooth_proxy/test.rp2350-ard.yaml b/tests/components/bluetooth_proxy/test.rp2350-ard.yaml new file mode 100644 index 0000000000..1abc62cedb --- /dev/null +++ b/tests/components/bluetooth_proxy/test.rp2350-ard.yaml @@ -0,0 +1,9 @@ +# Pico 2 W build of the full proxy: links the rp2350 framework archive, so +# the pool --wrap overrides and their per-architecture layout asserts are +# exercised for this chip too (see test.rp2040-ard.yaml for the slot shape). +packages: + common: !include common.yaml + +rp2_ble_tracker: + +bluetooth_proxy: