You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
extmod/zephyr_ble: Unregister connection callbacks in deinit.
Add bt_conn_cb_unregister() call in mp_bluetooth_deinit() to properly
clean up connection callbacks when the BLE stack is deactivated.
PROBLEM:
The static connection callback structure mp_bt_zephyr_conn_callbacks
persists across bt_disable()/bt_enable() cycles. Zephyr's bt_disable()
does not automatically clear registered callbacks, causing them to
accumulate on each reinitialization. While this doesn't directly cause
crashes (the callbacks are function pointers that remain valid), it
violates the lifecycle contract and could lead to unexpected behavior
if the callback structure were ever relocated or modified.
LIFECYCLE ISSUE:
- mp_bluetooth_init() calls bt_conn_cb_register(&mp_bt_zephyr_conn_callbacks)
- mp_bluetooth_deinit() calls bt_disable() but never unregisters callbacks
- Next mp_bluetooth_init() attempts to register the same callbacks again
- Without dynamic callback support (CONFIG_BT_CONN_DYNAMIC_CALLBACKS=1),
this would cause registration failures
With CONFIG_BT_CONN_DYNAMIC_CALLBACKS=1 enabled in our configuration,
Zephyr maintains a dynamic list of registered callbacks and silently
allows re-registration of the same callback structure. However, this
is still semantically incorrect and relies on implementation details.
SOLUTION:
Call bt_conn_cb_unregister(&mp_bt_zephyr_conn_callbacks) during
mp_bluetooth_deinit() to properly clean up the callbacks before
bt_disable() is called. This ensures clean state across init/deinit
cycles and follows proper lifecycle management.
The unregister operation is performed after stopping advertising and
scanning but before calling bt_disable(), ensuring callbacks are
removed while the BLE stack is still active and can properly process
the unregistration.
CALL SEQUENCE IN mp_bluetooth_deinit():
1. mp_bluetooth_gap_advertise_stop() - Stop advertising
2. mp_bluetooth_gattc_disconnect_all() - Disconnect clients
3. mp_bluetooth_gatts_deinit() - Unregister GATT services
4. mp_bluetooth_gap_scan_stop() - Stop scanning
5. bt_conn_cb_unregister() - Unregister callbacks (NEW)
6. bt_disable() - Shutdown BLE stack
This ordering ensures all BLE operations are stopped before callback
unregistration, and the stack is still active when unregistering.
TESTING:
Verified on STM32WB55 with soft reset cycles:
- 3 consecutive bt_enable() → bt_disable() cycles
- No callback-related errors or warnings
- Clean reinitialization on each cycle
This change is required for proper soft reset support but does not
fix the reference counting crash (that's fixed in the Zephyr submodule
commit). Both changes together enable full soft reset functionality.
Signed-off-by: Andrew Leech <[email protected]>
0 commit comments