From 9377d4acd48a42b6d0ec49b4ee4679d333204782 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 20 Mar 2018 18:06:58 +0800 Subject: [PATCH 1/3] pm: fix incorrect configuration at startup s_cpu_freq_by_mode array was statically initialised with 80MHz CPU frequency in CPU_MAX and APB_MAX modes, but sdkconfig setting for the CPU frequency could have been different. For the case of 240MHz CPU frequency, this would cause a frequency switch between 240MHz and 80MHz to happen, even though such switch is not supported in the fast path switching functions used by the DFS implementation. This fixes the issue by moving initialisation into esp_pm_impl_init, which is called at startup before the first mode switch can happen. Fixes https://github.com/espressif/esp-idf/issues/1729. --- components/esp32/pm_esp32.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/components/esp32/pm_esp32.c b/components/esp32/pm_esp32.c index 5866484a7..8a1005f43 100644 --- a/components/esp32/pm_esp32.c +++ b/components/esp32/pm_esp32.c @@ -82,14 +82,9 @@ static bool s_core_idle[portNUM_PROCESSORS]; extern uint32_t g_ticks_per_us_pro; /* Lookup table of CPU frequencies to be used in each mode. - * Modified by esp_pm_configure. + * Initialized by esp_pm_impl_init and modified by esp_pm_configure. */ -rtc_cpu_freq_t s_cpu_freq_by_mode[PM_MODE_COUNT] = { - [PM_MODE_LIGHT_SLEEP] = (rtc_cpu_freq_t) -1, /* unused */ - [PM_MODE_APB_MIN] = RTC_CPU_FREQ_XTAL, - [PM_MODE_APB_MAX] = RTC_CPU_FREQ_80M, - [PM_MODE_CPU_MAX] = RTC_CPU_FREQ_80M, -}; +rtc_cpu_freq_t s_cpu_freq_by_mode[PM_MODE_COUNT]; /* Lookup table of CPU ticks per microsecond for each RTC_CPU_FREQ_ value. * Essentially the same as returned by rtc_clk_cpu_freq_value(), but without @@ -192,6 +187,7 @@ esp_err_t esp_pm_configure(const void* vconfig) s_cpu_freq_by_mode[PM_MODE_CPU_MAX] = max_freq; s_cpu_freq_by_mode[PM_MODE_APB_MAX] = apb_max_freq; s_cpu_freq_by_mode[PM_MODE_APB_MIN] = min_freq; + s_cpu_freq_by_mode[PM_MODE_LIGHT_SLEEP] = min_freq; s_light_sleep_en = config->light_sleep_enable; portEXIT_CRITICAL(&s_switch_lock); @@ -452,5 +448,14 @@ void esp_pm_impl_init() ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "rtos1", &s_rtos_lock_handle[1])); ESP_ERROR_CHECK(esp_pm_lock_acquire(s_rtos_lock_handle[1])); + + /* Configure all modes to use the default CPU frequency. + * This will be modified later by a call to esp_pm_configure. + */ + rtc_cpu_freq_t default_freq; + assert(rtc_clk_cpu_freq_from_mhz(CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ, &default_freq)); + for (size_t i = 0; i < PM_MODE_COUNT; ++i) { + s_cpu_freq_by_mode[i] = default_freq; + } #endif // portNUM_PROCESSORS == 2 } From 7167ad45abf81847aa4cc8a2f719c7801e6b3290 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 20 Mar 2018 18:08:19 +0800 Subject: [PATCH 2/3] pm: improve debug output from esp_pm_dump_locks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - separate mode stats from lock stats by an extra comment line - add CPU frequency column to the mode stats - don’t print a row for light sleep if light sleep is not enabled --- components/esp32/pm_esp32.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/components/esp32/pm_esp32.c b/components/esp32/pm_esp32.c index 8a1005f43..5d422f3b8 100644 --- a/components/esp32/pm_esp32.c +++ b/components/esp32/pm_esp32.c @@ -426,9 +426,15 @@ void esp_pm_impl_dump_stats(FILE* out) time_in_mode[cur_mode] += now - last_mode_change_time; + fprintf(out, "Mode stats:\n"); for (int i = 0; i < PM_MODE_COUNT; ++i) { - fprintf(out, "%8s %12lld %2d%%\n", + if (i == PM_MODE_LIGHT_SLEEP && !s_light_sleep_en) { + /* don't display light sleep mode if it's not enabled */ + continue; + } + fprintf(out, "%8s %6s %12lld %2d%%\n", s_mode_names[i], + s_freq_names[s_cpu_freq_by_mode[i]], time_in_mode[i], (int) (time_in_mode[i] * 100 / now)); } From 1618dbc9a559044dd36f8c2fdb50352e3729072c Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 20 Mar 2018 18:27:32 +0800 Subject: [PATCH 3/3] soc/rtc: wait for frequency switch to complete The fast path of CPU frequency switch function, used in DFS, was not waiting for the frequency switch to complete when switching from XTAL to PLL. This resulted in incorrect reads from peripherals on APB, where two consecutive reads could return the same value. For example, in esp_timer, read of FRC_COUNT_REG would return same value as the preceding read of FRC_ALARM_REG, causing time to jump by the value of FRC_ALARM_REG / apb_freq_mhz. --- components/soc/esp32/rtc_clk.c | 1 + 1 file changed, 1 insertion(+) diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index 54dea84c5..eb72da2ce 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -402,6 +402,7 @@ void rtc_clk_cpu_freq_set_fast(rtc_cpu_freq_t cpu_freq) rtc_clk_cpu_freq_to_xtal(); } else if (cpu_freq > RTC_CPU_FREQ_XTAL) { rtc_clk_cpu_freq_to_pll(cpu_freq); + rtc_clk_wait_for_slow_cycle(); } }