From 0631d185bdc7eb8bb495115c1a1cc8a87b9a75b9 Mon Sep 17 00:00:00 2001 From: liu zhifu Date: Fri, 13 Dec 2019 10:46:23 +0800 Subject: [PATCH] esp_wifi: fix a WiFi receiving bug Support WiFi/BT MAC register writting when the WiFi/BT common clock is disabled. --- components/esp32/esp_adapter.c | 2 + components/esp_wifi/include/esp_phy_init.h | 12 ++++ .../include/esp_private/wifi_os_adapter.h | 2 + components/esp_wifi/lib_esp32 | 2 +- components/esp_wifi/src/phy_init.c | 62 +++++++++++++++++-- 5 files changed, 75 insertions(+), 5 deletions(-) diff --git a/components/esp32/esp_adapter.c b/components/esp32/esp_adapter.c index 4c8763f2c..410a73025 100644 --- a/components/esp32/esp_adapter.c +++ b/components/esp32/esp_adapter.c @@ -561,6 +561,8 @@ wifi_osi_funcs_t g_wifi_osi_funcs = { ._dport_access_stall_other_cpu_end_wrap = esp_dport_access_stall_other_cpu_end_wrap, ._phy_rf_deinit = esp_phy_rf_deinit, ._phy_load_cal_and_init = esp_phy_load_cal_and_init, + ._phy_common_clock_enable = esp_phy_common_clock_enable, + ._phy_common_clock_disable = esp_phy_common_clock_disable, ._read_mac = esp_read_mac, ._timer_arm = timer_arm_wrapper, ._timer_disarm = timer_disarm_wrapper, diff --git a/components/esp_wifi/include/esp_phy_init.h b/components/esp_wifi/include/esp_phy_init.h index 6783ff54b..7c0d263b0 100644 --- a/components/esp_wifi/include/esp_phy_init.h +++ b/components/esp_wifi/include/esp_phy_init.h @@ -202,6 +202,18 @@ esp_err_t esp_phy_rf_deinit(phy_rf_module_t module); */ void esp_phy_load_cal_and_init(phy_rf_module_t module); +/** + * @brief Enable WiFi/BT common clock + * + */ +void esp_phy_common_clock_enable(void); + +/** + * @brief Disable WiFi/BT common clock + * + */ +void esp_phy_common_clock_disable(void); + /** * @brief Module requires to enter modem sleep */ diff --git a/components/esp_wifi/include/esp_private/wifi_os_adapter.h b/components/esp_wifi/include/esp_private/wifi_os_adapter.h index 89422c51c..bcae79f03 100644 --- a/components/esp_wifi/include/esp_private/wifi_os_adapter.h +++ b/components/esp_wifi/include/esp_private/wifi_os_adapter.h @@ -79,6 +79,8 @@ typedef struct { void (* _dport_access_stall_other_cpu_end_wrap)(void); int32_t (* _phy_rf_deinit)(uint32_t module); void (* _phy_load_cal_and_init)(uint32_t module); + void (* _phy_common_clock_enable)(void); + void (* _phy_common_clock_disable)(void); int32_t (* _read_mac)(uint8_t* mac, uint32_t type); void (* _timer_arm)(void *timer, uint32_t tmout, bool repeat); void (* _timer_disarm)(void *timer); diff --git a/components/esp_wifi/lib_esp32 b/components/esp_wifi/lib_esp32 index 92458e35a..67d89ac83 160000 --- a/components/esp_wifi/lib_esp32 +++ b/components/esp_wifi/lib_esp32 @@ -1 +1 @@ -Subproject commit 92458e35a2f10f1dedf48adbd00e561786837e63 +Subproject commit 67d89ac83b5b2063b328cbabcdd5512ee7919fc8 diff --git a/components/esp_wifi/src/phy_init.c b/components/esp_wifi/src/phy_init.c index 676494346..6b867dfa0 100644 --- a/components/esp_wifi/src/phy_init.c +++ b/components/esp_wifi/src/phy_init.c @@ -51,6 +51,12 @@ static uint32_t s_module_phy_rf_init = 0; /* Whether modem sleep is turned on */ static volatile bool s_is_phy_rf_en = false; +/* Whether WiFi/BT common clock enabled reference */ +static volatile int32_t s_common_clock_enable_ref = 0; + +/* PHY spinlock mux */ +static portMUX_TYPE s_phy_spin_lock = portMUX_INITIALIZER_UNLOCKED; + /* Bit mask of modules needing to enter modem sleep mode */ static uint32_t s_modem_sleep_module_enter = 0; @@ -114,7 +120,56 @@ static inline void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now) } } -esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibration_mode_t mode, +IRAM_ATTR static inline void phy_spin_lock(void) +{ + if (xPortInIsrContext()) { + portENTER_CRITICAL_ISR(&s_phy_spin_lock); + } else { + portENTER_CRITICAL(&s_phy_spin_lock); + } +} + +IRAM_ATTR static inline void phy_spin_unlock(void) +{ + if (xPortInIsrContext()) { + portEXIT_CRITICAL_ISR(&s_phy_spin_lock); + } else { + portEXIT_CRITICAL(&s_phy_spin_lock); + } +} + +IRAM_ATTR void esp_phy_common_clock_enable(void) +{ + phy_spin_lock(); + + if (s_common_clock_enable_ref == 0) { + // Enable WiFi/BT common clock + periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); + } + + s_common_clock_enable_ref++; + phy_spin_unlock(); +} + +IRAM_ATTR void esp_phy_common_clock_disable(void) +{ + phy_spin_lock(); + + if (s_common_clock_enable_ref > 0) { + s_common_clock_enable_ref --; + + if (s_common_clock_enable_ref == 0) { + // Disable WiFi/BT common clock + periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); + } + } else { + abort(); + } + + phy_spin_unlock(); +} + +esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibration_mode_t mode, esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module) { /* 3 modules may call phy_init: Wi-Fi, BT, Modem Sleep */ @@ -161,8 +216,7 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat s_phy_rf_en_ts = esp_timer_get_time(); // Update WiFi MAC time before WiFi/BT common clock is enabled phy_update_wifi_mac_time(false, s_phy_rf_en_ts); - // Enable WiFi/BT common peripheral clock - periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE); + esp_phy_common_clock_enable(); phy_set_wifi_mode_only(0); if (ESP_CAL_DATA_CHECK_FAIL == register_chipv7_phy(init_data, calibration_data, mode)) { @@ -247,7 +301,7 @@ esp_err_t esp_phy_rf_deinit(phy_rf_module_t module) // Update WiFi MAC time before disalbe WiFi/BT common peripheral clock phy_update_wifi_mac_time(true, esp_timer_get_time()); // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG - periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); + esp_phy_common_clock_disable(); } }