From 8188138c35a1642182c52c9f913ef6fbb87240b7 Mon Sep 17 00:00:00 2001 From: ronghulin Date: Thu, 5 Dec 2019 11:12:26 +0800 Subject: [PATCH] esp32: fix a WiFi RX bug Support WiFi/BT MAC register writting when the WiFi/BT common clock is disabled. --- components/esp32/esp_adapter.c | 2 + components/esp32/include/esp_phy_init.h | 12 ++++ .../esp32/include/esp_wifi_os_adapter.h | 2 + components/esp32/lib | 2 +- components/esp32/phy_init.c | 62 ++++++++++++++++++- 5 files changed, 77 insertions(+), 3 deletions(-) diff --git a/components/esp32/esp_adapter.c b/components/esp32/esp_adapter.c index 70f1bb5c48..25fd6f8e40 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/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h index 6783ff54b4..3402f197b0 100644 --- a/components/esp32/include/esp_phy_init.h +++ b/components/esp32/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/esp32/include/esp_wifi_os_adapter.h b/components/esp32/include/esp_wifi_os_adapter.h index c8b8766dea..89778661a4 100644 --- a/components/esp32/include/esp_wifi_os_adapter.h +++ b/components/esp32/include/esp_wifi_os_adapter.h @@ -78,6 +78,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/esp32/lib b/components/esp32/lib index 87ea041429..18a0319f5d 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit 87ea0414299f8b44d2424b85697ed24946ff3e99 +Subproject commit 18a0319f5d8777332b4a62bfb86b82904506bd27 diff --git a/components/esp32/phy_init.c b/components/esp32/phy_init.c index 967b4d02d1..74fa3a4855 100644 --- a/components/esp32/phy_init.c +++ b/components/esp32/phy_init.c @@ -52,6 +52,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; @@ -115,6 +121,56 @@ static inline void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now) } } +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) { @@ -163,7 +219,8 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat // 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); + //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 +304,8 @@ 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); + //periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE); + esp_phy_common_clock_disable(); } }