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 */
219206static 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