8000 Merge pull request #193 from geza-pycom/Resume_problem_bt_disconnect_… · pycom/pycom-micropython-sigfox@b728776 · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit b728776

Browse files
authored
Merge pull request #193 from geza-pycom/Resume_problem_bt_disconnect_memory_leak
Problem on machine.sleep(resume_wifi_ble=True) and Memory leak during Bluetooth.disconnect()
2 parents c3e7b6c + e3f3b41 commit b728776

File tree

4 files changed

+145
-65
lines changed

4 files changed

+145
-65
lines changed

esp32/mods/modbt.c

Lines changed: 70 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ static esp_ble_adv_params_t bt_adv_params = {
265265

266266
static bool mod_bt_allow_resume_deinit;
267267
static uint16_t mod_bt_gatts_mtu_restore = 0;
268-
static bool mod_bt_is_conn_restore_available;
269268

270269
static nvs_handle modbt_nvs_handle;
271270
static uint8_t tx_pwr_level_to_dbm[] = {-12, -9, -6, -3, 0, 3, 6, 9};
@@ -324,7 +323,6 @@ void modbt_init0(void) {
324323
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
325324

326325
mod_bt_allow_resume_deinit = false;
327-
mod_bt_is_conn_restore_available = false;
328326
}
329327

330328
void modbt_deinit(bool allow_reconnect)
@@ -363,11 +361,14 @@ void modbt_deinit(bool allow_reconnect)
363361
xEventGroupWaitBits(bt_event_group, MOD_BT_GATTS_DISCONN_EVT | MOD_BT_GATTS_CLOSE_EVT, true, true, 1000/portTICK_PERIOD_MS);
364362
}
365363

364+
esp_ble_gattc_app_unregister(MOD_BT_CLIENT_APP_ID);
365+
esp_ble_gatts_app_unregister(MOD_BT_SERVER_APP_ID);
366+
366367
esp_bluedroid_disable();
367368
esp_bluedroid_deinit();
368369
esp_bt_controller_disable();
370+
esp_bt_controller_deinit();
369371
bt_obj.init = false;
370-
mod_bt_is_conn_restore_available = false;
371372
xEventGroupClearBits(bt_event_group, MOD_BT_GATTC_MTU_EVT | MOD_BT_GATTS_MTU_EVT | MOD_BT_GATTS_DISCONN_EVT | MOD_BT_GATTS_CLOSE_EVT);
372373
}
373374
}
@@ -388,39 +389,48 @@ void bt_resume(bool reconnect)
388389
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Bluetooth enable failed"));
389390
}
390391

392+
esp_ble_gap_register_callback(gap_events_handler);
393+
esp_ble_gattc_register_callback(gattc_events_handler);
394+
esp_ble_gatts_register_callback(gatts_event_handler);
395+
391396
esp_ble_gattc_app_register(MOD_BT_CLIENT_APP_ID);
392397
esp_ble_gatts_app_register(MOD_BT_SERVER_APP_ID);
393398

394399
esp_ble_gatt_set_local_mtu(mod_bt_gatts_mtu_restore);
395400

396-
bt_connection_obj_t *connection_obj = NULL;
397-
398-
if(MP_STATE_PORT(btc_conn_list).len > 0)
401+
// If this list has 0 elements it means there were no active connections
402+
if(MP_STATE_PORT(btc_conn_list).len > 0 && reconnect)
399403
{
400-
/* Get the Last gattc connection obj before sleep */
401-
connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[MP_STATE_PORT(btc_conn_list).len - 1]));
402-
}
404+
/* Enable Scan */
405+
modbt_start_scan(MP_OBJ_NEW_SMALL_INT(-1));
406+
mp_hal_delay_ms(50);
407+
while(!bt_obj.scanning){
408+
/* Wait for scanning to start */
409+
}
403410

404-
if (reconnect)
405-
{
406-
/* Check if there was a gattc connection Active before sleep */
407-
if (connection_obj != NULL) {
408-
if (connection_obj->conn_id >= 0) {
409-
/* Enable Scan */
410-
modbt_start_scan(MP_OBJ_NEW_SMALL_INT(-1));
411-
mp_hal_delay_ms(50);
412-
while(!bt_obj.scanning){
413-
/* Wait for scanning to start */
414-
}
415-
/* re-connect to Last Connection */
416-
mp_obj_list_remove((void *)&MP_STATE_PORT(btc_conn_list), connection_obj);
417-
mp_obj_list_append((void *)&MP_STATE_PORT(btc_conn_list), modbt_connect(mp_obj_new_bytes((const byte *)connection_obj->srv_bda, 6)));
411+
/* Re-connect to all previously existing connections */
412+
// Need to save the old connections into a temporary list because during connect the original list is manipulated (items added)
413+
mp_obj_list_t btc_conn_list_tmp;
414+
mp_obj_list_init(&btc_conn_list_tmp, 0);
415+
for (mp_uint_t i = 0; i < MP_STATE_PORT(btc_conn_list).len; i++) {
416+
bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[i]));
417+
mp_obj_list_append(&btc_conn_list_tmp, connection_obj);
418+
}
418419

419-
mod_bt_is_conn_restore_available = true;
420+
// Connect to the old connections
421+
for (mp_uint_t i = 0; i < btc_conn_list_tmp.len; i++) {
422+
bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(btc_conn_list_tmp.items[i]));
423+
// Initiates re-connection
424+
bt_connection_obj_t *new_connection_obj = modbt_connect(mp_obj_new_bytes((const byte *)connection_obj->srv_bda, 6));
425+
// If new connection object has been created then overwrite the original one so from the MicroPython code the same reference can be used
426+
if(new_connection_obj != mp_const_none) {
427+
memcpy(connection_obj, new_connection_obj, sizeof(bt_connection_obj_t));
428+
// As modbt_connect appends the new connection to the original list, it needs to be removed because it is not needed
429+
mp_obj_list_remove((void *)&MP_STATE_PORT(btc_conn_list), new_connection_obj);
420430
}
421431
}
422432

