Skip to content

Commit e1aed77

Browse files
committed
Merge branch 'feat/mcpwm_sleep_rentention_v5.4' into 'release/v5.4'
feat(mcpwm): support sleep retention (v5.4) See merge request espressif/esp-idf!34802
2 parents 551cb70 + 2e44cb9 commit e1aed77

File tree

31 files changed

+665
-93
lines changed

31 files changed

+665
-93
lines changed

components/esp_driver_mcpwm/include/driver/mcpwm_cap.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -22,6 +22,11 @@ typedef struct {
2222
int group_id; /*!< Specify from which group to allocate the capture timer */
2323
mcpwm_capture_clock_source_t clk_src; /*!< MCPWM capture timer clock source */
2424
uint32_t resolution_hz; /*!< Resolution of capture timer */
25+
struct {
26+
uint32_t allow_pd: 1; /*!< Set to allow power down. When this flag set, the driver will backup/restore the MCPWM registers before/after entering/exist sleep mode.
27+
By this approach, the system can power off MCPWM's power domain.
28+
This can save power, but at the expense of more RAM being consumed.*/
29+
} flags; /*!< Extra configuration flags for timer */
2530
} mcpwm_capture_timer_config_t;
2631

2732
/**

components/esp_driver_mcpwm/include/driver/mcpwm_timer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ typedef struct {
4040
struct {
4141
uint32_t update_period_on_empty: 1; /*!< Whether to update period when timer counts to zero */
4242
uint32_t update_period_on_sync: 1; /*!< Whether to update period on sync event */
43+
uint32_t allow_pd: 1; /*!< Set to allow power down. When this flag set, the driver will backup/restore the MCPWM registers before/after entering/exist sleep mode.
44+
By this approach, the system can power off MCPWM's power domain.
45+
This can save power, but at the expense of more RAM being consumed. */
4346
} flags; /*!< Extra configuration flags for timer */
4447
} mcpwm_timer_config_t;
4548

components/esp_driver_mcpwm/src/mcpwm_cap.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
9494
ESP_GOTO_ON_FALSE(config->group_id < SOC_MCPWM_GROUPS && config->group_id >= 0, ESP_ERR_INVALID_ARG,
9595
err, TAG, "invalid group ID:%d", config->group_id);
9696

97+
#if !SOC_MCPWM_SUPPORT_SLEEP_RETENTION
98+
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
99+
#endif // SOC_MCPWM_SUPPORT_SLEEP_RETENTION
100+
97101
cap_timer = heap_caps_calloc(1, sizeof(mcpwm_cap_timer_t), MCPWM_MEM_ALLOC_CAPS);
98102
ESP_GOTO_ON_FALSE(cap_timer, ESP_ERR_NO_MEM, err, TAG, "no mem for capture timer");
99103

