Search code examples
cesp8266freertosesp8266wifi

ESP8266-RTOS-SDK - cannot connect to WPA2 network depending on esp_wifi_init() location


I encounter a strange issue while working on my project with ESP8266 and using FreeRTOS SDK (version release/v3.4).

In my code, I'd like to have 5 functions for controlling WiFi state:

  • wifi_initialize()
  • wifi_station_connect()
  • wifi_station_disconnect()
  • wifi_ap_start()
  • wifi_ap_stop()

I believe the names are self-descriptive. The (simplified) code for first 2 (only ones relevant to the problem) is as follows:

void wifi_initialize()
{
    tcpip_adapter_init();

    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL);
    esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL);

    wifi_init_config_t init_cfg = WIFI_INIT_CONFIG_DEFAULT(); // Problematic when called here
    ESP_ERROR_CHECK(esp_wifi_init(&init_cfg));                // Problematic when called here
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));      // Problematic when called here
    ESP_ERROR_CHECK(esp_wifi_start());                        // Problematic when called here
}

void wifi_station_connect()
{
    // wifi_init_config_t init_cfg = WIFI_INIT_CONFIG_DEFAULT(); // OK when called here
    // ESP_ERROR_CHECK(esp_wifi_init(&init_cfg));                // OK when called here
    // ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_APSTA));      // OK when called here
    // ESP_ERROR_CHECK(esp_wifi_start());                        // OK when called here

    wifi_config_t wifi_config;
    if (xSemaphoreTake(common_settings_mutex, pdMS_TO_TICKS(20)))
    {
        memcpy(wifi_config.sta.ssid, common_settings.wifi_ssid, 32);
        ESP_LOGI(TAG, "Using SSID: %s", wifi_config.sta.ssid);
        memcpy(wifi_config.sta.password, common_settings.wifi_password, 64);
        ESP_LOGI(TAG, "Using password: %s", wifi_config.sta.password);
        xSemaphoreGive(common_settings_mutex);
    }
    if (strlen((char*) wifi_config.sta.password))
    {
        wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
    }

    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
    ESP_ERROR_CHECK(esp_wifi_connect());
}

The problem: with the code as above, the ESP is unable to connect to password-protected networks. The SSID and password copied to wifi_config are correct as checked using logging. Connecting to open networks (using empty password) works fine. The bizzare part: moving call to esp_wifi_init() from wifi_initialize() to wifi_station_connect() solves the problem, even though in any case wifi_station_connect() is called directly after wifi_initialize() (esp_wifi_set_mode() and esp_wifi_start() are also moved, since they need to be called after esp_wifi_init()).

I will be grateful for any suggestions what might be wrong here, or how to debug this issue/


Solution

  • I'll answer my own question since I found a solution: the wifi_config_t union/struct must be defined before values are assigned to SSID and password fields. This line:

    wifi_config_t wifi_config;
    

    Has to become:

    wifi_config_t wifi_config = {};
    

    Then everything works as expected.

    EDIT
    The reason for this behavior is lack of memory allocation for an union before it is declared. In Espressif's examples the config is initialized during variable definition, so this problem doesn't occur. That said, it's interesting the in some cases the code was working fine, and that no exception was thrown.