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:
Chen Jichang
2024-11-07 11:48:16 +08:00
parent bab289ca78
commit 31befbfad3
21 changed files with 356 additions and 4 deletions

View File

@@ -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

View File

@@ -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}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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
},
};

View File

@@ -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

View File

@@ -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 \
)

View File

@@ -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 */

View File

@@ -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
},
};

View File

@@ -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

View File

@@ -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 \
)

View File

@@ -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 */

View File

@@ -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
},
};

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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