Skip to content

Commit 041a937

Browse files
committed
Merge branch 'fix/fix_esp32p4_freq_switching_timing' into 'master'
fix(esp_hw_support): fix esp32p4 CPU frequency switching timing Closes IDFCI-2280 and IDFCI-2281 See merge request espressif/esp-idf!33823
2 parents 2bb613c + e1a3414 commit 041a937

File tree

1 file changed

+44
-40
lines changed
  • components/esp_hw_support/port/esp32p4

1 file changed

+44
-40
lines changed

components/esp_hw_support/port/esp32p4/rtc_clk.c

Lines changed: 44 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "soc/rtc.h"
1515
#include "esp_private/rtc_clk.h"
1616
#include "esp_attr.h"
17-
#include "esp_cpu.h"
1817
#include "esp_hw_log.h"
1918
#include "esp_rom_sys.h"
2019
#include "hal/clk_tree_ll.h"
@@ -183,13 +182,7 @@ static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div, bool to_default)
183182
clk_ll_mem_set_divider(mem_divider);
184183
clk_ll_sys_set_divider(sys_divider);
185184
clk_ll_apb_set_divider(apb_divider);
186-
#if (!defined(BOOTLOADER_BUILD) && (CONFIG_FREERTOS_NUMBER_OF_CORES == 2))
187-
esp_cpu_stall(1 - esp_cpu_get_core_id());
188-
#endif
189185
clk_ll_bus_update();
190-
#if (!defined(BOOTLOADER_BUILD) && (CONFIG_FREERTOS_NUMBER_OF_CORES == 2))
191-
esp_cpu_unstall(1 - esp_cpu_get_core_id());
192-
#endif
193186
esp_rom_set_cpu_ticks_per_us(cpu_freq);
194187
}
195188

@@ -201,13 +194,7 @@ static void rtc_clk_cpu_freq_to_8m(void)
201194
clk_ll_sys_set_divider(1);
202195
clk_ll_apb_set_divider(1);
203196
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
204-
#if (!defined(BOOTLOADER_BUILD) && (CONFIG_FREERTOS_NUMBER_OF_CORES == 2))
205-
esp_cpu_stall(1 - esp_cpu_get_core_id());
206-
#endif
207197
clk_ll_bus_update();
208-
#if (!defined(BOOTLOADER_BUILD) && (CONFIG_FREERTOS_NUMBER_OF_CORES == 2))
209-
esp_cpu_unstall(1 - esp_cpu_get_core_id());
210-
#endif
211198
esp_rom_set_cpu_ticks_per_us(20);
212199
}
213200