423-
/* See if there was an averstisment active before Sleep */
433+
/* See if there was an advertisement active before Sleep */
424434
if(bt_obj.advertising) {
425435
esp_ble_gap_start_advertising(&bt_adv_params);
426436
}
@@ -554,8 +564,7 @@ static void set_pin(uint32_t new_pin)
554564
static void close_connection (int32_t conn_id) {
555565
for (mp_uint_t i = 0; i < MP_STATE_PORT(btc_conn_list).len; i++) {
556566
bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[i]));
557-
/* Only reset Conn Id if it is a normal disconnect not module de-init to mark conn obj to be restored */
558-
if (connection_obj->conn_id == conn_id && (!mod_bt_allow_resume_deinit)) {
567+
if (connection_obj->conn_id == conn_id) {
559568
connection_obj->conn_id = -1;
560569
mp_obj_list_remove((void *)&MP_STATE_PORT(btc_conn_list), connection_obj);
561570
}
@@ -1408,7 +1417,13 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){
14081417
EventBits_t uxBits;
14091418

14101419
if (bt_obj.busy) {
1411-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "operation already in progress"));
1420+
// Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1421+
if(mod_bt_allow_resume_deinit == false) {
1422+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "operation already in progress"));
1423+
}
1424+
else {
1425+
return mp_const_none;
1426+
}
14121427
}
14131428

14141429
if (bt_obj.scanning) {
@@ -1425,15 +1440,28 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){
14251440

14261441
/* Initiate a background connection, esp_ble_gattc_open returns immediately */
14271442
if (ESP_OK != esp_ble_gattc_open(bt_obj.gattc_if, bufinfo.buf, BLE_ADDR_TYPE_PUBLIC, true)) {
1428-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
1443+
// Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1444+
if(mod_bt_allow_resume_deinit == false) {
1445+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
1446+
}
1447+
else {
1448+
return mp_const_none;
1449+
}
14291450
}
1451+
14301452
MP_THREAD_GIL_EXIT();
14311453
if (xQueueReceive(xScanQueue, &bt_event, timeout) == pdTRUE)
14321454
{
14331455
MP_THREAD_GIL_ENTER();
14341456

14351457
if (bt_event.connection.conn_id < 0) {
1436-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "connection refused"));
1458+
// Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1459+
if(mod_bt_allow_resume_deinit == false) {
1460+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "connection refused"));
1461+
}
1462+
else {
1463+
return mp_const_none;
1464+
}
14371465
}
14381466

14391467
// setup the object
@@ -1452,14 +1480,22 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){
14521480
}
14531481
memcpy(conn->srv_bda, bt_event.connection.srv_bda, 6);
14541482
mp_obj_list_append((void *)&MP_STATE_PORT(btc_conn_list), conn);
1483+
14551484
return conn;
14561485
}
14571486
else
14581487
{
14591488
MP_THREAD_GIL_ENTER();
14601489

14611490
(void)esp_ble_gap_disconnect(bufinfo.buf);
1462-
nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out"));
1491+
1492+
// Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error
1493+
if(mod_bt_allow_resume_deinit == false) {
1494+
nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out"));
1495+
}
1496+
else {
1497+
return mp_const_none;
1498+
}
14631499
}
14641500
return mp_const_none;
14651501
}
@@ -2272,8 +2308,9 @@ STATIC mp_obj_t bt_conn_disconnect(mp_obj_t self_in) {
22722308
if (self->conn_id >= 0) {
22732309
esp_ble_gattc_close(bt_obj.gattc_if, self->conn_id);
22742310
esp_ble_gap_disconnect(self->srv_bda);
2275-
/* Only reset Conn Id if it is a normal disconnect not module de-init to mark conn obj to be restored */
2276-
if(!mod_bt_allow_resume_deinit)
2311+
/* Only reset Conn Id if it is needed that the connection should be established again after wakeup
2312+
* otherwise this connection will be completely removed in close_connection() call triggered by ESP_GATTC_DISCONNECT_EVT event */
2313+
if(mod_bt_allow_resume_deinit)
22772314
{
22782315
self->conn_id = -1;
22792316
}

esp32/mods/modmachine.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ STATIC mp_obj_t machine_sleep (uint n_args, const mp_obj_t *arg) {
435435
}
436436

437437
modbt_deinit(reconnect);
438-
wlan_deinit(NULL);
438+
// TRUE means wlan_deinit is called from machine_sleep
439+
wlan_deinit(mp_const_true);
439440

440441
if(ESP_OK != esp_light_sleep_start())
441442
{

0 commit comments

Comments
 (0)
0