mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(mcpwm): support sleep retention
This commit is contained in:
@@ -94,6 +94,10 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
|
||||
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
|
||||
err, TAG, "invalid group ID:%d", config->group_id);
|
||||
|
||||
#if !SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#endif // SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
cap_timer = heap_caps_calloc(1, sizeof(mcpwm_cap_timer_t), MCPWM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(cap_timer, ESP_ERR_NO_MEM, err, TAG, "no mem for capture timer");
|
||||
|
||||
@@ -139,6 +143,13 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
|
||||
cap_timer->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
cap_timer->fsm = MCPWM_CAP_TIMER_FSM_INIT;
|
||||
*ret_cap_timer = cap_timer;
|
||||
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
if (config->flags.allow_pd != 0) {
|
||||
mcpwm_create_retention_module(group);
|
||||
}
|
||||
#endif // MCPWM_USE_RETENTION_LINK
|
||||
|
||||
ESP_LOGD(TAG, "new capture timer at %p, in group (%d), resolution %"PRIu32, cap_timer, group_id, cap_timer->resolution_hz);
|
||||
return ESP_OK;
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/mcpwm_ll.h"
|
||||
#include "mcpwm_private.h"
|
||||
#include "esp_private/rtc_clk.h"
|
||||
|
||||
#if SOC_PERIPH_CLK_CTRL_SHARED
|
||||
#define MCPWM_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
@@ -34,6 +35,10 @@
|
||||
#define MCPWM_RCC_ATOMIC()
|
||||
#endif
|
||||
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
static esp_err_t mcpwm_create_sleep_retention_link_cb(void *arg);
|
||||
#endif
|
||||
|
||||
static const char *TAG = "mcpwm";
|
||||
|
||||
typedef struct {
|
||||
@@ -59,6 +64,23 @@ mcpwm_group_t *mcpwm_acquire_group_handle(int group_id)
|
||||
group->group_id = group_id;
|
||||
group->intr_priority = -1;
|
||||
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
sleep_retention_module_t module = mcpwm_reg_retention_info[group_id].retention_module;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = {
|
||||
.create = {
|
||||
.handle = mcpwm_create_sleep_retention_link_cb,
|
||||
.arg = group,
|
||||
},
|
||||
},
|
||||
.depends = SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM
|
||||
};
|
||||
// we only do retention init here. Allocate retention module in the unit initialization
|
||||
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
|
||||
// even though the sleep retention module init failed, MCPWM driver should still work, so just warning here
|
||||
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
|
||||
}
|
||||
#endif // MCPWM_USE_RETENTION_LINK
|
||||
// enable APB to access MCPWM registers
|
||||
MCPWM_RCC_ATOMIC() {
|
||||
mcpwm_ll_enable_bus_clock(group_id, true);
|
||||
@@ -116,6 +138,15 @@ void mcpwm_release_group_handle(mcpwm_group_t *group)
|
||||
if (group->pm_lock) {
|
||||
esp_pm_lock_delete(group->pm_lock);
|
||||
}
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
const periph_retention_module_t module_id = mcpwm_reg_retention_info[group_id].retention_module;
|
||||
if (sleep_retention_get_created_modules() & BIT(module_id)) {
|
||||
sleep_retention_module_free(module_id);
|
||||
}
|
||||
if (sleep_retention_get_inited_modules() & BIT(module_id)) {
|
||||
sleep_retention_module_deinit(module_id);
|
||||
}
|
||||
#endif // MCPWM_USE_RETENTION_LINK
|
||||
free(group);
|
||||
}
|
||||
_lock_release(&s_platform.mutex);
|
||||
@@ -257,3 +288,29 @@ esp_err_t mcpwm_set_prescale(mcpwm_group_t *group, uint32_t expect_module_resolu
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
static esp_err_t mcpwm_create_sleep_retention_link_cb(void *arg)
|
||||
{
|
||||
mcpwm_group_t *group = (mcpwm_group_t *)arg;
|
||||
int group_id = group->group_id;
|
||||
sleep_retention_module_t module_id = mcpwm_reg_retention_info[group_id].retention_module;
|
||||
esp_err_t err = sleep_retention_entries_create(mcpwm_reg_retention_info[group_id].regdma_entry_array,
|
||||
mcpwm_reg_retention_info[group_id].array_size,
|
||||
REGDMA_LINK_PRI_MCPWM, module_id);
|
||||
return err;
|
||||
}
|
||||
void mcpwm_create_retention_module(mcpwm_group_t *group)
|
||||
{
|
||||
int group_id = group->group_id;
|
||||
sleep_retention_module_t module_id = mcpwm_reg_retention_info[group_id].retention_module;
|
||||
_lock_acquire(&s_platform.mutex);
|
||||
if ((sleep_retention_get_inited_modules() & BIT(module_id)) && !(sleep_retention_get_created_modules() & BIT(module_id))) {
|
||||
if (sleep_retention_module_allocate(module_id) != ESP_OK) {
|
||||
// even though the sleep retention module create failed, MCPWM driver should still work, so just warning here
|
||||
ESP_LOGW(TAG, "create retention module failed, power domain can't turn off");
|
||||
}
|
||||
}
|
||||
_lock_release(&s_platform.mutex);
|
||||
}
|
||||
#endif // MCPWM_USE_RETENTION_LINK
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "hal/mcpwm_hal.h"
|
||||
#include "hal/mcpwm_types.h"
|
||||
#include "driver/mcpwm_types.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -34,6 +35,9 @@ extern "C" {
|
||||
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
|
||||
#endif
|
||||
|
||||
// Use retention link only when the target supports sleep retention is enabled
|
||||
#define MCPWM_USE_RETENTION_LINK (SOC_MCPWM_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
|
||||
#define MCPWM_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED
|
||||
|
||||
#define MCPWM_GROUP_CLOCK_DEFAULT_PRESCALE 2
|
||||
@@ -259,6 +263,10 @@ int mcpwm_get_intr_priority_flag(mcpwm_group_t *group);
|
||||
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src);
|
||||
esp_err_t mcpwm_set_prescale(mcpwm_group_t *group, uint32_t expect_module_resolution_hz, uint32_t module_prescale_max, uint32_t *ret_module_prescale);
|
||||
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
void mcpwm_create_retention_module(mcpwm_group_t *group);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -102,6 +102,10 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
|
||||
}
|
||||
ESP_GOTO_ON_FALSE(peak_ticks > 0 && peak_ticks < MCPWM_LL_MAX_COUNT_VALUE, ESP_ERR_INVALID_ARG, err, TAG, "invalid period ticks");
|
||||
|
||||
#if !SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
|
||||
#endif // SOC_MCPWM_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
timer = heap_caps_calloc(1, sizeof(mcpwm_timer_t), MCPWM_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(timer, ESP_ERR_NO_MEM, err, TAG, "no mem for timer");
|
||||
|
||||
@@ -143,6 +147,13 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
|
||||
timer->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
timer->fsm = MCPWM_TIMER_FSM_INIT;
|
||||
*ret_timer = timer;
|
||||
|
||||
#if MCPWM_USE_RETENTION_LINK
|
||||
if (config->flags.allow_pd != 0) {
|
||||
mcpwm_create_retention_module(group);
|
||||
}
|
||||
#endif // MCPWM_USE_RETENTION_LINK
|
||||
|
||||
ESP_LOGD(TAG, "new timer(%d,%d) at %p, resolution:%"PRIu32"Hz, peak:%"PRIu32", count_mod:%c",
|
||||
group_id, timer_id, timer, timer->resolution_hz, timer->peak_ticks, "SUDB"[timer->count_mode]);
|
||||
return ESP_OK;
|
||||
|
||||
Reference in New Issue
Block a user