Skip to content

Commit 08512c5

Browse files
authored
Merge pull request #9342 from Sola85/esp32-settable-cpu-frequency
esp: make cpu frequency settable
2 parents 4ebd5f5 + b8c6542 commit 08512c5

File tree

5 files changed

+74
-1
lines changed

5 files changed

+74
-1
lines changed

ports/espressif/common-hal/microcontroller/Processor.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010

1111
#include "py/runtime.h"
1212

13+
#include "bindings/espidf/__init__.h"
1314
#include "common-hal/microcontroller/Processor.h"
1415
#include "shared-bindings/microcontroller/Processor.h"
1516
#include "shared-bindings/microcontroller/ResetReason.h"
1617

1718
#include "esp_sleep.h"
1819
#include "esp_system.h"
20+
#include "esp_pm.h"
1921

2022
#include "soc/efuse_reg.h"
2123

@@ -44,9 +46,67 @@ float common_hal_mcu_processor_get_voltage(void) {
4446
}
4547

4648
uint32_t common_hal_mcu_processor_get_frequency(void) {
49+
#if CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY
50+
esp_pm_config_t pm;
51+
CHECK_ESP_RESULT(esp_pm_get_configuration(&pm));
52+
return pm.min_freq_mhz * 1000000;
53+
#else
4754
return CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ * 1000000;
55+
#endif
56+
}
57+
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+
62+
#if defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32C6)
63+
uint32_t valid_cpu_frequencies[] = {20, 40, 80, 160};
64+
#elif defined(CONFIG_IDF_TARGET_ESP32C2)
65+
uint32_t valid_cpu_frequencies[] = {20, 40, 80, 120};
66+
#elif defined(CONFIG_IDF_TARGET_ESP32H2)
67+
uint32_t valid_cpu_frequencies[] = {32, 48, 64, 96};
68+
#else
69+
uint32_t valid_cpu_frequencies[] = {20, 40, 80, 160, 240};
70+
#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];
4889
}
4990

91+
void common_hal_mcu_processor_set_frequency(mcu_processor_obj_t *self, uint32_t frequency) {
92+
// Without this check, everything would compile without errors, but silently fail at runtime if
93+
// CONFIG_PM_ENABLE is ever accidentally disabled
94+
#if !defined(CONFIG_PM_ENABLE)
95+
#error "common_hal_mcu_processor_set_frequency needs CONFIG_PM_ENABLE to be defined."
96+
#endif
97+
98+
frequency /= 1000000;
99+
100+
frequency = get_valid_cpu_frequency(frequency);
101+
102+
esp_pm_config_t pm;
103+
pm.max_freq_mhz = frequency;
104+
pm.min_freq_mhz = frequency;
105+
pm.light_sleep_enable = false;
106+
CHECK_ESP_RESULT(esp_pm_configure(&pm));
107+
}
108+
#endif
109+
50110
static uint8_t swap_nibbles(uint8_t v) {
51111
return ((v << 4) | (v >> 4)) & 0xff;
52112
}

ports/espressif/esp-idf-config/sdkconfig-flash-4MB-no-uf2.defaults

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,9 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-4MB-no-uf2.csv
2222
CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-4MB-no-uf2.csv"
2323
# end of Partition Table
2424

25+
#
26+
# Power Management
27+
#
28+
CONFIG_PM_ENABLE=n # required for CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY, but doesn't fit with this partition table
29+
2530
# end of Espressif IoT Development Framework Configuration

ports/espressif/esp-idf-config/sdkconfig.defaults

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ CONFIG_GPTIMER_ISR_IRAM_SAFE=y
2828
# CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE is not set
2929
# end of PHY
3030

31+
#
32+
# Power Management
33+
#
34+
CONFIG_PM_ENABLE=y # required for CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY
35+
3136
#
3237
# ESP System Settings
3338
#

ports/espressif/mpconfigport.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ CIRCUITPY_ALARM = 0
198198
endif
199199
CIRCUITPY_DUALBANK = 1
200200
CIRCUITPY_BLEIO = 0
201+
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 0
202+
else
203+
CIRCUITPY_SETTABLE_PROCESSOR_FREQUENCY = 1
201204
endif
202205

203206
# No room for dualbank or mp3 on boards with 2MB flash

shared-bindings/microcontroller/Processor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
//| """The CPU operating frequency in Hertz.
4848
//|
4949
//| **Limitations:** On most boards, ``frequency`` is read-only. Setting
50-
//| the ``frequency`` is possible on RP2040 boards and some i.MX boards.
50+
//| the ``frequency`` is possible on RP2040 boards, some ESP32 boards and some i.MX boards.
5151
//|
5252
//| .. warning:: Overclocking likely voids your warranties and may reduce
5353
//| the lifetime of the chip.

0 commit comments

Comments
 (0)