Skip to content

Commit 164c549

Browse files
projectgusdpgeorge
authored andcommitted
esp32/machine_pwm: Restore PWM support for ESP-IDF v5.0.x and v5.1.x.
The cleanup in 548babf relies on some functions not available in older ESP-IDF. Temporarily restore them, until we drop support for ESP-IDF <5.2. PWM functionality should end up the same regardless of ESP-IDF version, and also no different from MicroPython V1.23. Signed-off-by: Angus Gratton <angus@redyak.com.au>
1 parent 6f32768 commit 164c549

File tree

1 file changed

+50
-2
lines changed

1 file changed

+50
-2
lines changed

ports/esp32/machine_pwm.c

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,12 @@
3434
#include "py/mphal.h"
3535
#include "driver/ledc.h"
3636
#include "esp_err.h"
37-
#include "esp_clk_tree.h"
3837
#include "soc/gpio_sig_map.h"
3938

39+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
40+
#include "esp_clk_tree.h"
41+
#endif
42+
4043
#define PWM_DBG(...)
4144
// #define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n");
4245

@@ -208,7 +211,41 @@ static void configure_channel(machine_pwm_obj_t *self) {
208211
}
209212
}
210213

214+
// Temporary workaround for ledc_find_suitable_duty_resolution function only being added in IDF V5.2
215+
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 2, 0)
216+
static uint32_t ledc_find_suitable_duty_resolution(uint32_t src_clk_freq, uint32_t timer_freq) {
217+
// This implementation is based on the one used in Micropython v1.23
218+
219+
// Find the highest bit resolution for the requested frequency
220+
unsigned int freq = src_clk_freq;
221+
222+
int divider = (freq + timer_freq / 2) / timer_freq; // rounded
223+
if (divider == 0) {
224+
divider = 1;
225+
}
226+
float f = (float)freq / divider; // actual frequency
227+
if (f <= 1.0) {
228+
f = 1.0;
229+
}
230+
freq = (unsigned int)roundf((float)freq / f);
231+
232+
unsigned int res = 0;
233+
for (; freq > 1; freq >>= 1) {
234+
++res;
235+
}
236+
if (res == 0) {
237+
res = 1;
238+
} else if (res > HIGHEST_PWM_RES) {
239+
// Limit resolution to HIGHEST_PWM_RES to match units of our duty
240+
res = HIGHEST_PWM_RES;
241+
}
242+
243+
return res;
244+
}
245+
#endif
246+
211247
static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_config_t *timer) {
248+
esp_err_t err;
212249
if (freq != timer->freq_hz) {
213250
// Configure the new frequency and resolution
214251
timer->freq_hz = freq;
@@ -228,10 +265,21 @@ static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
228265
}
229266
#endif
230267
uint32_t src_clk_freq = 0;
231-
esp_err_t err = esp_clk_tree_src_get_freq_hz(timer->clk_cfg, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_freq);
268+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
269+
err = esp_clk_tree_src_get_freq_hz(timer->clk_cfg, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_freq);
232270
if (err != ESP_OK) {
233271
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unable to query source clock frequency %d"), (int)timer->clk_cfg);
234272
}
273+
#else
274+
// Simplified fallback logic for IDF V5.0.x, for targets with APB only.
275+
src_clk_freq = APB_CLK_FREQ; // 80 MHz
276+
#if SOC_LEDC_SUPPORT_REF_TICK
277+
if (timer->clk_cfg == LEDC_USE_REF_TICK) {
278+
src_clk_freq = REF_CLK_FREQ; // 1 MHz
279+
}
280+
#endif // SOC_LEDC_SUPPORT_REF_TICK
281+
#endif // ESP_IDF_VERSION
282+
235283
timer->duty_resolution = ledc_find_suitable_duty_resolution(src_clk_freq, timer->freq_hz);
236284

237285
// Set frequency

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy