From fc1018559d90d78d12367c70bcacd7e7b65d6025 Mon Sep 17 00:00:00 2001 From: Christian Ehlers Date: Fri, 6 Nov 2020 23:07:05 +0100 Subject: [PATCH] BLE update --- esp32/mods/modbt.c | 161 +++++++++++++++++++++++++++------------- esp32/mods/modmachine.c | 3 +- esp32/mods/modwlan.c | 102 +++++++++++++++++-------- esp32/mods/modwlan.h | 2 +- esp32/pycom_version.h | 2 +- 5 files changed, 185 insertions(+), 85 deletions(-) diff --git a/esp32/mods/modbt.c b/esp32/mods/modbt.c index 2b720d69ab..9964cf83b2 100644 --- a/esp32/mods/modbt.c +++ b/esp32/mods/modbt.c @@ -113,6 +113,7 @@ typedef struct { int32_t conn_id; uint16_t mtu; esp_gatt_if_t gatt_if; + esp_ble_addr_type_t addr_type; } bt_connection_obj_t; typedef struct { @@ -258,7 +259,6 @@ static esp_ble_adv_params_t bt_adv_params = { static bool mod_bt_allow_resume_deinit; static uint16_t mod_bt_gatts_mtu_restore = 0; -static bool mod_bt_is_conn_restore_available; static nvs_handle modbt_nvs_handle; static uint8_t tx_pwr_level_to_dbm[] = {-12, -9, -6, -3, 0, 3, 6, 9}; @@ -278,7 +278,7 @@ STATIC void gattc_char_callback_handler(void *arg); STATIC void gatts_char_callback_handler(void *arg); static mp_obj_t modbt_start_scan(mp_obj_t timeout); static mp_obj_t modbt_conn_disconnect(mp_obj_t self_in); -static mp_obj_t modbt_connect(mp_obj_t addr); +static mp_obj_t modbt_connect(mp_obj_t addr, esp_ble_addr_type_t addr_type); /****************************************************************************** DEFINE PUBLIC FUNCTIONS @@ -317,7 +317,6 @@ void modbt_init0(void) { esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT); mod_bt_allow_resume_deinit = false; - mod_bt_is_conn_restore_available = false; } void modbt_deinit(bool allow_reconnect) @@ -356,11 +355,14 @@ void modbt_deinit(bool allow_reconnect) xEventGroupWaitBits(bt_event_group, MOD_BT_GATTS_DISCONN_EVT | MOD_BT_GATTS_CLOSE_EVT, true, true, 1000/portTICK_PERIOD_MS); } + esp_ble_gattc_app_unregister(MOD_BT_CLIENT_APP_ID); + esp_ble_gatts_app_unregister(MOD_BT_SERVER_APP_ID); + esp_bluedroid_disable(); esp_bluedroid_deinit(); esp_bt_controller_disable(); + esp_bt_controller_deinit(); bt_obj.init = false; - mod_bt_is_conn_restore_available = false; xEventGroupClearBits(bt_event_group, MOD_BT_GATTC_MTU_EVT | MOD_BT_GATTS_MTU_EVT | MOD_BT_GATTS_DISCONN_EVT | MOD_BT_GATTS_CLOSE_EVT); } } @@ -381,39 +383,48 @@ void bt_resume(bool reconnect) nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Bluetooth enable failed")); } + esp_ble_gap_register_callback(gap_events_handler); + esp_ble_gattc_register_callback(gattc_events_handler); + esp_ble_gatts_register_callback(gatts_event_handler); + esp_ble_gattc_app_register(MOD_BT_CLIENT_APP_ID); esp_ble_gatts_app_register(MOD_BT_SERVER_APP_ID); esp_ble_gatt_set_local_mtu(mod_bt_gatts_mtu_restore); - bt_connection_obj_t *connection_obj = NULL; - - if(MP_STATE_PORT(btc_conn_list).len > 0) + // If this list has 0 elements it means there were no active connections + if(MP_STATE_PORT(btc_conn_list).len > 0 && reconnect) { - /* Get the Last gattc connection obj before sleep */ - connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[MP_STATE_PORT(btc_conn_list).len - 1])); - } + /* Enable Scan */ + modbt_start_scan(MP_OBJ_NEW_SMALL_INT(-1)); + mp_hal_delay_ms(50); + while(!bt_obj.scanning){ + /* Wait for scanning to start */ + } - if (reconnect) - { - /* Check if there was a gattc connection Active before sleep */ - if (connection_obj != NULL) { - if (connection_obj->conn_id >= 0) { - /* Enable Scan */ - modbt_start_scan(MP_OBJ_NEW_SMALL_INT(-1)); - mp_hal_delay_ms(50); - while(!bt_obj.scanning){ - /* Wait for scanning to start */ - } - /* re-connect to Last Connection */ - mp_obj_list_remove((void *)&MP_STATE_PORT(btc_conn_list), connection_obj); - mp_obj_list_append((void *)&MP_STATE_PORT(btc_conn_list), modbt_connect(mp_obj_new_bytes((const byte *)connection_obj->srv_bda, 6))); + /* Re-connect to all previously existing connections */ + // Need to save the old connections into a temporary list because during connect the original list is manipulated (items added) + mp_obj_list_t btc_conn_list_tmp; + mp_obj_list_init(&btc_conn_list_tmp, 0); + for (mp_uint_t i = 0; i < MP_STATE_PORT(btc_conn_list).len; i++) { + bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[i])); + mp_obj_list_append(&btc_conn_list_tmp, connection_obj); + } - mod_bt_is_conn_restore_available = true; + // Connect to the old connections + for (mp_uint_t i = 0; i < btc_conn_list_tmp.len; i++) { + bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(btc_conn_list_tmp.items[i])); + // Initiates re-connection + bt_connection_obj_t *new_connection_obj = modbt_connect(mp_obj_new_bytes((const byte *)connection_obj->srv_bda, 6), connection_obj->addr_type); + // If new connection object has been created then overwrite the original one so from the MicroPython code the same reference can be used + if(new_connection_obj != mp_const_none) { + memcpy(connection_obj, new_connection_obj, sizeof(bt_connection_obj_t)); + // As modbt_connect appends the new connection to the original list, it needs to be removed because it is not needed + mp_obj_list_remove((void *)&MP_STATE_PORT(btc_conn_list), new_connection_obj); } } - /* See if there was an averstisment active before Sleep */ + /* See if there was an advertisement active before Sleep */ if(bt_obj.advertising) { esp_ble_gap_start_advertising(&bt_adv_params); } @@ -456,19 +467,19 @@ static void create_hash(uint32_t pin, uint8_t *h_value) { bt_hash_obj_t pin_hash; mbedtls_sha1_context sha1_context; - + mbedtls_sha1_init(&sha1_context); mbedtls_sha1_starts_ret(&sha1_context); - + pin_hash.pin = pin; mbedtls_sha1_update_ret(&sha1_context, pin_hash.value, 4); - + mbedtls_sha1_finish_ret(&sha1_context, h_value); mbedtls_sha1_free(&sha1_context); } -static bool pin_changed(uint32_t new_pin) -{ +static bool pin_changed(uint32_t new_pin) +{ bool ret = false; uint32_t h_size = MOD_BT_HASH_SIZE; uint8_t h_stored[MOD_BT_HASH_SIZE] = {0}; @@ -480,9 +491,9 @@ static bool pin_changed(uint32_t new_pin) mp_printf(&mp_plat_print, "Error opening secure BLE NVS namespace!\n"); } nvs_get_blob(modbt_nvs_handle, key, h_stored, &h_size); - + create_hash(new_pin, h_created); - + if (memcmp(h_stored, h_created, MOD_BT_HASH_SIZE) != 0) { esp_err = nvs_set_blob(modbt_nvs_handle, key, h_created, h_size); if (esp_err == ESP_OK) { @@ -490,7 +501,7 @@ static bool pin_changed(uint32_t new_pin) ret = true; } } - + nvs_close(modbt_nvs_handle); return ret; @@ -547,8 +558,7 @@ static void set_pin(uint32_t new_pin) static void close_connection (int32_t conn_id) { for (mp_uint_t i = 0; i < MP_STATE_PORT(btc_conn_list).len; i++) { bt_connection_obj_t *connection_obj = ((bt_connection_obj_t *)(MP_STATE_PORT(btc_conn_list).items[i])); - /* Only reset Conn Id if it is a normal disconnect not module de-init to mark conn obj to be restored */ - if (connection_obj->conn_id == conn_id && (!mod_bt_allow_resume_deinit)) { + if (connection_obj->conn_id == conn_id) { connection_obj->conn_id = -1; mp_obj_list_remove((void *)&MP_STATE_PORT(btc_conn_list), connection_obj); } @@ -1371,13 +1381,19 @@ STATIC mp_obj_t bt_events(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bt_events_obj, bt_events); -static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){ +static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout, esp_ble_addr_type_t addr_type){ bt_event_result_t bt_event; EventBits_t uxBits; if (bt_obj.busy) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "operation already in progress")); + // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error + if(mod_bt_allow_resume_deinit == false) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "operation already in progress")); + } + else { + return mp_const_none; + } } if (bt_obj.scanning) { @@ -1393,16 +1409,29 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){ bt_obj.busy = true; /* Initiate a background connection, esp_ble_gattc_open returns immediately */ - if (ESP_OK != esp_ble_gattc_open(bt_obj.gattc_if, bufinfo.buf, BLE_ADDR_TYPE_PUBLIC, true)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + if (ESP_OK != esp_ble_gattc_open(bt_obj.gattc_if, bufinfo.buf, addr_type, true)) { + // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error + if(mod_bt_allow_resume_deinit == false) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + } + else { + return mp_const_none; + } } + MP_THREAD_GIL_EXIT(); if (xQueueReceive(xScanQueue, &bt_event, timeout) == pdTRUE) { MP_THREAD_GIL_ENTER(); if (bt_event.connection.conn_id < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "connection refused")); + // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error + if(mod_bt_allow_resume_deinit == false) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "connection refused")); + } + else { + return mp_const_none; + } } // setup the object @@ -1410,6 +1439,7 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){ conn->base.type = (mp_obj_t)&mod_bt_connection_type; conn->conn_id = bt_event.connection.conn_id; conn->gatt_if = bt_event.connection.gatt_if; + conn->addr_type = addr_type; MP_THREAD_GIL_EXIT(); uxBits = xEventGroupWaitBits(bt_event_group, MOD_BT_GATTC_MTU_EVT, true, true, 1000/portTICK_PERIOD_MS); @@ -1421,6 +1451,7 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){ } memcpy(conn->srv_bda, bt_event.connection.srv_bda, 6); mp_obj_list_append((void *)&MP_STATE_PORT(btc_conn_list), conn); + return conn; } else @@ -1428,7 +1459,14 @@ static mp_obj_t bt_connect_helper(mp_obj_t addr, TickType_t timeout){ MP_THREAD_GIL_ENTER(); (void)esp_ble_gap_disconnect(bufinfo.buf); - nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); + + // Only drop exception if not called from bt_resume() API, otherwise return with mp_const_none on error + if(mod_bt_allow_resume_deinit == false) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); + } + else { + return mp_const_none; + } } return mp_const_none; } @@ -1439,6 +1477,7 @@ STATIC mp_obj_t bt_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t STATIC const mp_arg_t allowed_args[] = { { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_OBJ, }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_addr_type, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, }; // parse arguments @@ -1447,7 +1486,7 @@ STATIC mp_obj_t bt_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t mp_obj_t addr = args[0].u_obj; - /* Timeout parameter is in miliseconds */ + /* Timeout parameter is in milliseconds */ TickType_t timeout; if(args[1].u_obj == MP_OBJ_NULL){ timeout = portMAX_DELAY; @@ -1463,13 +1502,30 @@ STATIC mp_obj_t bt_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t } } - return bt_connect_helper(addr, timeout); + /* addr_type parameter */ + uint32_t addr_type; + if(args[2].u_obj == MP_OBJ_NULL){ + addr_type = BLE_ADDR_TYPE_PUBLIC; + } + else + { + if(MP_OBJ_IS_SMALL_INT(args[2].u_obj) == true) { + addr_type = mp_obj_get_int(args[2].u_obj); + } + else + { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "If addr_type is specified it must be a valid integer number")); + } + } + + + return bt_connect_helper(addr, timeout, addr_type); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bt_connect_obj, 1, bt_connect); -static mp_obj_t modbt_connect(mp_obj_t addr) +static mp_obj_t modbt_connect(mp_obj_t addr, esp_ble_addr_type_t addr_type) { - return bt_connect_helper(addr, portMAX_DELAY); + return bt_connect_helper(addr, portMAX_DELAY, addr_type); } @@ -1482,7 +1538,7 @@ STATIC mp_obj_t bt_set_advertisement_params (mp_uint_t n_args, const mp_obj_t *p { MP_QSTR_channel_map, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_adv_filter_policy, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; - + // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), allowed_args, args); @@ -1635,14 +1691,14 @@ STATIC mp_obj_t bt_set_advertisement_raw(mp_obj_t self_in, mp_obj_t raw_data) { memcpy(data, (uint8_t *)bufinfo.buf, sizeof(data)); data_len = sizeof(data); } - + esp_ble_gap_config_adv_data_raw(data, data_len); - + // wait for the advertisement data to be configured bt_gatts_event_result_t gatts_event; xQueueReceive(xGattsQueue, &gatts_event, portMAX_DELAY); } - + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(bt_set_advertisement_raw_obj, bt_set_advertisement_raw); @@ -2241,8 +2297,9 @@ STATIC mp_obj_t bt_conn_disconnect(mp_obj_t self_in) { if (self->conn_id >= 0) { esp_ble_gattc_close(bt_obj.gattc_if, self->conn_id); esp_ble_gap_disconnect(self->srv_bda); - /* Only reset Conn Id if it is a normal disconnect not module de-init to mark conn obj to be restored */ - if(!mod_bt_allow_resume_deinit) + /* Only reset Conn Id if it is needed that the connection should be established again after wakeup + * otherwise this connection will be completely removed in close_connection() call triggered by ESP_GATTC_DISCONNECT_EVT event */ + if(mod_bt_allow_resume_deinit) { self->conn_id = -1; } diff --git a/esp32/mods/modmachine.c b/esp32/mods/modmachine.c index 7bbaa76338..bbe15f3399 100644 --- a/esp32/mods/modmachine.c +++ b/esp32/mods/modmachine.c @@ -223,7 +223,8 @@ STATIC mp_obj_t machine_sleep (uint n_args, const mp_obj_t *arg) { } modbt_deinit(reconnect); - wlan_deinit(NULL); + // TRUE means wlan_deinit is called from machine_sleep + wlan_deinit(mp_const_true); if(ESP_OK != esp_light_sleep_start()) { diff --git a/esp32/mods/modwlan.c b/esp32/mods/modwlan.c index 64a0ecc321..203ee4a91f 100644 --- a/esp32/mods/modwlan.c +++ b/esp32/mods/modwlan.c @@ -93,14 +93,14 @@ wlan_obj_t wlan_obj = { .enable_servers = false, .pwrsave = false, .is_promiscuous = false, - .sta_conn_timeout = false + .sta_conn_timeout = false, + .country = NULL }; /* TODO: Maybe we can add possibility to create IRQs for wifi events */ static EventGroupHandle_t wifi_event_group; -static bool mod_wlan_is_deinit = false; static uint16_t mod_wlan_ap_number_of_connections = 0; /* Variables holding wlan conn params for wakeup recovery of connections */ @@ -132,6 +132,7 @@ SemaphoreHandle_t smartConfigTimeout_mutex; static const int ESPTOUCH_DONE_BIT = BIT1; static const int ESPTOUCH_STOP_BIT = BIT2; +static const int ESPTOUCH_SLEEP_STOP_BIT = BIT3; static bool wlan_smart_config_enabled = false; /****************************************************************************** @@ -201,24 +202,36 @@ void wlan_pre_init (void) { wlan_obj.mutex = xSemaphoreCreateMutex(); timeout_mutex = xSemaphoreCreateMutex(); smartConfigTimeout_mutex = xSemaphoreCreateMutex(); - memcpy(wlan_obj.country.cc, (const char*)"NA", sizeof(wlan_obj.country.cc)); // create Smart Config Task xTaskCreatePinnedToCore(TASK_SMART_CONFIG, "SmartConfig", SMART_CONF_TASK_STACK_SIZE / sizeof(StackType_t), NULL, SMART_CONF_TASK_PRIORITY, &SmartConfTaskHandle, 1); } void wlan_resume (bool reconnect) { - if (!wlan_obj.started && mod_wlan_is_deinit) { - - mod_wlan_is_deinit = false; - - if(reconnect) - { - wifi_country_t* country = NULL; - - if(strcmp((const char*)wlan_obj.country.cc, "NA")) - { - country = &(wlan_obj.country); + // Configure back WLAN as it was before if reconnect is TRUE + if(reconnect) { + // If SmartConfig enabled then re-start it + if(wlan_smart_config_enabled) { + // Do initial configuration as at this point the Wifi Driver is not initialized + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); + wlan_set_antenna(wlan_obj.antenna); + wlan_set_mode(wlan_obj.mode); + wlan_set_bandwidth(wlan_obj.bandwidth); + if(wlan_obj.country != NULL) { + esp_wifi_set_country(wlan_obj.country); + } + xTaskNotifyGive(SmartConfTaskHandle); + } + // Otherwise set up WLAN with the same parameters as it was before + else { + // In wlan_setup the wlan_obj.country is overwritten with the value coming from setup_config, need to save it out + wifi_country_t country; + wifi_country_t* country_ptr = NULL; + if(wlan_obj.country != NULL) { + memcpy(&country, wlan_obj.country, sizeof(wifi_country_t)); + country_ptr = &country; } wlan_internal_setup_t setup_config = { @@ -233,11 +246,11 @@ void wlan_resume (bool reconnect) false, wlan_conn_recover_hidden, wlan_obj.bandwidth, - country, + country_ptr, &(wlan_obj.max_tx_pwr) }; - // initialize the wlan subsystem + // Initialize & reconnect to the previous connection wlan_setup(&setup_config); } } @@ -260,12 +273,15 @@ void wlan_setup (wlan_internal_setup_t *config) { wlan_set_bandwidth(config->bandwidth); if (config->country != NULL) { - - if(ESP_OK != esp_wifi_set_country(config->country)) + esp_err_t ret = esp_wifi_set_country(config->country); + if(ESP_OK != ret) { nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); } - memcpy(&(wlan_obj.country), config->country, sizeof(wlan_obj.country)); + if(wlan_obj.country == NULL) { + wlan_obj.country = (wifi_country_t*)malloc(sizeof(wifi_country_t)); + } + memcpy(wlan_obj.country, config->country, sizeof(wifi_country_t)); } if(config->max_tx_pr != NULL) @@ -968,9 +984,8 @@ static void TASK_SMART_CONFIG (void *pvParameters) { static uint32_t thread_notification; smartConf_init: - wlan_smart_config_enabled = false; connected = false; - // Block task till notification is recieved + // Block task till notification is received thread_notification = ulTaskNotifyTake(pdTRUE, portMAX_DELAY); if (thread_notification) { @@ -985,30 +1000,36 @@ static void TASK_SMART_CONFIG (void *pvParameters) { } CHECK_ESP_ERR(esp_smartconfig_set_type(SC_TYPE_ESPTOUCH), smartConf_init) CHECK_ESP_ERR(esp_smartconfig_start(smart_config_callback), smartConf_init) - wlan_smart_config_enabled = true; goto smartConf_start; } goto smartConf_init; smartConf_start: - //mp_printf(&mp_plat_print, "\n-------SmartConfig Started-------\n"); + wlan_smart_config_enabled = true; /*create Timer */ wlan_smartConfig_timeout = xTimerCreate("smartConfig_Timer", 60000 / portTICK_PERIOD_MS, 0, 0, wlan_timer_callback); /*start Timer */ xTimerStart(wlan_smartConfig_timeout, 0); while (1) { - uxBits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT | ESPTOUCH_STOP_BIT, true, false, portMAX_DELAY); + uxBits = xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT | ESPTOUCH_DONE_BIT | ESPTOUCH_STOP_BIT | ESPTOUCH_SLEEP_STOP_BIT, true, false, portMAX_DELAY); if(uxBits & ESPTOUCH_STOP_BIT) { + wlan_smart_config_enabled = false; esp_smartconfig_stop(); //mp_printf(&mp_plat_print, "\nSmart Config Aborted or Timed-out\n"); goto smartConf_init; } + if(uxBits & ESPTOUCH_SLEEP_STOP_BIT) { + esp_smartconfig_stop(); + //mp_printf(&mp_plat_print, "\nSmart Config Aborted because sleep operation has been requested\n"); + goto smartConf_init; + } if(uxBits & CONNECTED_BIT) { //mp_printf(&mp_plat_print, "WiFi Connected to ap\n"); connected = true; } if(uxBits & ESPTOUCH_DONE_BIT) { //mp_printf(&mp_plat_print, "smartconfig over\n"); + wlan_smart_config_enabled = false; esp_smartconfig_stop(); wlan_stop_smartConfig_timer(); //set event flag @@ -1264,11 +1285,25 @@ mp_obj_t wlan_deinit(mp_obj_t self_in) { if (wlan_obj.started) { + bool called_from_sleep = false; + // stop smart config if enabled - if(wlan_smart_config_enabled) - { - xEventGroupSetBits(wifi_event_group, ESPTOUCH_STOP_BIT); - vTaskDelay(100/portTICK_PERIOD_MS); + if(wlan_smart_config_enabled) { + // If the input parameter is not the object itself but a simple boolean, it is interpreted that + // wlan_deinit is called from machine_sleep() + if(mp_obj_get_type(self_in) == &mp_type_bool) { + called_from_sleep = (bool)mp_obj_get_int(self_in); + if(called_from_sleep == true) { + // stop smart config with special event + xEventGroupSetBits(wifi_event_group, ESPTOUCH_SLEEP_STOP_BIT); + vTaskDelay(100/portTICK_PERIOD_MS); + } + } + else { + // stop smart config with original STOP event + xEventGroupSetBits(wifi_event_group, ESPTOUCH_STOP_BIT); + vTaskDelay(100/portTICK_PERIOD_MS); + } } esp_wifi_stop(); @@ -1281,7 +1316,11 @@ mp_obj_t wlan_deinit(mp_obj_t self_in) { /* stop and free wifi resource */ esp_wifi_deinit(); - mod_wlan_is_deinit = true; + // Only free up memory area of country information if this deinit is not called from machine.sleep() + if(called_from_sleep == false) { + free(wlan_obj.country); + wlan_obj.country = NULL; + } wlan_obj.started = false; mod_network_deregister_nic(&wlan_obj); } @@ -2465,7 +2504,10 @@ STATIC mp_obj_t wlan_country(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); } - memcpy(&(wlan_obj.country), &country_config, sizeof(wlan_obj.country)); + if(wlan_obj.country == NULL) { + wlan_obj.country = (wifi_country_t*)malloc(sizeof(wifi_country_t)); + } + memcpy(wlan_obj.country, &country_config, sizeof(wifi_country_t)); return mp_const_none; } diff --git a/esp32/mods/modwlan.h b/esp32/mods/modwlan.h index 585e0ef905..105ed7a295 100644 --- a/esp32/mods/modwlan.h +++ b/esp32/mods/modwlan.h @@ -73,7 +73,7 @@ typedef struct _wlan_obj_t { uint8_t channel; uint8_t antenna; int8_t max_tx_pwr; - wifi_country_t country; + wifi_country_t* country; // my own ssid, key and mac uint8_t ssid[(MODWLAN_SSID_LEN_MAX + 1)]; diff --git a/esp32/pycom_version.h b/esp32/pycom_version.h index 4675e70422..65d1ec1fb4 100644 --- a/esp32/pycom_version.h +++ b/esp32/pycom_version.h @@ -10,7 +10,7 @@ #ifndef VERSION_H_ #define VERSION_H_ -#define SW_VERSION_NUMBER "1.20.2.r1" +#define SW_VERSION_NUMBER "1.20.2.r2" #define LORAWAN_VERSION_NUMBER "1.0.2"