@@ -139,6 +143,13 @@ esp_err_t mcpwm_new_capture_timer(const mcpwm_capture_timer_config_t *config, mc
139143
cap_timer->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
140144
cap_timer->fsm = MCPWM_CAP_TIMER_FSM_INIT;
141145
*ret_cap_timer = cap_timer;
146+
147+
#if MCPWM_USE_RETENTION_LINK
148+
if (config->flags.allow_pd != 0) {
149+
mcpwm_create_retention_module(group);
150+
}
151+
#endif // MCPWM_USE_RETENTION_LINK
152+
142153
ESP_LOGD(TAG, "new capture timer at %p, in group (%d), resolution %"PRIu32, cap_timer, group_id, cap_timer->resolution_hz);
143154
return ESP_OK;
144155

components/esp_driver_mcpwm/src/mcpwm_com.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "soc/soc_caps.h"
2222
#include "hal/mcpwm_ll.h"
2323
#include "mcpwm_private.h"
24+
#include "esp_private/rtc_clk.h"
2425

2526
#if SOC_PERIPH_CLK_CTRL_SHARED
2627
#define MCPWM_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
@@ -34,6 +35,10 @@
3435
#define MCPWM_RCC_ATOMIC()
3536
#endif
3637

38+
#if MCPWM_USE_RETENTION_LINK
39+
static esp_err_t mcpwm_create_sleep_retention_link_cb(void *arg);
40+
#endif
41+
3742
static const char *TAG = "mcpwm";
3843

3944
typedef struct {
@@ -59,6 +64,23 @@ mcpwm_group_t *mcpwm_acquire_group_handle(int group_id)
5964
group->group_id = group_id;
6065
group->intr_priority = -1;
6166
group->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
67+
#if MCPWM_USE_RETENTION_LINK
68+
sleep_retention_module_t module = mcpwm_reg_retention_info[group_id].retention_module;
69+
sleep_retention_module_init_param_t init_param = {
70+
.cbs = {
71+
.create = {
72+
.handle = mcpwm_create_sleep_retention_link_cb,
73+
.arg = group,
74+
},
75+
},
76+
.depends = SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM
77+
};
78+
// we only do retention init here. Allocate retention module in the unit initialization
79+
if (sleep_retention_module_init(module, &init_param) != ESP_OK) {
80+
// even though the sleep retention module init failed, MCPWM driver should still work, so just warning here
81+
ESP_LOGW(TAG, "init sleep retention failed %d, power domain may be turned off during sleep", group_id);
82+
}
83+
#endif // MCPWM_USE_RETENTION_LINK
6284
// enable APB to access MCPWM registers
6385
MCPWM_RCC_ATOMIC() {
6486
mcpwm_ll_enable_bus_clock(group_id, true);
@@ -116,6 +138,15 @@ void mcpwm_release_group_handle(mcpwm_group_t *group)
116138
if (group->pm_lock) {
117139
esp_pm_lock_delete(group->pm_lock);
118140
}
141+
#if MCPWM_USE_RETENTION_LINK
142+
const periph_retention_module_t module_id = mcpwm_reg_retention_info[group_id].retention_module;
143+
if (sleep_retention_get_created_modules() & BIT(module_id)) {
144+
sleep_retention_module_free(module_id);
145+
}
146+
if (sleep_retention_get_inited_modules() & BIT(module_id)) {
147+
sleep_retention_module_deinit(module_id);
148+
}
149+
#endif // MCPWM_USE_RETENTION_LINK
119150
free(group);
120151
}
121152
_lock_release(&s_platform.mutex);
@@ -257,3 +288,29 @@ esp_err_t mcpwm_set_prescale(mcpwm_group_t *group, uint32_t expect_module_resolu
257288

258289
return ESP_OK;
259290
}
291+
292+
#if MCPWM_USE_RETENTION_LINK
293+
static esp_err_t mcpwm_create_sleep_retention_link_cb(void *arg)
294+
{
295+
mcpwm_group_t *group = (mcpwm_group_t *)arg;
296+
int group_id = group->group_id;
297+
sleep_retention_module_t module_id = mcpwm_reg_retention_info[group_id].retention_module;
298+
esp_err_t err = sleep_retention_entries_create(mcpwm_reg_retention_info[group_id].regdma_entry_array,
299+
mcpwm_reg_retention_info[group_id].array_size,
300+
REGDMA_LINK_PRI_MCPWM, module_id);
301+
return err;
302+
}
303+
void mcpwm_create_retention_module(mcpwm_group_t *group)
304+
{
305+
int group_id = group->group_id;
306+
sleep_retention_module_t module_id = mcpwm_reg_retention_info[group_id].retention_module;
307+
_lock_acquire(&s_platform.mutex);
308+
if ((sleep_retention_get_inited_modules() & BIT(module_id)) && !(sleep_retention_get_created_modules() & BIT(module_id))) {
309+
if (sleep_retention_module_allocate(module_id) != ESP_OK) {
310+
// even though the sleep retention module create failed, MCPWM driver should still work, so just warning here
311+
ESP_LOGW(TAG, "create retention module failed, power domain can't turn off");
312+
}
313+
}
314+
_lock_release(&s_platform.mutex);
315+
}
316+
#endif // MCPWM_USE_RETENTION_LINK

components/esp_driver_mcpwm/src/mcpwm_private.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -17,6 +17,7 @@
1717
#include "hal/mcpwm_hal.h"
1818
#include "hal/mcpwm_types.h"
1919
#include "driver/mcpwm_types.h"
20+
#include "esp_private/sleep_retention.h"
2021

2122
#ifdef __cplusplus
2223
extern "C" {
@@ -34,6 +35,9 @@ extern "C" {
3435
#define MCPWM_INTR_ALLOC_FLAG (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
3536
#endif
3637

38+
// Use retention link only when the target supports sleep retention is enabled
39+
#define MCPWM_USE_RETENTION_LINK (SOC_MCPWM_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
40+
3741
#define MCPWM_ALLOW_INTR_PRIORITY_MASK ESP_INTR_FLAG_LOWMED
3842

3943
#define MCPWM_GROUP_CLOCK_DEFAULT_PRESCALE 2
@@ -259,6 +263,10 @@ int mcpwm_get_intr_priority_flag(mcpwm_group_t *group);
259263
esp_err_t mcpwm_select_periph_clock(mcpwm_group_t *group, soc_module_clk_t clk_src);
260264
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);
261265

266+
#if MCPWM_USE_RETENTION_LINK
267+
void mcpwm_create_retention_module(mcpwm_group_t *group);
268+
#endif
269+
262270
#ifdef __cplusplus
263271
}
264272
#endif

components/esp_driver_mcpwm/src/mcpwm_timer.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -102,6 +102,10 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
102102
}
103103
ESP_GOTO_ON_FALSE(peak_ticks > 0 && peak_ticks < MCPWM_LL_MAX_COUNT_VALUE, ESP_ERR_INVALID_ARG, err, TAG, "invalid period ticks");
104104

105+
#if !SOC_MCPWM_SUPPORT_SLEEP_RETENTION
106+
ESP_RETURN_ON_FALSE(config->flags.allow_pd == 0, ESP_ERR_NOT_SUPPORTED, TAG, "register back up is not supported");
107+
#endif // SOC_MCPWM_SUPPORT_SLEEP_RETENTION
108+
105109
timer = heap_caps_calloc(1, sizeof(mcpwm_timer_t), MCPWM_MEM_ALLOC_CAPS);
106110
ESP_GOTO_ON_FALSE(timer, ESP_ERR_NO_MEM, err, TAG, "no mem for timer");
107111

@@ -143,6 +147,13 @@ esp_err_t mcpwm_new_timer(const mcpwm_timer_config_t *config, mcpwm_timer_handle
143147
timer->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
144148
timer->fsm = MCPWM_TIMER_FSM_INIT;
145149
*ret_timer = timer;
150+
151+
#if MCPWM_USE_RETENTION_LINK
152+
if (config->flags.allow_pd != 0) {
153+
mcpwm_create_retention_module(group);
154+
}
155+
#endif // MCPWM_USE_RETENTION_LINK
156+
146157
ESP_LOGD(TAG, "new timer(%d,%d) at %p, resolution:%"PRIu32"Hz, peak:%"PRIu32", count_mod:%c",
147158
group_id, timer_id, timer, timer->resolution_hz, timer->peak_ticks, "SUDB"[timer->count_mode]);
148159
return ESP_OK;

components/esp_driver_mcpwm/test_apps/mcpwm/main/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ if(CONFIG_SOC_ETM_SUPPORTED AND CONFIG_SOC_MCPWM_SUPPORT_ETM)
1717
list(APPEND srcs "test_mcpwm_etm.c")
1818
endif()
1919

20+
# TODO: IDF-9928 support ESP32P4
21+
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_PM_ENABLE AND NOT CONFIG_IDF_TARGET_ESP32P4)
22+
list(APPEND srcs "test_mcpwm_sleep.c")
23+
endif()
24+
2025
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
2126
# the component can be registered as WHOLE_ARCHIVE
2227
idf_component_register(SRCS ${srcs}

0 commit comments

Comments
 (0)