@@ -218,15 +205,18 @@ static void rtc_clk_cpu_freq_to_8m(void)
218205
*/
219206
static void rtc_clk_cpu_freq_to_cpll_mhz(int cpu_freq_mhz, hal_utils_clk_div_t *div)
220207
{
221-
// CPLL -> CPU_CLK -> MEM_CLK -> SYS_CLK -> APB_CLK
222-
// Constraint: MEM_CLK <= 200MHz, APB_CLK <= 100MHz
223-
// This implies that when clock source is CPLL,
224-
// If cpu_divider < 2, mem_divider must be larger or equal to 2
225-
// If cpu_divider < 2, mem_divider = 2, sys_divider < 2, apb_divider must be larger or equal to 2
226-
// Current available configurations:
227-
// 360 - 360 - 180 - 180 - 90
228-
// 360 - 180 - 180 - 180 - 90
229-
// 360 - 90 - 90 - 90 - 90
208+
/**
209+
* Constraint: MEM_CLK <= 200MHz, APB_CLK <= 100MHz
210+
* This implies that when clock source is CPLL,
211+
* If cpu_divider < 2, mem_divider must be larger or equal to 2
212+
* If cpu_divider < 2, mem_divider = 2, sys_divider < 2, apb_divider must be larger or equal to 2
213+
*
214+
* Current available configurations:
215+
* CPLL -> CPU_CLK -> MEM_CLK -> SYS_CLK -> APB_CLK
216+
* 360 div1 360 div2 180 div1 180 div2 90
217+
* 360 div2 180 div1 180 div1 180 div2 90
218+
* 360 div4 90 div1 90 div1 90 div1 90
219+
*/
230220
uint32_t mem_divider = 1;
231221
uint32_t sys_divider = 1; // We are not going to change this
232222
uint32_t apb_divider = 1;
@@ -250,25 +240,39 @@ static void rtc_clk_cpu_freq_to_cpll_mhz(int cpu_freq_mhz, hal_utils_clk_div_t *
250240
// To avoid such case, we will strictly do abort here.
251241
abort();
252242
}
253-
// Update bit does not control CPU clock sel mux. Therefore, there may be a middle state during the switch (CPU rises)
254-
// Since this is upscaling, we need to configure the frequency division coefficient before switching the clock source.
255-
// Otherwise, an intermediate state will occur, in the intermediate state, the frequency of APB/MEM does not meet the
256-
// timing requirements. If there are periperals access that depend on these two clocks at this moment, some exception
257-
// might occur.
258-
clk_ll_cpu_set_divider(div->integer, div->numerator, div->denominator);
259-
clk_ll_mem_set_divider(mem_divider);
260-
clk_ll_sys_set_divider(sys_divider);
261-
clk_ll_apb_set_divider(apb_divider);
262-
#if (!defined(BOOTLOADER_BUILD) && (CONFIG_FREERTOS_NUMBER_OF_CORES == 2))
263-
// During frequency switching, non-frequency switching cores may have ongoing memory accesses, which may cause access
264-
// failures, stalling non-frequency switching cores here can avoid such failures.
265-
esp_cpu_stall(1 - esp_cpu_get_core_id());
266-
#endif
267-
clk_ll_bus_update();
243+
244+
// If it's upscaling, the divider of MEM/SYS/APB needs to be increased, to avoid illegal intermediate states,
245+
// the clock divider should be updated in the order from the APB_CLK to CPU_CLK.
246+
// And if it's downscaling, the divider of MEM/SYS/APB needs to be decreased, the clock divider should be updated
247+
// in the order from the CPU_CLK to APB_CLK.
248+
// Otherwise, an intermediate state will occur, in the intermediate state, the frequency of APB/MEM does not meet
249+
// the timing requirements. If there are periperals/CPU access that depend on these two clocks at this moment, some
250+
// exception might occur.
251+
if (cpu_freq_mhz >= esp_rom_get_cpu_ticks_per_us()) {
252+
// Frequency Upscaling
253+
clk_ll_apb_set_divider(apb_divider);
254+
clk_ll_bus_update();
255+
clk_ll_sys_set_divider(sys_divider);
256+
clk_ll_bus_update();
257+
clk_ll_mem_set_divider(mem_divider);
258+
clk_ll_bus_update();
259+
clk_ll_cpu_set_divider(div->integer, div->numerator, div->denominator);
260+
clk_ll_bus_update();
261+
} else {
262+
// Frequency Downscaling
263+
clk_ll_cpu_set_divider(div->integer, div->numerator, div->denominator);
264+
clk_ll_bus_update();
265+
clk_ll_mem_set_divider(mem_divider);
266+
clk_ll_bus_update();
267+
clk_ll_sys_set_divider(sys_divider);
268+
clk_ll_bus_update();
269+
clk_ll_apb_set_divider(apb_divider);
270+
clk_ll_bus_update();
271+
}
272+
273+
// Update bit does not control CPU clock sel mux, the clock source needs to be switched at
274+
// last to avoid intermediate states.
268275
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
269-
#if (!defined(BOOTLOADER_BUILD) && (CONFIG_FREERTOS_NUMBER_OF_CORES == 2))
270-
esp_cpu_unstall(1 - esp_cpu_get_core_id());
271-
#endif
272276
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
273277
}
274278

0 commit comments

Comments
 (0)