@@ -46,42 +46,58 @@ float common_hal_mcu_processor_get_voltage(void) {
4646}
4747
4848uint32_t common_hal_mcu_processor_get_frequency (void ) {
49+ #if CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY
4950 esp_pm_config_t pm ;
5051 CHECK_ESP_RESULT (esp_pm_get_configuration (& pm ));
5152 return pm .min_freq_mhz * 1000000 ;
53+ #else
54+ return CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000 ;
55+ #endif
5256}
5357
54- #if defined(CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY ) // Don't need a NotImplementedError here if this is false, as that is handled in shared-bindings
55- static void validate_cpu_frequency (uint32_t freq_mhz ) {
58+ #if CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY // Don't need a NotImplementedError here if this is false, as that is handled in shared-bindings
59+ // If the requested frequency is not supported by the hardware, return the next lower supported frequency
60+ static uint32_t get_valid_cpu_frequency (uint32_t requested_freq_mhz ) {
61+
5662 #if defined(CONFIG_IDF_TARGET_ESP32C3 ) || defined(CONFIG_IDF_TARGET_ESP32C6 )
57- if (freq_mhz != 20 && freq_mhz != 40 && freq_mhz != 80 && freq_mhz != 160 ) {
58- mp_raise_ValueError (MP_ERROR_TEXT ("Frequency must be 20, 40, 80 or 160MHz" ));
59- }
63+ uint32_t valid_cpu_frequencies [] = {20 , 40 , 80 , 160 };
6064 #elif defined(CONFIG_IDF_TARGET_ESP32C2 )
61- if (freq_mhz != 20 && freq_mhz != 40 && freq_mhz != 80 && freq_mhz != 120 ) {
62- mp_raise_ValueError (MP_ERROR_TEXT ("Frequency must be 20, 40, 80 or 120MHz" ));
63- }
65+ uint32_t valid_cpu_frequencies [] = {20 , 40 , 80 , 120 };
6466 #elif defined(CONFIG_IDF_TARGET_ESP32H2 )
65- if (freq_mhz != 32 && freq_mhz != 48 && freq_mhz != 64 && freq_mhz != 96 ) {
66- mp_raise_ValueError (MP_ERROR_TEXT ("Frequency must be 32, 48, 64 or 96MHz" ));
67- }
67+ uint32_t valid_cpu_frequencies [] = {32 , 48 , 64 , 96 };
6868 #else
69- if (freq_mhz != 20 && freq_mhz != 40 && freq_mhz != 80 && freq_mhz != 160 && freq_mhz != 240 ) {
70- mp_raise_ValueError (MP_ERROR_TEXT ("Frequency must be 20, 40, 80, 160 or 240MHz" ));
71- }
69+ uint32_t valid_cpu_frequencies [] = {20 , 40 , 80 , 160 , 240 };
7270 #endif
71+
72+ if (requested_freq_mhz < valid_cpu_frequencies [0 ]) {
73+ // Don't round to the lowest valid frequency automatically here because the lowest valid frequency
74+ // can break UART/USB connection on some boards and it's very easy to trigger this case accidentally
75+ // (e.g. accidentally setting the frequency to 16000000 instead of 160000000,
76+ // or setting the frequency to 160 instead of 160000000). So trigger an exception instead.
77+ mp_raise_ValueError_varg (MP_ERROR_TEXT ("Invalid %q" ), MP_QSTR_frequency );
78+ }
79+
80+ const size_t num_valid_frequencies = MP_ARRAY_SIZE (valid_cpu_frequencies );
81+
82+ for (size_t i = 1 ; i < num_valid_frequencies ; i ++ ) {
83+ if (requested_freq_mhz < valid_cpu_frequencies [i ]) {
84+ return valid_cpu_frequencies [i - 1 ];
85+ }
86+ }
87+
88+ return valid_cpu_frequencies [num_valid_frequencies - 1 ];
7389}
7490
7591void common_hal_mcu_processor_set_frequency (mcu_processor_obj_t * self , uint32_t frequency ) {
76- // Without this check, everything would compile without error , but silently fail at runtime if
92+ // Without this check, everything would compile without errors , but silently fail at runtime if
7793 // CONFIG_PM_ENABLE is ever accidentally disabled
7894 #if !defined(CONFIG_PM_ENABLE )
7995 #error "common_hal_mcu_processor_set_frequency needs CONFIG_PM_ENABLE to be defined."
8096 #endif
8197
8298 frequency /= 1000000 ;
8399
84- validate_cpu_frequency (frequency );
100+ frequency = get_valid_cpu_frequency (frequency );
85101
86102 esp_pm_config_t pm ;
87103 pm .max_freq_mhz = frequency ;
0 commit comments