Merge branch 'feat/pcnt_sleep_retention_v5.4' into 'release/v5.4'

feat(pcnt): add sleep retention init to avoid light sleep when pcnt is working (v5.4)

See merge request espressif/esp-idf!34728
This commit is contained in:
morris
2024-11-08 17:31:28 +08:00
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