From 91006fdee1316da6d0caf816bcb437a03cdd49a1 Mon Sep 17 00:00:00 2001 From: liuning Date: Wed, 28 Feb 2024 11:54:23 +0800 Subject: [PATCH] feat(phy): support to query phy used time --- components/esp_phy/Kconfig | 5 ++ components/esp_phy/include/esp_phy_init.h | 18 +++++++ components/esp_phy/src/phy_init.c | 61 +++++++++++++++++++++- components/esp_phy/src/phy_init_esp32hxx.c | 61 +++++++++++++++++++++- 4 files changed, 143 insertions(+), 2 deletions(-) diff --git a/components/esp_phy/Kconfig b/components/esp_phy/Kconfig index c0837398e2..75b5be45cd 100644 --- a/components/esp_phy/Kconfig +++ b/components/esp_phy/Kconfig @@ -172,5 +172,10 @@ menu "PHY" help If enabled, there will be some logs while pll tracking + config ESP_PHY_RECORD_USED_TIME + bool "Record PHY used time" + default n + help + Select to support record and query phy used time. endif endmenu # PHY diff --git a/components/esp_phy/include/esp_phy_init.h b/components/esp_phy/include/esp_phy_init.h index 95756568b4..2e194f707b 100644 --- a/components/esp_phy/include/esp_phy_init.h +++ b/components/esp_phy/include/esp_phy_init.h @@ -38,6 +38,7 @@ typedef enum { PHY_MODEM_WIFI = 1, /*!< PHY modem WIFI */ PHY_MODEM_BT = 2, /*!< PHY modem BT */ PHY_MODEM_IEEE802154 = 4, /*!< PHY modem IEEE802154 */ + PHY_MODEM_MAX, /*!< Don't use it. Used by ESP_PHY_MODEM_COUNT_MAX */ } esp_phy_modem_t; /** @@ -286,6 +287,23 @@ void phy_init_param_set(uint8_t param); */ void phy_wifi_enable_set(uint8_t enable); +#if CONFIG_ESP_PHY_RECORD_USED_TIME +/** + * @brief Get phy used time from different modem + * @param used_time pointer of variable to get used time, in microseconds + * @param modem modem type + * @return ESP_ERR_INVALID_ARG on incorrect modem type. + */ +esp_err_t phy_query_used_time(uint64_t *used_time, esp_phy_modem_t modem); + +/** + * @brief Clear phy used time for different modem + * @param modem modem type + * @return ESP_ERR_INVALID_ARG on incorrect modem type. + */ +esp_err_t phy_clear_used_time(esp_phy_modem_t modem); +#endif + #ifdef __cplusplus } #endif diff --git a/components/esp_phy/src/phy_init.c b/components/esp_phy/src/phy_init.c index bc495b3031..86f1cbb5e0 100644 --- a/components/esp_phy/src/phy_init.c +++ b/components/esp_phy/src/phy_init.c @@ -161,6 +161,60 @@ static phy_country_to_bin_type_t s_country_code_map_type_table[] = { {"US", ESP_PHY_INIT_DATA_TYPE_FCC}, }; #endif + +#if CONFIG_ESP_PHY_RECORD_USED_TIME +#define ESP_PHY_MODEM_COUNT_MAX (__builtin_ffs(PHY_MODEM_MAX - 1)) +#define ESP_PHY_IS_VALID_MODEM(modem) (__builtin_popcount(modem) == 1 && __builtin_ctz(modem) < ESP_PHY_MODEM_COUNT_MAX) + +static DRAM_ATTR struct { + uint64_t used_time; + uint64_t enabled_time; + uint64_t disabled_time; +} s_phy_rf_used_info[ESP_PHY_MODEM_COUNT_MAX]; + +static IRAM_ATTR void phy_record_time(bool enabled, esp_phy_modem_t modem) { + uint8_t index = __builtin_ctz(modem); + if (enabled) { + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].disabled_time = esp_timer_get_time(); + s_phy_rf_used_info[index].used_time += s_phy_rf_used_info[index].disabled_time - s_phy_rf_used_info[index].enabled_time; + } +} + +esp_err_t phy_query_used_time(uint64_t *used_time, esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + *used_time = s_phy_rf_used_info[index].used_time; + if (s_phy_rf_used_info[index].disabled_time < s_phy_rf_used_info[index].enabled_time) { + // phy is being used + *used_time += esp_timer_get_time() - s_phy_rf_used_info[index].enabled_time; + } + _lock_release(&s_phy_access_lock); + return ESP_OK; +} + +esp_err_t phy_clear_used_time(esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + if (s_phy_rf_used_info[index].enabled_time > s_phy_rf_used_info[index].disabled_time) { + // phy is being used + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].enabled_time = s_phy_rf_used_info[index].disabled_time; + } + s_phy_rf_used_info[index].used_time = 0; + _lock_release(&s_phy_access_lock); + return ESP_OK; +} +#endif + uint32_t IRAM_ATTR phy_enter_critical(void) { if (xPortInIsrContext()) { @@ -293,13 +347,18 @@ void esp_phy_enable(esp_phy_modem_t modem) phy_track_pll(); #endif +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(true, modem); +#endif _lock_release(&s_phy_access_lock); } void esp_phy_disable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); - +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(false, modem); +#endif phy_clr_modem_flag(modem); if (phy_get_modem_flag() == 0) { // ESP32 will track pll in the wifi/BT modem interrupt handler. diff --git a/components/esp_phy/src/phy_init_esp32hxx.c b/components/esp_phy/src/phy_init_esp32hxx.c index d0d3e2a20b..9ff88d452f 100644 --- a/components/esp_phy/src/phy_init_esp32hxx.c +++ b/components/esp_phy/src/phy_init_esp32hxx.c @@ -8,6 +8,7 @@ #include "freertos/portmacro.h" #include "esp_phy_init.h" #include "esp_private/phy.h" +#include "esp_timer.h" #if SOC_MODEM_CLOCK_IS_INDEPENDENT #include "esp_private/esp_modem_clock.h" @@ -23,6 +24,59 @@ static _lock_t s_phy_access_lock; /* Reference count of enabling PHY */ static bool s_phy_is_enabled = false; +#if CONFIG_ESP_PHY_RECORD_USED_TIME +#define ESP_PHY_MODEM_COUNT_MAX (__builtin_ffs(PHY_MODEM_MAX - 1)) +#define ESP_PHY_IS_VALID_MODEM(modem) (__builtin_popcount(modem) == 1 && __builtin_ctz(modem) < ESP_PHY_MODEM_COUNT_MAX) + +static DRAM_ATTR struct { + uint64_t used_time; + uint64_t enabled_time; + uint64_t disabled_time; +} s_phy_rf_used_info[ESP_PHY_MODEM_COUNT_MAX]; + +static IRAM_ATTR void phy_record_time(bool enabled, esp_phy_modem_t modem) { + uint8_t index = __builtin_ctz(modem); + if (enabled) { + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].disabled_time = esp_timer_get_time(); + s_phy_rf_used_info[index].used_time += s_phy_rf_used_info[index].disabled_time - s_phy_rf_used_info[index].enabled_time; + } +} + +esp_err_t phy_query_used_time(uint64_t *used_time, esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + *used_time = s_phy_rf_used_info[index].used_time; + if (s_phy_rf_used_info[index].disabled_time < s_phy_rf_used_info[index].enabled_time) { + // phy is being used + *used_time += esp_timer_get_time() - s_phy_rf_used_info[index].enabled_time; + } + _lock_release(&s_phy_access_lock); + return ESP_OK; +} + +esp_err_t phy_clear_used_time(esp_phy_modem_t modem) { + if (!ESP_PHY_IS_VALID_MODEM(modem)) { + return ESP_ERR_INVALID_ARG; + } + uint8_t index = __builtin_ctz(modem); + _lock_acquire(&s_phy_access_lock); + if (s_phy_rf_used_info[index].enabled_time > s_phy_rf_used_info[index].disabled_time) { + // phy is being used + s_phy_rf_used_info[index].enabled_time = esp_timer_get_time(); + } else { + s_phy_rf_used_info[index].enabled_time = s_phy_rf_used_info[index].disabled_time; + } + s_phy_rf_used_info[index].used_time = 0; + _lock_release(&s_phy_access_lock); + return ESP_OK; +} +#endif + uint32_t IRAM_ATTR phy_enter_critical(void) { if (xPortInIsrContext()) { @@ -64,13 +118,18 @@ void esp_phy_enable(esp_phy_modem_t modem) phy_set_modem_flag(modem); // Immediately track pll when phy enabled. phy_track_pll(); +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(true, modem); +#endif _lock_release(&s_phy_access_lock); } void esp_phy_disable(esp_phy_modem_t modem) { _lock_acquire(&s_phy_access_lock); - +#if CONFIG_ESP_PHY_RECORD_USED_TIME + phy_record_time(false, modem); +#endif phy_clr_modem_flag(modem); if (phy_get_modem_flag() == 0) {