forked from espressif/esp-idf
feat(pcnt): add sleep retention init
Currently, due to the lack of sleep callback feature. We only init sleep module but don't allocate it. Thus the power domain will be kept during the light sleep. And temporarily disable pcnt sleep retention support on P4 due to the lack of retention module ID.
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "hal/gpio_ll.h" // for io_loop_back flag only
|
||||
@@ -65,6 +66,13 @@ typedef struct pcnt_group_t pcnt_group_t;
|
||||
typedef struct pcnt_unit_t pcnt_unit_t;
|
||||
typedef struct pcnt_chan_t pcnt_chan_t;
|
||||
|
||||
// Use retention link only when the target supports sleep retention
|
||||
#define PCNT_USE_RETENTION_LINK (SOC_PCNT_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
|
||||
|
||||
#if PCNT_USE_RETENTION_LINK
|
||||
static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg);
|
||||
#endif
|
||||
|
||||
struct pcnt_platform_t {
|
||||
_lock_t mutex; // platform level mutex lock
|
||||
pcnt_group_t *groups[SOC_PCNT_GROUPS]; // pcnt group pool
|
||||
@@ -864,6 +872,23 @@ static pcnt_group_t *pcnt_acquire_group_handle(int group_id)
|
||||
pcnt_ll_enable_bus_clock(group_id, true);
|
||||
pcnt_ll_reset_register(group_id);
|
||||
}
|
||||
#if PCNT_USE_RETENTION_LINK
|
||||
sleep_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module;
|
||||
sleep_retention_module_init_param_t init_param = {
|
||||
.cbs = {
|
||||
.create = {
|
||||
.handle = pcnt_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_id, &init_param) != ESP_OK) {
|
||||
// even though the sleep retention module init failed, PCNT 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 // PCNT_USE_RETENTION_LINK
|
||||
// initialize HAL context
|
||||
pcnt_hal_init(&group->hal, group_id);
|
||||
}
|
||||
@@ -901,6 +926,12 @@ static void pcnt_release_group_handle(pcnt_group_t *group)
|
||||
_lock_release(&s_platform.mutex);
|
||||
|
||||
if (do_deinitialize) {
|
||||
#if PCNT_USE_RETENTION_LINK
|
||||
const periph_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module;
|
||||
if (sleep_retention_get_inited_modules() & BIT(module_id)) {
|
||||
sleep_retention_module_deinit(module_id);
|
||||
}
|
||||
#endif // PCNT_USE_RETENTION_LINK
|
||||
free(group);
|
||||
ESP_LOGD(TAG, "del group (%d)", group_id);
|
||||
}
|
||||
@@ -998,3 +1029,17 @@ IRAM_ATTR static void pcnt_default_isr(void *args)
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
#if PCNT_USE_RETENTION_LINK
|
||||
static esp_err_t pcnt_create_sleep_retention_link_cb(void *arg)
|
||||
{
|
||||
pcnt_group_t *group = (pcnt_group_t *)arg;
|
||||
int group_id = group->group_id;
|
||||
sleep_retention_module_t module_id = pcnt_reg_retention_info[group_id].retention_module;
|
||||
esp_err_t err = sleep_retention_entries_create(pcnt_reg_retention_info[group_id].regdma_entry_array,
|
||||
pcnt_reg_retention_info[group_id].array_size,
|
||||
REGDMA_LINK_PRI_PCNT, module_id);
|
||||
ESP_RETURN_ON_ERROR(err, TAG, "create retention link failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif // PCNT_USE_RETENTION_LINK
|
||||
|
@@ -6,6 +6,11 @@ if(CONFIG_PCNT_ISR_IRAM_SAFE)
|
||||
list(APPEND srcs "test_pulse_cnt_iram.c")
|
||||
endif()
|
||||
|
||||
# TODO: IDF-9907 support ESP32P4
|
||||
if(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED AND CONFIG_PM_ENABLE AND NOT CONFIG_IDF_TARGET_ESP32P4)
|
||||
list(APPEND srcs "test_pulse_cnt_sleep.c")
|
||||
endif()
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
|
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "unity_test_utils.h"
|
||||
#include "driver/pulse_cnt.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "spi_flash_mmap.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/pcnt_struct.h"
|
||||
#include "hal/pcnt_ll.h"
|
||||
#include "test_pulse_cnt_board.h"
|
||||
#include "esp_private/sleep_cpu.h"
|
||||
#include "esp_private/esp_sleep_internal.h"
|
||||
#include "esp_private/esp_pmu.h"
|
||||
|
||||
/**
|
||||
* @brief Test the PCNT driver can still work after light sleep
|
||||
*/
|
||||
static void test_pcnt_sleep_retention(void)
|
||||
{
|
||||
test_gpio_init_for_simulation(TEST_PCNT_GPIO_A);
|
||||
test_gpio_init_for_simulation(TEST_PCNT_GPIO_B);
|
||||
|
||||
printf("install pcnt units\r\n");
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
.high_limit = 100,
|
||||
};
|
||||
pcnt_unit_handle_t units[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TEST_ESP_OK(pcnt_new_unit(&unit_config, &units[i]));
|
||||
}
|
||||
|
||||
printf("install pcnt channels\r\n");
|
||||
const int channel_gpios[] = {TEST_PCNT_GPIO_A, TEST_PCNT_GPIO_B};
|
||||
pcnt_chan_config_t chan_config = {
|
||||
.level_gpio_num = -1,
|
||||
};
|
||||
pcnt_channel_handle_t chans[2];
|
||||
for (int i = 0; i < 2; i++) {
|
||||
chan_config.edge_gpio_num = channel_gpios[i];
|
||||
TEST_ESP_OK(pcnt_new_channel(units[i], &chan_config, &chans[i]));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(chans[i], PCNT_CHANNEL_EDGE_ACTION_INCREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(chans[i], PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_KEEP));
|
||||
}
|
||||
|
||||
printf("enable and start unit\r\n");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_enable(units[i]));
|
||||
TEST_ESP_OK(pcnt_unit_start(units[i]));
|
||||
}
|
||||
|
||||
// trigger 10 rising edge on GPIO
|
||||
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
|
||||
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_B, 10);
|
||||
|
||||
int count_value = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
|
||||
TEST_ASSERT_EQUAL(10, count_value);
|
||||
}
|
||||
|
||||
// hold GPIO to avoid trigger PCNT counter during GPIO power down
|
||||
gpio_hold_en(TEST_PCNT_GPIO_A);
|
||||
gpio_hold_en(TEST_PCNT_GPIO_B);
|
||||
|
||||
printf("stop and disable unit before sleep\r\n");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_stop(units[i]));
|
||||
TEST_ESP_OK(pcnt_unit_disable(units[i]));
|
||||
}
|
||||
|
||||
// go to sleep
|
||||
esp_sleep_context_t sleep_ctx;
|
||||
esp_sleep_set_sleep_context(&sleep_ctx);
|
||||
printf("go to light sleep for 1 seconds\r\n");
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
TEST_ESP_OK(sleep_cpu_configure(true));
|
||||
#endif
|
||||
TEST_ESP_OK(esp_sleep_enable_timer_wakeup(1 * 1000 * 1000));
|
||||
TEST_ESP_OK(esp_light_sleep_start());
|
||||
|
||||
printf("Waked up! Let's see if PCNT driver can still work...\r\n");
|
||||
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||
TEST_ESP_OK(sleep_cpu_configure(false));
|
||||
#endif
|
||||
|
||||
printf("check if the sleep happened as expected\r\n");
|
||||
TEST_ASSERT_EQUAL(0, sleep_ctx.sleep_request_result);
|
||||
#if SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
// check if the power domain also is powered down
|
||||
TEST_ASSERT_EQUAL(0, (sleep_ctx.sleep_flags) & PMU_SLEEP_PD_TOP);
|
||||
#endif
|
||||
esp_sleep_set_sleep_context(NULL);
|
||||
|
||||
gpio_hold_dis(TEST_PCNT_GPIO_A);
|
||||
gpio_hold_dis(TEST_PCNT_GPIO_B);
|
||||
|
||||
printf("enable and start unit after sleep\r\n");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_enable(units[i]));
|
||||
TEST_ESP_OK(pcnt_unit_start(units[i]));
|
||||
}
|
||||
|
||||
// Verify the counter still holds the value
|
||||
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 10);
|
||||
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_B, 10);
|
||||
|
||||
int reg_value = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// check the counter value (include accum value and register value)
|
||||
TEST_ESP_OK(pcnt_unit_get_count(units[i], &count_value));
|
||||
TEST_ASSERT_EQUAL(20, count_value);
|
||||
// check the register value
|
||||
reg_value = pcnt_ll_get_count(&PCNT, i);
|
||||
TEST_ASSERT_EQUAL(20, reg_value);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
TEST_ESP_OK(pcnt_unit_stop(units[i]));
|
||||
TEST_ESP_OK(pcnt_unit_disable(units[i]));
|
||||
TEST_ESP_OK(pcnt_del_channel(chans[i]));
|
||||
TEST_ESP_OK(pcnt_del_unit(units[i]));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("pcnt light sleep", "[pcnt]")
|
||||
{
|
||||
test_pcnt_sleep_retention();
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
CONFIG_PM_ENABLE=y
|
||||
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
|
@@ -1,2 +1,5 @@
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP_TASK_WDT_EN=n
|
||||
|
||||
# primitives for checking sleep internal state
|
||||
CONFIG_ESP_SLEEP_DEBUG=y
|
||||
|
@@ -767,6 +767,10 @@ config SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RMT_GROUPS
|
||||
int
|
||||
default 1
|
||||
|
@@ -43,6 +43,7 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 19,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 20,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 21,
|
||||
SLEEP_RETENTION_MODULE_PCNT0 = 22,
|
||||
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@@ -89,6 +90,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
SLEEP_RETENTION_MODULE_BM_PCNT0 = BIT(SLEEP_RETENTION_MODULE_PCNT0),
|
||||
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
|
||||
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
|
||||
@@ -115,6 +117,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
| SLEEP_RETENTION_MODULE_BM_PCNT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_NULL \
|
||||
)
|
||||
#ifdef __cplusplus
|
||||
|
@@ -323,6 +323,7 @@
|
||||
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
|
||||
#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1
|
||||
#define SOC_PCNT_SUPPORT_STEP_NOTIFY 1
|
||||
#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */
|
||||
|
||||
/*--------------------------- RMT CAPS ---------------------------------------*/
|
||||
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/pcnt_reg.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
@@ -68,3 +69,31 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* PCNT Registers to be saved during sleep retention
|
||||
* - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG...
|
||||
* - Step Configuration registers, e.g.: PCNT_U0_CHANGE_CONF_REG, PCNT_U1_CHANGE_CONF_REG, PCNT_U2_CHANGE_CONF_REG, PCNT_U3_CHANGE_CONF_REG
|
||||
* - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG
|
||||
*/
|
||||
#define PCNT_RETENTION_REGS_CNT 18
|
||||
#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0)
|
||||
static const uint32_t pcnt_regs_map[4] = {0x1f040fff, 0x0, 0x0, 0x0};
|
||||
static const regdma_entries_config_t pcnt_regs_retention[] = {
|
||||
// backup stage: save configuration registers
|
||||
// restore stage: restore the configuration registers
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \
|
||||
PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \
|
||||
PCNT_RETENTION_REGS_CNT, 0, 0, \
|
||||
pcnt_regs_map[0], pcnt_regs_map[1], \
|
||||
pcnt_regs_map[2], pcnt_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||
};
|
||||
|
||||
const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = {
|
||||
[0] = {
|
||||
.regdma_entry_array = pcnt_regs_retention,
|
||||
.array_size = ARRAY_SIZE(pcnt_regs_retention),
|
||||
.retention_module = SLEEP_RETENTION_MODULE_PCNT0
|
||||
},
|
||||
};
|
||||
|
@@ -779,6 +779,10 @@ config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RMT_GROUPS
|
||||
int
|
||||
default 1
|
||||
|
@@ -45,6 +45,7 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 21,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 22,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 23,
|
||||
SLEEP_RETENTION_MODULE_PCNT0 = 24,
|
||||
|
||||
/* Modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
|
||||
@@ -87,6 +88,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
SLEEP_RETENTION_MODULE_BM_PCNT0 = BIT(SLEEP_RETENTION_MODULE_PCNT0),
|
||||
/* modem module, which includes WiFi, BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_MAC = BIT(SLEEP_RETENTION_MODULE_WIFI_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_WIFI_BB = BIT(SLEEP_RETENTION_MODULE_WIFI_BB),
|
||||
@@ -117,6 +119,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
| SLEEP_RETENTION_MODULE_BM_PCNT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_NULL \
|
||||
)
|
||||
|
||||
|
@@ -308,6 +308,7 @@
|
||||
#define SOC_PCNT_CHANNELS_PER_UNIT 2
|
||||
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
|
||||
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
|
||||
#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */
|
||||
|
||||
/*--------------------------- RMT CAPS ---------------------------------------*/
|
||||
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
|
||||
|
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/pcnt_reg.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
@@ -64,3 +65,30 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* PCNT Registers to be saved during sleep retention
|
||||
* - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG...
|
||||
* - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG
|
||||
*/
|
||||
#define PCNT_RETENTION_REGS_CNT 14
|
||||
#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0)
|
||||
static const uint32_t pcnt_regs_map[4] = {0x1040fff, 0x0, 0x0, 0x0};
|
||||
static const regdma_entries_config_t pcnt_regs_retention[] = {
|
||||
// backup stage: save configuration registers
|
||||
// restore stage: restore the configuration registers
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \
|
||||
PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \
|
||||
PCNT_RETENTION_REGS_CNT, 0, 0, \
|
||||
pcnt_regs_map[0], pcnt_regs_map[1], \
|
||||
pcnt_regs_map[2], pcnt_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||
};
|
||||
|
||||
const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = {
|
||||
[0] = {
|
||||
.regdma_entry_array = pcnt_regs_retention,
|
||||
.array_size = ARRAY_SIZE(pcnt_regs_retention),
|
||||
.retention_module = SLEEP_RETENTION_MODULE_PCNT0
|
||||
},
|
||||
};
|
||||
|
@@ -763,6 +763,10 @@ config SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_RMT_GROUPS
|
||||
int
|
||||
default 1
|
||||
|
@@ -45,6 +45,7 @@ typedef enum periph_retention_module {
|
||||
SLEEP_RETENTION_MODULE_PARLIO0 = 21,
|
||||
SLEEP_RETENTION_MODULE_GPSPI2 = 22,
|
||||
SLEEP_RETENTION_MODULE_LEDC = 23,
|
||||
SLEEP_RETENTION_MODULE_PCNT0 = 24,
|
||||
|
||||
/* Modem module, which includes BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BLE_MAC = 28,
|
||||
@@ -85,6 +86,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
SLEEP_RETENTION_MODULE_BM_PARLIO0 = BIT(SLEEP_RETENTION_MODULE_PARLIO0),
|
||||
SLEEP_RETENTION_MODULE_BM_GPSPI2 = BIT(SLEEP_RETENTION_MODULE_GPSPI2),
|
||||
SLEEP_RETENTION_MODULE_BM_LEDC = BIT(SLEEP_RETENTION_MODULE_LEDC),
|
||||
SLEEP_RETENTION_MODULE_BM_PCNT0 = BIT(SLEEP_RETENTION_MODULE_PCNT0),
|
||||
/* modem module, which includes BLE and 802.15.4 */
|
||||
SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC),
|
||||
SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB),
|
||||
@@ -113,6 +115,7 @@ typedef enum periph_retention_module_bitmap {
|
||||
| SLEEP_RETENTION_MODULE_BM_PARLIO0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_GPSPI2 \
|
||||
| SLEEP_RETENTION_MODULE_BM_LEDC \
|
||||
| SLEEP_RETENTION_MODULE_BM_PCNT0 \
|
||||
| SLEEP_RETENTION_MODULE_BM_NULL \
|
||||
)
|
||||
|
||||
|
@@ -302,6 +302,7 @@
|
||||
#define SOC_PCNT_CHANNELS_PER_UNIT 2
|
||||
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
|
||||
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
|
||||
#define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 /*!< The sleep retention feature can help back up PCNT registers before sleep */
|
||||
|
||||
/*--------------------------- RMT CAPS ---------------------------------------*/
|
||||
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
|
||||
|
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/pcnt_reg.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
@@ -64,3 +65,30 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* PCNT Registers to be saved during sleep retention
|
||||
* - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG...
|
||||
* - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG
|
||||
*/
|
||||
#define PCNT_RETENTION_REGS_CNT 14
|
||||
#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0)
|
||||
static const uint32_t pcnt_regs_map[4] = {0x1040fff, 0x0, 0x0, 0x0};
|
||||
static const regdma_entries_config_t pcnt_regs_retention[] = {
|
||||
// backup stage: save configuration registers
|
||||
// restore stage: restore the configuration registers
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \
|
||||
PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \
|
||||
PCNT_RETENTION_REGS_CNT, 0, 0, \
|
||||
pcnt_regs_map[0], pcnt_regs_map[1], \
|
||||
pcnt_regs_map[2], pcnt_regs_map[3]), \
|
||||
.owner = ENTRY(0) | ENTRY(2) }, \
|
||||
};
|
||||
|
||||
const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = {
|
||||
[0] = {
|
||||
.regdma_entry_array = pcnt_regs_retention,
|
||||
.array_size = ARRAY_SIZE(pcnt_regs_retention),
|
||||
.retention_module = SLEEP_RETENTION_MODULE_PCNT0
|
||||
},
|
||||
};
|
||||
|
@@ -408,6 +408,7 @@
|
||||
#define SOC_PCNT_THRES_POINT_PER_UNIT 2
|
||||
#define SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE 1
|
||||
#define SOC_PCNT_SUPPORT_CLEAR_SIGNAL 1 /*!< Support clear signal input */
|
||||
// #define SOC_PCNT_SUPPORT_SLEEP_RETENTION 1 // TODO: IDF-9907 Waiting for expansion of module ID /*!< The sleep retention feature can help back up PCNT registers before sleep */
|
||||
|
||||
/*--------------------------- RMT CAPS ---------------------------------------*/
|
||||
#define SOC_RMT_GROUPS 1U /*!< One RMT group */
|
||||
|
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "soc/pcnt_periph.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/pcnt_reg.h"
|
||||
|
||||
const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
.groups = {
|
||||
@@ -68,3 +69,33 @@ const pcnt_signal_conn_t pcnt_periph_signals = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
/**
|
||||
* PCNT Registers to be saved during sleep retention
|
||||
* - Configuration registers, e.g.: PCNT_CTRL_REG, PCNT_U0_CONF0_REG, PCNT_U0_CONF1_REG, PCNT_U0_CONF2_REG, PCNT_U1_CONF0_REG...
|
||||
* - Step Configuration registers, e.g.: PCNT_U0_CHANGE_CONF_REG, PCNT_U1_CHANGE_CONF_REG, PCNT_U2_CHANGE_CONF_REG, PCNT_U3_CHANGE_CONF_REG
|
||||
* - Interrupt enable registers, e.g.: PCNT_INT_ENA_REG
|
||||
*/
|
||||
#define PCNT_RETENTION_REGS_CNT 18
|
||||
#define PCNT_RETENTION_REGS_BASE (DR_REG_PCNT_BASE + 0x0)
|
||||
static const uint32_t pcnt_regs_map[4] = {0x1f040fff, 0x0, 0x0, 0x0};
|
||||
static const regdma_entries_config_t pcnt_regs_retention[] = {
|
||||
// backup stage: save configuration registers
|
||||
// restore stage: restore the configuration registers
|
||||
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCNT_LINK(0x00), \
|
||||
PCNT_RETENTION_REGS_BASE, PCNT_RETENTION_REGS_BASE, \
|
||||
PCNT_RETENTION_REGS_CNT, 0, 0, \
|
||||
pcnt_regs_map[0], pcnt_regs_map[1], \
|
||||
pcnt_regs_map[2], pcnt_regs_map[3]), \
|
||||
.owner = ENTRY(0)}, \
|
||||
};
|
||||
|
||||
const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS] = {
|
||||
[0] = {
|
||||
.regdma_entry_array = pcnt_regs_retention,
|
||||
.array_size = ARRAY_SIZE(pcnt_regs_retention),
|
||||
.retention_module = SLEEP_RETENTION_MODULE_PCNT0
|
||||
},
|
||||
};
|
||||
#endif // SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -9,6 +9,10 @@
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/regdma.h"
|
||||
#if SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
#include "soc/retention_periph_defs.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -31,6 +35,16 @@ typedef struct {
|
||||
|
||||
extern const pcnt_signal_conn_t pcnt_periph_signals;
|
||||
|
||||
#if SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
typedef struct {
|
||||
const periph_retention_module_t retention_module;
|
||||
const regdma_entries_config_t *regdma_entry_array;
|
||||
uint32_t array_size;
|
||||
} pcnt_reg_retention_info_t;
|
||||
|
||||
extern const pcnt_reg_retention_info_t pcnt_reg_retention_info[SOC_PCNT_GROUPS];
|
||||
#endif // SOC_PCNT_SUPPORT_SLEEP_RETENTION
|
||||
|
||||
#endif // SOC_PCNT_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -60,6 +60,7 @@ extern "C" {
|
||||
#define REGDMA_PARLIO_LINK(_pri) ((0x22 << 8) | _pri)
|
||||
#define REGDMA_GPSPI_LINK(_pri) ((0x23 << 8) | _pri)
|
||||
#define REGDMA_LEDC_LINK(_pri) ((0x24 << 8) | _pri)
|
||||
#define REGDMA_PCNT_LINK(_pri) ((0x25 << 8) | _pri)
|
||||
#define REGDMA_MODEM_FE_LINK(_pri) ((0xFF << 8) | _pri)
|
||||
|
||||
#define REGDMA_LINK_PRI_SYS_CLK REGDMA_LINK_PRI_0
|
||||
@@ -79,6 +80,7 @@ extern "C" {
|
||||
#define REGDMA_LINK_PRI_I2C REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_I2S REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_PARLIO REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_PCNT REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_UART REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_TEMPERATURE_SENSOR REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
#define REGDMA_LINK_PRI_TWAI REGDMA_LINK_PRI_GENERAL_PERIPH
|
||||
|
Reference in New Issue
Block a user