summaryrefslogtreecommitdiff
path: root/extmod/nimble/modbluetooth_nimble.c
diff options
context:
space:
mode:
authorAndrew Leech <andrew.leech@planetinnovation.com.au>2025-05-07 09:11:25 +1000
committerDamien George <damien@micropython.org>2025-06-04 02:21:32 +1000
commitd5f2fc239af2d69407170fa290ba6752c8f1790c (patch)
treef765b059b0887de6e8f7f0f10bb5541c47bd5b95 /extmod/nimble/modbluetooth_nimble.c
parent17898f8607dc4fb881e860719cc1906d304e60f4 (diff)
extmod/modbluetooth: Add timeout to deinit.
If the BLE radio stops responding before deinit is called the function can get stuck waiting for an event that is never received, particularly if the radio is external or on a separate core. This commit adds a timeout, similar to the timeout already used in the init function. Updated for nimble, btstack, esp32 and zephyr bindings. Signed-off-by: Andrew Leech <andrew.leech@planetinnovation.com.au>
Diffstat (limited to 'extmod/nimble/modbluetooth_nimble.c')
-rw-r--r--extmod/nimble/modbluetooth_nimble.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index 6ca0c1726..5e7030e36 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -60,6 +60,7 @@
static uint8_t nimble_address_mode = BLE_OWN_ADDR_RANDOM;
#define NIMBLE_STARTUP_TIMEOUT 2000
+#define NIMBLE_SHUTDOWN_TIMEOUT 500
// Any BLE_HS_xxx code not in this table will default to MP_EIO.
static int8_t ble_hs_err_to_errno_table[] = {
@@ -554,7 +555,7 @@ static void ble_hs_shutdown_stop_cb(int status, void *arg) {
static struct ble_hs_stop_listener ble_hs_shutdown_stop_listener;
-void mp_bluetooth_nimble_port_shutdown(void) {
+int mp_bluetooth_nimble_port_shutdown(void) {
DEBUG_printf("mp_bluetooth_nimble_port_shutdown (nimble default)\n");
// By default, just call ble_hs_stop directly and wait for the stack to stop.
@@ -562,9 +563,17 @@ void mp_bluetooth_nimble_port_shutdown(void) {
ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL);
+ mp_uint_t timeout_start_ticks_ms = mp_hal_ticks_ms();
while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
- mp_event_wait_indefinite();
+ mp_uint_t elapsed = mp_hal_ticks_ms() - timeout_start_ticks_ms;
+ if (elapsed > NIMBLE_SHUTDOWN_TIMEOUT) {
+ // Stack had not responded (via ble_hs_shutdown_stop_cb)
+ return MP_ETIMEDOUT;
+ }
+
+ mp_event_wait_ms(NIMBLE_SHUTDOWN_TIMEOUT - elapsed);
}
+ return 0;
}
#endif // !MICROPY_BLUETOOTH_NIMBLE_BINDINGS_ONLY
@@ -659,10 +668,11 @@ int mp_bluetooth_init(void) {
return 0;
}
-void mp_bluetooth_deinit(void) {
+int mp_bluetooth_deinit(void) {
DEBUG_printf("mp_bluetooth_deinit %d\n", mp_bluetooth_nimble_ble_state);
+ int ret = 0;
if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
- return;
+ return 0;
}
// Must call ble_hs_stop() in a port-specific way to stop the background
@@ -675,7 +685,7 @@ void mp_bluetooth_deinit(void) {
DEBUG_printf("mp_bluetooth_deinit: starting port shutdown\n");
- mp_bluetooth_nimble_port_shutdown();
+ ret = mp_bluetooth_nimble_port_shutdown();
assert(mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF);
} else {
mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF;
@@ -692,6 +702,7 @@ void mp_bluetooth_deinit(void) {
#endif
DEBUG_printf("mp_bluetooth_deinit: shut down\n");
+ return ret;
}
bool mp_bluetooth_is_active(void) {