• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <esp_event.h>
16 #include <esp_wifi.h>
17 #include "esp_log.h"
18 #include "esp_private/wifi.h"
19 #include "esp_sleep.h"
20 #include "soc/rtc.h"
21 #include "esp_netif.h"
22 #include "tcpip_adapter_compatible/tcpip_adapter_compat.h"
23 #include "driver/adc.h"
24 #include "driver/adc2_wifi_private.h"
25 #include "esp_coexist_internal.h"
26 #include "esp_phy_init.h"
27 
28 #if (CONFIG_ESP32_WIFI_RX_BA_WIN > CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM)
29 #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than WIFI_DYNAMIC_RX_BUFFER_NUM!"
30 #endif
31 
32 #if (CONFIG_ESP32_WIFI_RX_BA_WIN > (CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM << 1))
33 #error "WiFi configuration check: WARNING, WIFI_RX_BA_WIN should not be larger than double of the WIFI_STATIC_RX_BUFFER_NUM!"
34 #endif
35 
36 ESP_EVENT_DEFINE_BASE(WIFI_EVENT);
37 
38 extern uint8_t esp_wifi_get_user_init_flag_internal(void);
39 extern esp_err_t esp_supplicant_init(void);
40 extern esp_err_t esp_supplicant_deinit(void);
41 #ifdef CONFIG_PM_ENABLE
42 static esp_pm_lock_handle_t s_wifi_modem_sleep_lock;
43 #endif
44 
45 #if CONFIG_IDF_TARGET_ESP32
46 /* Callback function to update WiFi MAC time */
47 wifi_mac_time_update_cb_t s_wifi_mac_time_update_cb = NULL;
48 #endif
49 
50 /* Set additional WiFi features and capabilities */
51 uint64_t g_wifi_feature_caps =
52 #if CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE
53     CONFIG_FEATURE_WPA3_SAE_BIT |
54 #endif
55 #if (CONFIG_ESP32_SPIRAM_SUPPORT || CONFIG_ESP32S2_SPIRAM_SUPPORT || CONFIG_ESP32S3_SPIRAM_SUPPORT)
56     CONFIG_FEATURE_CACHE_TX_BUF_BIT |
57 #endif
58 #if CONFIG_ESP_WIFI_FTM_INITIATOR_SUPPORT
59     CONFIG_FEATURE_FTM_INITIATOR_BIT |
60 #endif
61 #if CONFIG_ESP_WIFI_FTM_RESPONDER_SUPPORT
62     CONFIG_FEATURE_FTM_RESPONDER_BIT |
63 #endif
64 0;
65 
66 static bool s_wifi_adc_xpd_flag;
67 
68 static const char* TAG = "wifi_init";
69 
s_set_default_wifi_log_level(void)70 static void __attribute__((constructor)) s_set_default_wifi_log_level(void)
71 {
72     /* WiFi libraries aren't compiled to know CONFIG_LOG_DEFAULT_LEVEL,
73        so set it at runtime startup. Done here not in esp_wifi_init() to allow
74        the user to set the level again before esp_wifi_init() is called.
75     */
76     esp_log_level_set("wifi", CONFIG_LOG_DEFAULT_LEVEL);
77     esp_log_level_set("mesh", CONFIG_LOG_DEFAULT_LEVEL);
78     esp_log_level_set("smartconfig", CONFIG_LOG_DEFAULT_LEVEL);
79     esp_log_level_set("ESPNOW", CONFIG_LOG_DEFAULT_LEVEL);
80 }
81 
esp_wifi_set_log_level(void)82 static void esp_wifi_set_log_level(void)
83 {
84     wifi_log_level_t wifi_log_level = WIFI_LOG_INFO;
85     /* set WiFi log level */
86 #if CONFIG_WIFI_LOG_DEFAULT_LEVEL_NONE
87     wifi_log_level = WIFI_LOG_NONE;
88 #elif CONFIG_WIFI_LOG_DEFAULT_LEVEL_ERROR
89     wifi_log_level = WIFI_LOG_ERROR;
90 #elif CONFIG_WIFI_LOG_DEFAULT_LEVEL_WARN
91     wifi_log_level = WIFI_LOG_WARNING;
92 #elif CONFIG_WIFI_LOG_DEFAULT_LEVEL_INFO
93     wifi_log_level = WIFI_LOG_INFO;
94 #elif CONFIG_WIFI_LOG_DEFAULT_LEVEL_DEBUG
95     wifi_log_level = WIFI_LOG_DEBUG;
96 #elif CONFIG_WIFI_LOG_DEFAULT_LEVEL_VERBOSE
97     wifi_log_level = WIFI_LOG_VERBOSE;
98 #endif
99     esp_wifi_internal_set_log_level(wifi_log_level);
100 }
101 
esp_wifi_deinit(void)102 esp_err_t esp_wifi_deinit(void)
103 {
104     esp_err_t err = ESP_OK;
105 
106     if (esp_wifi_get_user_init_flag_internal()) {
107         ESP_LOGE(TAG, "Wi-Fi not stop");
108         return ESP_ERR_WIFI_NOT_STOPPED;
109     }
110 
111     esp_supplicant_deinit();
112     err = esp_wifi_deinit_internal();
113     if (err != ESP_OK) {
114         ESP_LOGE(TAG, "Failed to deinit Wi-Fi driver (0x%x)", err);
115         return err;
116     }
117 
118 #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
119     tcpip_adapter_clear_default_wifi_handlers();
120 #endif
121 #if CONFIG_ESP_WIFI_SLP_IRAM_OPT
122     esp_pm_unregister_light_sleep_default_params_config_callback();
123 #endif
124 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
125 #if SOC_WIFI_HW_TSF
126     esp_pm_unregister_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active);
127     esp_pm_unregister_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
128     esp_sleep_disable_wifi_wakeup();
129 #endif
130 #endif
131 #if CONFIG_MAC_BB_PD
132     esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
133     esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
134 #endif
135     return err;
136 }
137 
esp_wifi_config_info(void)138 static void esp_wifi_config_info(void)
139 {
140 #ifdef CONFIG_ESP32_WIFI_RX_BA_WIN
141     ESP_LOGI(TAG, "rx ba win: %d", CONFIG_ESP32_WIFI_RX_BA_WIN);
142 #endif
143 
144 #ifdef CONFIG_ESP_NETIF_TCPIP_LWIP
145     ESP_LOGI(TAG, "tcpip mbox: %d", CONFIG_LWIP_TCPIP_RECVMBOX_SIZE);
146     ESP_LOGI(TAG, "udp mbox: %d", CONFIG_LWIP_UDP_RECVMBOX_SIZE);
147     ESP_LOGI(TAG, "tcp mbox: %d", CONFIG_LWIP_TCP_RECVMBOX_SIZE);
148     ESP_LOGI(TAG, "tcp tx win: %d", CONFIG_LWIP_TCP_SND_BUF_DEFAULT);
149     ESP_LOGI(TAG, "tcp rx win: %d", CONFIG_LWIP_TCP_WND_DEFAULT);
150     ESP_LOGI(TAG, "tcp mss: %d", CONFIG_LWIP_TCP_MSS);
151 
152 #ifdef CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP
153     ESP_LOGI(TAG, "WiFi/LWIP prefer SPIRAM");
154 #endif
155 
156 #ifdef CONFIG_ESP32_WIFI_IRAM_OPT
157     ESP_LOGI(TAG, "WiFi IRAM OP enabled");
158 #endif
159 
160 #ifdef CONFIG_ESP32_WIFI_RX_IRAM_OPT
161     ESP_LOGI(TAG, "WiFi RX IRAM OP enabled");
162 #endif
163 
164 #ifdef CONFIG_ESP_WIFI_SLP_IRAM_OPT
165     ESP_LOGI(TAG, "WiFi SLP IRAM OP enabled");
166 #endif
167 
168 #ifdef CONFIG_LWIP_IRAM_OPTIMIZATION
169     ESP_LOGI(TAG, "LWIP IRAM OP enabled");
170 #endif
171 
172 #else
173     ESP_LOGI(TAG, "LWIP disabled");
174 #endif
175 }
176 
esp_wifi_init(const wifi_init_config_t * config)177 esp_err_t esp_wifi_init(const wifi_init_config_t *config)
178 {
179 #ifdef CONFIG_PM_ENABLE
180     if (s_wifi_modem_sleep_lock == NULL) {
181         esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "wifi",
182                 &s_wifi_modem_sleep_lock);
183         if (err != ESP_OK) {
184             return err;
185         }
186     }
187 #endif
188 
189 #if CONFIG_ESP_WIFI_SLP_IRAM_OPT
190     esp_pm_register_light_sleep_default_params_config_callback(esp_wifi_internal_update_light_sleep_default_params);
191 
192     int min_freq_mhz = esp_pm_impl_get_cpu_freq(PM_MODE_LIGHT_SLEEP);
193     int max_freq_mhz = esp_pm_impl_get_cpu_freq(PM_MODE_CPU_MAX);
194     esp_wifi_internal_update_light_sleep_default_params(min_freq_mhz, max_freq_mhz);
195 
196     uint32_t sleep_delay_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME * 1000;
197     esp_wifi_set_sleep_delay_time(sleep_delay_us);
198 
199     uint32_t keep_alive_time_us = CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME * 1000 * 1000;
200     esp_wifi_set_keep_alive_time(keep_alive_time_us);
201 #endif
202 
203 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
204 #if CONFIG_MAC_BB_PD
205     if (esp_register_mac_bb_pd_callback(pm_mac_sleep) != ESP_OK
206         || esp_register_mac_bb_pu_callback(pm_mac_wakeup) != ESP_OK) {
207 
208         esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
209         esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
210         return ESP_ERR_INVALID_ARG;
211     }
212 #endif
213 
214 #if SOC_WIFI_HW_TSF
215     esp_err_t ret = esp_pm_register_skip_light_sleep_callback(esp_wifi_internal_is_tsf_active);
216     if (ret != ESP_OK) {
217         ESP_LOGE(TAG, "Failed to register skip light sleep callback (0x%x)", ret);
218 #if CONFIG_MAC_BB_PD
219         esp_unregister_mac_bb_pd_callback(pm_mac_sleep);
220         esp_unregister_mac_bb_pu_callback(pm_mac_wakeup);
221 #endif
222         return ret;
223     }
224     ret = esp_pm_register_inform_out_light_sleep_overhead_callback(esp_wifi_internal_update_light_sleep_wake_ahead_time);
225     if (ret != ESP_OK) {
226         ESP_LOGE(TAG, "Failed to register inform light sleep overhead callback (0x%x)", ret);
227         return ret;
228     }
229     esp_sleep_enable_wifi_wakeup();
230 #endif
231 #endif
232 
233 #if CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER
234     esp_err_t err = tcpip_adapter_set_default_wifi_handlers();
235     if (err != ESP_OK) {
236         ESP_LOGW(TAG, "Failed to set default Wi-Fi event handlers (0x%x)", err);
237     }
238 #endif
239 #if CONFIG_SW_COEXIST_ENABLE
240     coex_init();
241 #endif
242     esp_wifi_set_log_level();
243     esp_err_t result = esp_wifi_init_internal(config);
244     if (result == ESP_OK) {
245 #if CONFIG_MAC_BB_PD
246         esp_mac_bb_pd_mem_init();
247         esp_wifi_internal_set_mac_sleep(true);
248 #endif
249 #if CONFIG_IDF_TARGET_ESP32
250         s_wifi_mac_time_update_cb = esp_wifi_internal_update_mac_time;
251 #endif
252 
253         result = esp_supplicant_init();
254         if (result != ESP_OK) {
255             ESP_LOGE(TAG, "Failed to init supplicant (0x%x)", result);
256             esp_err_t deinit_ret = esp_wifi_deinit();
257             if (deinit_ret != ESP_OK) {
258                 ESP_LOGE(TAG, "Failed to deinit Wi-Fi (0x%x)", deinit_ret);
259             }
260 
261             return result;
262         }
263     }
264     adc2_cal_include(); //This enables the ADC2 calibration constructor at start up.
265 
266     esp_wifi_config_info();
267     return result;
268 }
269 
270 #ifdef CONFIG_PM_ENABLE
wifi_apb80m_request(void)271 void wifi_apb80m_request(void)
272 {
273     assert(s_wifi_modem_sleep_lock);
274     esp_pm_lock_acquire(s_wifi_modem_sleep_lock);
275     if (rtc_clk_apb_freq_get() != APB_CLK_FREQ) {
276         ESP_LOGE(__func__, "WiFi needs 80MHz APB frequency to work, but got %dHz", rtc_clk_apb_freq_get());
277     }
278 }
279 
wifi_apb80m_release(void)280 void wifi_apb80m_release(void)
281 {
282     assert(s_wifi_modem_sleep_lock);
283     esp_pm_lock_release(s_wifi_modem_sleep_lock);
284 }
285 #endif //CONFIG_PM_ENABLE
286 
287 /* Coordinate ADC power with other modules. This overrides the function from PHY lib. */
288 // It seems that it is only required on ESP32, but we still compile it for all chips, in case it is
289 // called by PHY unexpectedly.
set_xpd_sar(bool en)290 void set_xpd_sar(bool en)
291 {
292     if (s_wifi_adc_xpd_flag == en) {
293         /* ignore repeated calls to set_xpd_sar when the state is already correct */
294         return;
295     }
296 
297     s_wifi_adc_xpd_flag = en;
298     if (en) {
299         adc_power_acquire();
300     } else {
301         adc_power_release();
302     }
303 }
304 
305 #ifndef CONFIG_ESP_WIFI_FTM_ENABLE
ieee80211_ftm_attach(void)306 void ieee80211_ftm_attach(void)
307 {
308     /* Do not remove, stub to overwrite weak link in Wi-Fi Lib */
309 }
310 #endif
311