mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(ledc): fix undesired module reset when acquiring new speed mode on ESP32
Introduced in 885e32d4f0
This commit is contained in:
@@ -399,44 +399,55 @@ esp_err_t ledc_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags,
|
|||||||
static bool ledc_speed_mode_ctx_create(ledc_mode_t speed_mode)
|
static bool ledc_speed_mode_ctx_create(ledc_mode_t speed_mode)
|
||||||
{
|
{
|
||||||
bool new_ctx = false;
|
bool new_ctx = false;
|
||||||
|
bool group_acquired = false;
|
||||||
|
|
||||||
// Prevent p_ledc_obj malloc concurrently
|
// Prevent p_ledc_obj malloc concurrently
|
||||||
_lock_acquire(&s_ledc_mutex[speed_mode]);
|
_lock_acquire(&s_ledc_mutex[speed_mode]);
|
||||||
if (!p_ledc_obj[speed_mode]) {
|
if (!p_ledc_obj[speed_mode]) {
|
||||||
|
for (int i = 0; i < LEDC_SPEED_MODE_MAX; i++) {
|
||||||
|
if (p_ledc_obj[i]) {
|
||||||
|
group_acquired = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
ledc_obj_t *ledc_new_mode_obj = (ledc_obj_t *) heap_caps_calloc(1, sizeof(ledc_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
ledc_obj_t *ledc_new_mode_obj = (ledc_obj_t *) heap_caps_calloc(1, sizeof(ledc_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||||
if (ledc_new_mode_obj) {
|
if (ledc_new_mode_obj) {
|
||||||
new_ctx = true;
|
new_ctx = true;
|
||||||
PERIPH_RCC_ATOMIC() {
|
// initialize some fields
|
||||||
ledc_ll_enable_bus_clock(0, true);
|
|
||||||
ledc_ll_reset_register(0);
|
|
||||||
}
|
|
||||||
// Enable core clock gating at early stage, some LEDC registers and gamma RAM rely on the LEDC core clock existence
|
|
||||||
PERIPH_RCC_ATOMIC() {
|
|
||||||
ledc_ll_enable_clock(0, true);
|
|
||||||
}
|
|
||||||
ledc_hal_init(&(ledc_new_mode_obj->ledc_hal), 0);
|
|
||||||
ledc_new_mode_obj->glb_clk = LEDC_SLOW_CLK_UNINIT;
|
ledc_new_mode_obj->glb_clk = LEDC_SLOW_CLK_UNINIT;
|
||||||
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
|
#if SOC_LEDC_HAS_TIMER_SPECIFIC_MUX
|
||||||
memset(ledc_new_mode_obj->timer_specific_clk, LEDC_TIMER_SPECIFIC_CLK_UNINIT, sizeof(ledc_clk_src_t) * LEDC_TIMER_MAX);
|
memset(ledc_new_mode_obj->timer_specific_clk, LEDC_TIMER_SPECIFIC_CLK_UNINIT, sizeof(ledc_clk_src_t) * LEDC_TIMER_MAX);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ledc_new_mode_obj->sleep_mode = LEDC_SLEEP_MODE_INVALID;
|
ledc_new_mode_obj->sleep_mode = LEDC_SLEEP_MODE_INVALID;
|
||||||
|
|
||||||
|
// if the entire LEDC group is not acquired, do module based initialization
|
||||||
|
if (!group_acquired) {
|
||||||
|
PERIPH_RCC_ATOMIC() {
|
||||||
|
ledc_ll_enable_bus_clock(0, true);
|
||||||
|
ledc_ll_reset_register(0);
|
||||||
|
}
|
||||||
|
// Enable core clock gating at early stage, some LEDC registers and gamma RAM rely on the LEDC core clock existence
|
||||||
|
PERIPH_RCC_ATOMIC() {
|
||||||
|
ledc_ll_enable_clock(0, true);
|
||||||
|
}
|
||||||
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // for targets that is !SOC_LEDC_SUPPORT_SLEEP_RETENTION, retention module should still be inited to avoid TOP PD
|
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // for targets that is !SOC_LEDC_SUPPORT_SLEEP_RETENTION, retention module should still be inited to avoid TOP PD
|
||||||
// Initialize sleep retention module for LEDC
|
// Initialize sleep retention module for LEDC
|
||||||
sleep_retention_module_t module = ledc_reg_retention_info[0].module_id;
|
sleep_retention_module_t module = ledc_reg_retention_info[0].module_id;
|
||||||
sleep_retention_module_init_param_t init_param = {
|
sleep_retention_module_init_param_t init_param = {
|
||||||
.cbs = {
|
.cbs = {
|
||||||
.create = {
|
.create = {
|
||||||
.handle = ledc_create_sleep_retention_link_cb,
|
.handle = ledc_create_sleep_retention_link_cb,
|
||||||
.arg = NULL,
|
.arg = NULL,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
|
||||||
.depends = RETENTION_MODULE_BITMAP_INIT(CLOCK_SYSTEM)
|
};
|
||||||
};
|
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
||||||
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
ESP_LOGW(LEDC_TAG, "init sleep retention failed for ledc, power domain may be turned off during sleep");
|
||||||
ESP_LOGW(LEDC_TAG, "init sleep retention failed for ledc, power domain may be turned off during sleep");
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
ledc_hal_init(&(ledc_new_mode_obj->ledc_hal), 0);
|
||||||
p_ledc_obj[speed_mode] = ledc_new_mode_obj;
|
p_ledc_obj[speed_mode] = ledc_new_mode_obj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user