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

Merge branch 'bugfix/auto_beacon_recv_fail_enable_light_sleep_after_modem_sleep' into 'master'

fix the issue of failure of receiving beacons in modem state

See merge request espressif/esp-idf!22900
Jiang Jiang Jian 2 лет назад
Родитель
Сommit
796250c63d

+ 7 - 0
components/esp_hw_support/include/esp_private/sleep_modem.h

@@ -42,6 +42,13 @@ void mac_bb_power_up_cb_execute(void);
 
 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
 
+/**
+ * @brief The retention action in the modem state of WiFi PHY module
+ *
+ * @param restore  true for restore the PHY context, false for backup the PHY context
+ */
+void sleep_modem_wifi_do_phy_retention(bool restore);
+
 /**
  * @brief Get WiFi modem state
  *

+ 35 - 1
components/esp_hw_support/sleep_modem.c

@@ -13,6 +13,7 @@
 #include "esp_attr.h"
 #include "esp_sleep.h"
 #include "soc/soc_caps.h"
+#include "esp_private/pm_impl.h"
 #include "esp_private/sleep_modem.h"
 #include "esp_private/sleep_retention.h"
 #include "sdkconfig.h"
@@ -26,6 +27,7 @@
 
 #if SOC_PM_SUPPORT_PMU_MODEM_STATE
 #include "soc/pmu_reg.h"
+#include "esp_private/esp_pau.h"
 #endif
 
 static __attribute__((unused)) const char *TAG = "sleep_modem";
@@ -153,10 +155,17 @@ typedef struct {
 typedef struct sleep_modem_config {
     struct {
         void    *phy_link;
+        union {
+            struct {
+                uint32_t modem_state_phy_done: 1;
+                uint32_t reserved: 31;
+            };
+            uint32_t flags;
+        };
     } wifi;
 } sleep_modem_config_t;
 
-static sleep_modem_config_t s_sleep_modem = { .wifi.phy_link = NULL };
+static sleep_modem_config_t s_sleep_modem = { .wifi.phy_link = NULL, .wifi.flags = 0 };
 
 static __attribute__((unused)) esp_err_t sleep_modem_wifi_modem_state_init(void)
 {
@@ -229,6 +238,7 @@ static __attribute__((unused)) esp_err_t sleep_modem_wifi_modem_state_init(void)
         if (err == ESP_OK) {
             pau_regdma_set_modem_link_addr(link);
             s_sleep_modem.wifi.phy_link = link;
+            s_sleep_modem.wifi.flags = 0;
         }
     }
     return err;
@@ -239,6 +249,19 @@ static __attribute__((unused)) void sleep_modem_wifi_modem_state_deinit(void)
     if (s_sleep_modem.wifi.phy_link) {
         regdma_link_destroy(s_sleep_modem.wifi.phy_link, 0);
         s_sleep_modem.wifi.phy_link = NULL;
+        s_sleep_modem.wifi.flags = 0;
+    }
+}
+
+void IRAM_ATTR sleep_modem_wifi_do_phy_retention(bool restore)
+{
+    if (restore) {
+        if (s_sleep_modem.wifi.modem_state_phy_done == 1) {
+            pau_regdma_trigger_modem_link_restore();
+        }
+    } else {
+        pau_regdma_trigger_modem_link_backup();
+        s_sleep_modem.wifi.modem_state_phy_done = 1;
     }
 }
 
@@ -269,16 +292,27 @@ uint32_t IRAM_ATTR sleep_modem_reject_triggers(void)
     return reject_triggers;
 }
 
+static __attribute__((unused)) bool IRAM_ATTR sleep_modem_wifi_modem_state_skip_light_sleep(void)
+{
+    bool skip = false;
+#if SOC_PM_SUPPORT_PMU_MODEM_STATE
+    skip = (s_sleep_modem.wifi.phy_link != NULL) && (s_sleep_modem.wifi.modem_state_phy_done == 0);
+#endif
+    return skip;
+}
+
 esp_err_t sleep_modem_configure(int max_freq_mhz, int min_freq_mhz, bool light_sleep_enable)
 {
 #if CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP
     extern int esp_wifi_internal_mac_sleep_configure(bool, bool);
     if (light_sleep_enable) {
         if (sleep_modem_wifi_modem_state_init() == ESP_OK) {
+            esp_pm_register_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep);
             esp_wifi_internal_mac_sleep_configure(light_sleep_enable, true); /* require WiFi to enable automatically receives the beacon */
         }
     } else {
         esp_wifi_internal_mac_sleep_configure(light_sleep_enable, false); /* require WiFi to disable automatically receives the beacon */
+        esp_pm_unregister_skip_light_sleep_callback(sleep_modem_wifi_modem_state_skip_light_sleep);
         sleep_modem_wifi_modem_state_deinit();
     }
 #endif

+ 2 - 3
components/esp_phy/src/phy_init.c

@@ -42,7 +42,6 @@
 #include "soc/dport_reg.h"
 #elif CONFIG_IDF_TARGET_ESP32C6
 #include "esp_private/sleep_modem.h"
-#include "esp_private/esp_pau.h"
 #endif
 #include "hal/efuse_hal.h"
 
@@ -253,7 +252,7 @@ void esp_phy_enable(void)
             extern bool pm_mac_modem_rf_already_enabled(void);
             if (!pm_mac_modem_rf_already_enabled()) {
                 if (sleep_modem_wifi_modem_state_enabled()) {
-                    pau_regdma_trigger_modem_link_restore();
+                    sleep_modem_wifi_do_phy_retention(true);
                 } else {
                     phy_wakeup_init();
                 }
@@ -287,7 +286,7 @@ void esp_phy_disable(void)
 #endif
 #if SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP
         if (sleep_modem_wifi_modem_state_enabled()) {
-            pau_regdma_trigger_modem_link_backup();
+            sleep_modem_wifi_do_phy_retention(false);
         } else
 #endif /* SOC_PM_SUPPORT_PMU_MODEM_STATE && CONFIG_ESP_WIFI_ENHANCED_LIGHT_SLEEP */
         {

+ 1 - 1
components/esp_pm/pm_impl.c

@@ -100,7 +100,7 @@ static uint32_t s_mode_mask;
 
 #if CONFIG_FREERTOS_USE_TICKLESS_IDLE
 
-#define PERIPH_SKIP_LIGHT_SLEEP_NO 1
+#define PERIPH_SKIP_LIGHT_SLEEP_NO 2
 
 /* Indicates if light sleep shoule be skipped by peripherals. */
 static skip_light_sleep_cb_t s_periph_skip_light_sleep_cb[PERIPH_SKIP_LIGHT_SLEEP_NO];