esp32/machine_pwm: Restore PWM support for ESP-IDF v5.0.x and v5.1.x.
The cleanup in 548babf8 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>
This commit is contained in:
committed by
Damien George
parent
275b3afae7
commit
594670e446
@@ -34,9 +34,12 @@
|
|||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "driver/ledc.h"
|
#include "driver/ledc.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_clk_tree.h"
|
|
||||||
#include "soc/gpio_sig_map.h"
|
#include "soc/gpio_sig_map.h"
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
|
||||||
|
#include "esp_clk_tree.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PWM_DBG(...)
|
#define PWM_DBG(...)
|
||||||
// #define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n");
|
// #define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__); mp_printf(&mp_plat_print, "\n");
|
||||||
|
|
||||||
@@ -208,7 +211,41 @@ static void configure_channel(machine_pwm_obj_t *self) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Temporary workaround for ledc_find_suitable_duty_resolution function only being added in IDF V5.2
|
||||||
|
#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 2, 0)
|
||||||
|
static uint32_t ledc_find_suitable_duty_resolution(uint32_t src_clk_freq, uint32_t timer_freq) {
|
||||||
|
// This implementation is based on the one used in Micropython v1.23
|
||||||
|
|
||||||
|
// Find the highest bit resolution for the requested frequency
|
||||||
|
unsigned int freq = src_clk_freq;
|
||||||
|
|
||||||
|
int divider = (freq + timer_freq / 2) / timer_freq; // rounded
|
||||||
|
if (divider == 0) {
|
||||||
|
divider = 1;
|
||||||
|
}
|
||||||
|
float f = (float)freq / divider; // actual frequency
|
||||||
|
if (f <= 1.0) {
|
||||||
|
f = 1.0;
|
||||||
|
}
|
||||||
|
freq = (unsigned int)roundf((float)freq / f);
|
||||||
|
|
||||||
|
unsigned int res = 0;
|
||||||
|
for (; freq > 1; freq >>= 1) {
|
||||||
|
++res;
|
||||||
|
}
|
||||||
|
if (res == 0) {
|
||||||
|
res = 1;
|
||||||
|
} else if (res > HIGHEST_PWM_RES) {
|
||||||
|
// Limit resolution to HIGHEST_PWM_RES to match units of our duty
|
||||||
|
res = HIGHEST_PWM_RES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_config_t *timer) {
|
static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_config_t *timer) {
|
||||||
|
esp_err_t err;
|
||||||
if (freq != timer->freq_hz) {
|
if (freq != timer->freq_hz) {
|
||||||
// Configure the new frequency and resolution
|
// Configure the new frequency and resolution
|
||||||
timer->freq_hz = freq;
|
timer->freq_hz = freq;
|
||||||
@@ -228,10 +265,21 @@ static void set_freq(machine_pwm_obj_t *self, unsigned int freq, ledc_timer_conf
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
uint32_t src_clk_freq = 0;
|
uint32_t src_clk_freq = 0;
|
||||||
esp_err_t err = esp_clk_tree_src_get_freq_hz(timer->clk_cfg, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_freq);
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0)
|
||||||
|
err = esp_clk_tree_src_get_freq_hz(timer->clk_cfg, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &src_clk_freq);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unable to query source clock frequency %d"), (int)timer->clk_cfg);
|
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("unable to query source clock frequency %d"), (int)timer->clk_cfg);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// Simplified fallback logic for IDF V5.0.x, for targets with APB only.
|
||||||
|
src_clk_freq = APB_CLK_FREQ; // 80 MHz
|
||||||
|
#if SOC_LEDC_SUPPORT_REF_TICK
|
||||||
|
if (timer->clk_cfg == LEDC_USE_REF_TICK) {
|
||||||
|
src_clk_freq = REF_CLK_FREQ; // 1 MHz
|
||||||
|
}
|
||||||
|
#endif // SOC_LEDC_SUPPORT_REF_TICK
|
||||||
|
#endif // ESP_IDF_VERSION
|
||||||
|
|
||||||
timer->duty_resolution = ledc_find_suitable_duty_resolution(src_clk_freq, timer->freq_hz);
|
timer->duty_resolution = ledc_find_suitable_duty_resolution(src_clk_freq, timer->freq_hz);
|
||||||
|
|
||||||
// Set frequency
|
// Set frequency
|
||||||
|
|||||||
Reference in New Issue
Block a user