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