Просмотр исходного кода

esp_wifi: fix a WiFi receiving bug

Support WiFi/BT MAC register writting when the WiFi/BT common clock is disabled.
liu zhifu 6 лет назад
Родитель
Сommit
e1eeef2276

+ 2 - 0
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,

+ 12 - 0
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
  */

+ 2 - 0
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);

+ 1 - 1
components/esp_wifi/lib

@@ -1 +1 @@
-Subproject commit b64f976ee8cb345f686b345da35dfbbc72ae054e
+Subproject commit dcbca2f6b342049d78ec7790aaea77ccc3a4a69b

+ 57 - 3
components/esp_wifi/src/phy_init.c

@@ -57,6 +57,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;
 
@@ -124,6 +130,55 @@ static inline void phy_update_wifi_mac_time(bool en_clock_stopped, int64_t now)
 }
 #endif
 
+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)
 {
@@ -173,8 +228,7 @@ 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);
 #endif
-            // 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 CONFIG_IDF_TARGET_ESP32S2BETA
@@ -269,7 +323,7 @@ esp_err_t esp_phy_rf_deinit(phy_rf_module_t module)
             phy_update_wifi_mac_time(true, esp_timer_get_time());
 #endif
             // 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();
         }
     }