Compare commits

...

25 Commits

Author SHA1 Message Date
Rahul Tank
46acfdce96 Merge branch 'feat/send_data_len_afer_conn' into 'master'
Some checks failed
docker / docker (push) Has been cancelled
Vulnerability scan / Vulnerability scan (push) Has been cancelled
Sync remain PRs to Jira / Sync PRs to Jira (push) Has been cancelled
feat(nimble): Set data length after connection

See merge request espressif/esp-idf!32655
2024-09-21 21:24:54 +08:00
Jiang Jiang Jian
945af68d74 Merge branch 'feature/esp32c61_light_sleep_support_stage_3' into 'master'
feat(esp_hw_support): esp32c61 sleep support (Stage 3:  support system peripheral sleep retention)

Closes IDF-10384, IDF-10382, and IDF-11004

See merge request espressif/esp-idf!33298
2024-09-21 16:09:36 +08:00
Kapil Gupta
5d792910be Merge branch 'bugfix/wps_timer_causing_disconnect' into 'master'
fix(esp_wifi): Disable WPS timers once WPS succeed

Closes WIFIBUG-393

See merge request espressif/esp-idf!33240
2024-09-21 15:03:19 +08:00
David Čermák
82a29b7d21 Merge branch 'fix/lwip_drop_ipv6_if_no_ll' into 'master'
fix(lwip): Add default IPv6 input filter to drop traffic if ipv6 not assigned

Closes IDF-10472

See merge request espressif/esp-idf!32165
2024-09-20 23:33:49 +08:00
Kapil Gupta
0c9d7c9dd0 Merge branch 'bugfix/2g_5g_wnm_scan' into 'master'
fix(esp_wifi): Add changes to enable 5ghz scan

Closes WIFIBUG-773

See merge request espressif/esp-idf!33657
2024-09-20 22:20:26 +08:00
Kapil Gupta
3629909b11 fix(esp_wifi): Mask some error conditions in WPS
Mask some error conditions in WPS to increase the probability of
WPS success.
2024-09-20 22:08:01 +08:00
Kapil Gupta
3a35b26de1 fix(esp_wifi): Disable WPS timers once WPS succeed 2024-09-20 22:08:01 +08:00
Mahavir Jain
2a6be654cd Merge branch 'ci/enable_memprot_tests_for_esp32c61' into 'master'
Clear PMA entries before usage and enable tests for ESP32-C61

Closes IDF-10932

See merge request espressif/esp-idf!33438
2024-09-20 21:32:18 +08:00
Island
3000402fcf Merge branch 'bugfix/fix_ble_scan_assert_1728' into 'master'
fix(bt): Update bt lib for ESP32-C3 and ESP32-S3(e9ae856)

Closes IDFCI-2222 and BLERP-1037

See merge request espressif/esp-idf!33643
2024-09-20 20:12:00 +08:00
Kapil Gupta
b0712b6a2b Merge branch 'bugfix/deinitialize_wps_registrar' into 'master'
fix(esp_wifi): Deinit WPS registrar during hostapd deinit

Closes WIFIBUG-786 and WIFIBUG-695

See merge request espressif/esp-idf!33658
2024-09-20 17:40:57 +08:00
Liu Xiao Yu
e051b921b8 Merge branch 'feat/lp_spinlock' into 'master'
feat(ulp): implement inter-hp-lp-cpu spinlock/critical section

Closes IDF-10206

See merge request espressif/esp-idf!32775
2024-09-20 17:09:50 +08:00
David Cermak
98fdb1a97f fix(lwip): Add default IPv6 input filter to drop traffic if ipv6 not assigned
* Makes LWIP_HOOK_IP6_INPUT default to LWIP_HOOK_IP6_INPUT_DEFAULT
* Updated the stub hook implementation to actually filter out all IPv6
packets if the input netif has no link local address.
2024-09-20 10:36:43 +02:00
Kapil Gupta
1d7241acc1 fix(esp_wifi): Add changes to enable 5ghz scan 2024-09-20 12:58:14 +05:30
Lou Tianhao
bc0404ae03 fix(ci): some actions taken to pass CI 2024-09-20 14:10:45 +08:00
Lou Tianhao
46350e362e fix(esp_hw_support): add clock retention contents for esp32c61 & esp32c5 2024-09-20 14:09:29 +08:00
Lou Tianhao
6be09eb5b8 change(pm): replace SOC_CLK_RC32K_NOT_TO_USE with CONFIG_ESP_CLK_RC32K_NOT_TO_USE 2024-09-20 14:07:18 +08:00
Li Shuai
3b6f8b1f3d fix(esp32c61): enable soc caps macro to fix regdma wait compare bug 2024-09-20 14:07:18 +08:00
Lou Tianhao
9529c4ece4 fix(esp_hw_support): fix mmu memory powered down issue by software backup and restore mmu table content
squash! fix(esp_hw_support): fix mmu memory powered down issue by software backup and restore mmu table content
2024-09-20 14:07:18 +08:00
Lou Tianhao
a30ed69f69 feat(pm): support top retention for esp32c61 2024-09-20 14:07:18 +08:00
Xiaoyu Liu
446528d40f feat(ulp): implement ulp lp core spinlock 2024-09-20 10:22:45 +08:00
Kapil Gupta
28f12bfb47 fix(esp_wifi): Deinit WPS registrar during hostapd deinit 2024-09-19 23:10:08 +05:30
Rahul Tank
675fac1a6c feat(nimble): Set data length after connection 2024-09-19 20:20:47 +05:30
zhanghaipeng
32c7694f56 fix(bt): Update bt lib for ESP32-C3 and ESP32-S3(e9ae856)
- Fixed BLE scan assert in lld_scan.c 1728
2024-09-19 15:22:04 +08:00
harshal.patil
7667d9ebbe
fix(cpu_region_protect): Reset PMA entries before using them
- ROM uses some PMA entries so we clear such PMA entries before using them in ESP-IDF
2024-09-18 10:25:18 +05:30
harshal.patil
fcd751e79c
ci(memprot): enable memory protection tests for ESP32-C61 2024-09-18 10:25:18 +05:30
59 changed files with 1550 additions and 146 deletions

View File

@ -24,7 +24,7 @@ def test_app_update(dut: Dut) -> None:
@pytest.mark.supported_targets
# TODO: [ESP32C61] IDF-9245, IDF-9247, IDF-10983
# TODO: [ESP32C61] IDF-9245, IDF-10983
@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='C61 has not supported deep sleep')
@pytest.mark.generic
@pytest.mark.parametrize(

@ -1 +1 @@
Subproject commit b8ef2c474d392a88ea7e6626f89acf1fa5f30e4a
Subproject commit 5c913171361dac0821e15e83cc0cf604149e1b84

@ -1 +1 @@
Subproject commit 7e4f538a23591dfd361b90415eb517c6fc901a40
Subproject commit 62b04f185717f31c57b802d5059e13b0d4d12b0c

View File

@ -273,4 +273,13 @@ menu "Hardware Settings"
config ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM
bool
default n
config ESP_CLK_RC32K_NOT_TO_USE
bool
default y if IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C61
default n
help
Due to the poor low-temperature characteristics of
RC32K (it cannot operate below -40 degrees Celsius),
please avoid using it whenever possible
endmenu

View File

@ -19,7 +19,7 @@ esp_err_t sleep_clock_system_retention_init(void *arg)
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(0), PCR_AHB_FREQ_CONF_REG, 0, PCR_AHB_DIV_NUM, 1, 0), .owner = ENTRY(0) | ENTRY(1) }, /* Set AHB bus frequency to XTAL frequency */
[1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_PCR_LINK(1), PCR_BUS_CLK_UPDATE_REG, 1, PCR_BUS_CLOCK_UPDATE, 1, 0), .owner = ENTRY(0) | ENTRY(1) },
#if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 74, 0, 0, 0xffffffff, 0xffffffff, 0x7f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
[2] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(2), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 75, 0, 0, 0xffffffff, 0xffffffff, 0x200007f7, 0x0), .owner = ENTRY(0) | ENTRY(1) },
#endif
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);

View File

@ -0,0 +1,91 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_private/sleep_clock.h"
#include "soc/pcr_reg.h"
#include "modem/modem_syscon_reg.h"
static const char *TAG = "sleep_clock";
esp_err_t sleep_clock_system_retention_init(void *arg)
{
const static sleep_retention_entries_config_t pcr_regs_retention[] = {
[0] = { .config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_PCR_LINK(0), DR_REG_PCR_BASE, DR_REG_PCR_BASE, 63, 0, 0, 0xfd73ffff, 0xfdffffff, 0xe001, 0x0), .owner = ENTRY(0) | ENTRY(1) },
};
esp_err_t err = sleep_retention_entries_create(pcr_regs_retention, ARRAY_SIZE(pcr_regs_retention), REGDMA_LINK_PRI_SYS_CLK, SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for system (PCR) retention");
ESP_LOGI(TAG, "System Power, Clock and Reset sleep retention initialization");
return ESP_OK;
}
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
esp_err_t sleep_clock_modem_retention_init(void *arg)
{
#define N_REGS_SYSCON() (((MODEM_SYSCON_MEM_CONF_REG - MODEM_SYSCON_TEST_CONF_REG) / 4) + 1)
const static sleep_retention_entries_config_t modem_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_MODEMSYSCON_LINK(0), MODEM_SYSCON_TEST_CONF_REG, MODEM_SYSCON_TEST_CONF_REG, N_REGS_SYSCON(), 0, 0), .owner = ENTRY(0) | ENTRY(1) }, /* MODEM SYSCON */
};
esp_err_t err = sleep_retention_entries_create(modem_regs_retention, ARRAY_SIZE(modem_regs_retention), REGDMA_LINK_PRI_MODEM_CLK, SLEEP_RETENTION_MODULE_CLOCK_MODEM);
ESP_RETURN_ON_ERROR(err, TAG, "failed to allocate memory for modem (SYSCON) retention, 1 level priority");
ESP_LOGI(TAG, "Modem Power, Clock and Reset sleep retention initialization");
return ESP_OK;
}
#endif
bool clock_domain_pd_allowed(void)
{
const uint32_t inited_modules = sleep_retention_get_inited_modules();
const uint32_t created_modules = sleep_retention_get_created_modules();
const uint32_t sys_clk_dep_modules = (const uint32_t) (BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH));
/* The clock and reset of MODEM (WiFi, BLE and 15.4) modules are managed
* through MODEM_SYSCON, when one or more MODEMs are initialized, it is
* necessary to check the state of CLOCK_MODEM to determine MODEM domain on
* or off. The clock and reset of digital peripherals are managed through
* PCR, with TOP domain similar to MODEM domain. */
uint32_t modem_clk_dep_modules = 0;
#if SOC_WIFI_SUPPORTED
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_WIFI_MAC) | BIT(SLEEP_RETENTION_MODULE_WIFI_BB);
#endif
#if SOC_BT_SUPPORTED
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_BLE_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
#endif
#if SOC_IEEE802154_SUPPORTED
modem_clk_dep_modules |= BIT(SLEEP_RETENTION_MODULE_802154_MAC) | BIT(SLEEP_RETENTION_MODULE_BT_BB);
#endif
uint32_t mask = 0;
if (inited_modules & sys_clk_dep_modules) {
mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM);
}
if (inited_modules & modem_clk_dep_modules) {
#if SOC_WIFI_SUPPORTED || SOC_BT_SUPPORTED || SOC_IEEE802154_SUPPORTED
mask |= BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM);
#endif
}
return ((inited_modules & mask) == (created_modules & mask));
}
ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106)
{
sleep_retention_module_init_param_t init_param = {
.cbs = { .create = { .handle = sleep_clock_system_retention_init, .arg = NULL } },
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE
};
sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM, &init_param);
#if CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE
init_param = (sleep_retention_module_init_param_t) {
.cbs = { .create = { .handle = sleep_clock_modem_retention_init, .arg = NULL } },
.attribute = SLEEP_RETENTION_MODULE_ATTR_PASSIVE
};
sleep_retention_module_init(SLEEP_RETENTION_MODULE_CLOCK_MODEM, &init_param);
#endif
return ESP_OK;
}

View File

@ -0,0 +1,162 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stddef.h>
#include <string.h>
#include <inttypes.h>
#include "esp_attr.h"
#include "esp_check.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "esp_heap_caps.h"
#include "soc/soc_caps.h"
#include "sdkconfig.h"
#include "soc/spi_mem_reg.h"
#include "esp_private/startup_internal.h"
static const char *TAG = "sleep_mmu";
typedef struct {
uint32_t start;
uint32_t end;
} mmu_domain_dev_regs_region_t;
typedef struct {
mmu_domain_dev_regs_region_t *region;
int region_num;
uint32_t *regs_frame;
} mmu_domain_dev_sleep_frame_t;
/**
* Internal structure which holds all requested light sleep mmu retention parameters
*/
typedef struct {
struct {
mmu_domain_dev_sleep_frame_t *mmu_table_frame;
} retent;
} sleep_mmu_retention_t;
static DRAM_ATTR __attribute__((unused)) sleep_mmu_retention_t s_mmu_retention;
static void * mmu_domain_dev_sleep_frame_alloc_and_init(const mmu_domain_dev_regs_region_t *regions, const int region_num)
{
const int region_sz = sizeof(mmu_domain_dev_regs_region_t) * region_num;
int regs_frame_sz = 0;
for (int num = 0; num < region_num; num++) {
regs_frame_sz += regions[num].end - regions[num].start;
}
void *frame = heap_caps_malloc(sizeof(mmu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
if (frame) {
mmu_domain_dev_regs_region_t *region = (mmu_domain_dev_regs_region_t *)(frame + sizeof(mmu_domain_dev_sleep_frame_t));
memcpy(region, regions, region_num * sizeof(mmu_domain_dev_regs_region_t));
void *regs_frame = frame + sizeof(mmu_domain_dev_sleep_frame_t) + region_sz;
memset(regs_frame, 0, regs_frame_sz);
*(mmu_domain_dev_sleep_frame_t *)frame = (mmu_domain_dev_sleep_frame_t) {
.region = region,
.region_num = region_num,
.regs_frame = (uint32_t *)regs_frame
};
}
return frame;
}
static inline void * mmu_domain_mmu_table_sleep_frame_alloc_and_init(void)
{
#define MMU_TABLE_SIZE (512 * 4)
const static mmu_domain_dev_regs_region_t regions[] = {
{ .start = SPI_MEM_MMU_ITEM_CONTENT_REG(0), .end = SPI_MEM_MMU_ITEM_CONTENT_REG(0) + MMU_TABLE_SIZE}
};
return mmu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
}
static IRAM_ATTR void mmu_domain_dev_regs_save(mmu_domain_dev_sleep_frame_t *frame)
{
assert(frame);
mmu_domain_dev_regs_region_t *region = frame->region;
uint32_t *regs_frame = frame->regs_frame;
int offset = 0;
for (int i = 0; i < frame->region_num; i++) {
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset);
regs_frame[offset++] = REG_READ(SPI_MEM_MMU_ITEM_CONTENT_REG(0));
}
}
}
static IRAM_ATTR void mmu_domain_dev_regs_restore(mmu_domain_dev_sleep_frame_t *frame)
{
assert(frame);
mmu_domain_dev_regs_region_t *region = frame->region;
uint32_t *regs_frame = frame->regs_frame;
int offset = 0;
for (int i = 0; i < frame->region_num; i++) {
for (uint32_t addr = region[i].start; addr < region[i].end; addr+=4) {
REG_WRITE(SPI_MEM_MMU_ITEM_INDEX_REG(0), offset);
REG_WRITE(SPI_MEM_MMU_ITEM_CONTENT_REG(0),regs_frame[offset++]);
}
}
}
IRAM_ATTR void esp_sleep_mmu_retention(bool backup_or_restore)
{
if (backup_or_restore) {
mmu_domain_dev_regs_save(s_mmu_retention.retent.mmu_table_frame);
} else {
mmu_domain_dev_regs_restore(s_mmu_retention.retent.mmu_table_frame);
}
}
static esp_err_t esp_sleep_mmu_retention_deinit_impl(void)
{
if (s_mmu_retention.retent.mmu_table_frame) {
heap_caps_free((void *)s_mmu_retention.retent.mmu_table_frame);
s_mmu_retention.retent.mmu_table_frame = NULL;
}
return ESP_OK;
}
static esp_err_t esp_sleep_mmu_retention_init_impl(void)
{
if (s_mmu_retention.retent.mmu_table_frame == NULL) {
void *frame = mmu_domain_mmu_table_sleep_frame_alloc_and_init();
if (frame == NULL) {
goto err;
}
s_mmu_retention.retent.mmu_table_frame = (mmu_domain_dev_sleep_frame_t *)frame;
}
return ESP_OK;
err:
esp_sleep_mmu_retention_deinit();
return ESP_ERR_NO_MEM;
}
esp_err_t esp_sleep_mmu_retention_init(void)
{
return esp_sleep_mmu_retention_init_impl();
}
esp_err_t esp_sleep_mmu_retention_deinit(void)
{
return esp_sleep_mmu_retention_deinit_impl();
}
bool mmu_domain_pd_allowed(void)
{
return (s_mmu_retention.retent.mmu_table_frame != NULL);
}
ESP_SYSTEM_INIT_FN(sleep_mmu_startup_init, SECONDARY, BIT(0), 108)
{
esp_err_t ret;
ret = esp_sleep_mmu_retention_init();
if (ret != ESP_OK) {
ESP_EARLY_LOGW(TAG, "Failed to enable TOP power down during light sleep.");
}
return ESP_OK;
}

View File

@ -423,7 +423,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl
esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) (
(last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST :
(last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL :
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
(last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K :
#endif
(last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K :
@ -431,7 +431,7 @@ void modem_clock_select_lp_clock_source(periph_module_t module, modem_clock_lpcl
esp_sleep_pd_domain_t pu_domain = (esp_sleep_pd_domain_t) (
(src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST :
(src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL :
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
(src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K :
#endif
(src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K :
@ -486,7 +486,7 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module)
esp_sleep_pd_domain_t pd_domain = (esp_sleep_pd_domain_t) (
(last_src == MODEM_CLOCK_LPCLK_SRC_RC_FAST) ? ESP_PD_DOMAIN_RC_FAST :
(last_src == MODEM_CLOCK_LPCLK_SRC_MAIN_XTAL) ? ESP_PD_DOMAIN_XTAL :
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
(last_src == MODEM_CLOCK_LPCLK_SRC_RC32K) ? ESP_PD_DOMAIN_RC32K :
#endif
(last_src == MODEM_CLOCK_LPCLK_SRC_XTAL32K) ? ESP_PD_DOMAIN_XTAL32K :

View File

@ -34,44 +34,44 @@ static void esp_cpu_configure_invalid_regions(void)
__attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X;
__attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X;
// ROM uses some PMA entries, so we need to clear them before using them in ESP-IDF
// 0. Gap at bottom of address space
PMA_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
// 1. Gap between debug region & IROM
PMA_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
// 2. ROM has configured the ROM region to be cacheable, so we just need to lock the configuration
PMA_ENTRY_SET_TOR(3, SOC_IROM_MASK_LOW, PMA_NONE);
PMA_ENTRY_SET_TOR(4, SOC_DROM_MASK_HIGH, PMA_TOR | PMA_RX);
PMA_RESET_AND_ENTRY_SET_TOR(3, SOC_IROM_MASK_LOW, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(4, SOC_DROM_MASK_HIGH, PMA_TOR | PMA_RX);
// 3. Gap between ROM & RAM
PMA_ENTRY_SET_TOR(5, SOC_DROM_MASK_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(6, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(5, SOC_DROM_MASK_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(6, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
// 4. Gap between DRAM and I_Cache
PMA_ENTRY_SET_TOR(7, SOC_IRAM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(8, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(7, SOC_IRAM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(8, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
// 5. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration
// This function sets invalid regions but this is a valid memory region configuration that could have
// been configured using PMP as well, but due to insufficient PMP entries we are configuring this using PMA.
// This entry is also required to be set using PMA because the region needs to be configured as cacheable.
PMA_ENTRY_SET_NAPOT(9, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX);
PMA_RESET_AND_ENTRY_SET_NAPOT(9, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX);
// 6. Gap between D_Cache & LP_RAM
PMA_ENTRY_SET_TOR(10, SOC_DROM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(11, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(10, SOC_DROM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(11, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE);
// 7. Gap between LP memory & peripheral addresses
PMA_ENTRY_SET_TOR(12, SOC_RTC_IRAM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(13, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(12, SOC_RTC_IRAM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(13, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE);
// 8. End of address space
PMA_ENTRY_SET_TOR(14, SOC_PERIPHERAL_HIGH, PMA_NONE);
PMA_ENTRY_CFG_RESET(15);
PMA_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(14, SOC_PERIPHERAL_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE);
}
void esp_cpu_configure_region_protection(void)

View File

@ -17,7 +17,7 @@ if(NOT BOOTLOADER_BUILD)
endif()
# TODO: [ESP32C61] IDF-9250
# TODO: [ESP32C61] IDF-9304
if(CONFIG_IDF_TARGET_ESP32C61)
list(REMOVE_ITEM srcs
"sar_periph_ctrl.c"

View File

@ -35,34 +35,41 @@ static void esp_cpu_configure_invalid_regions(void)
__attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X;
__attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X;
// ROM uses some PMA entries, so we need to clear them before using them in ESP-IDF
// 0. Gap at bottom of address space
PMA_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
// 1. Gap between debug region & IROM
PMA_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
// 3. Gap between ROM & RAM
PMA_ENTRY_SET_TOR(3, SOC_DROM_MASK_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(4, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(3, SOC_DROM_MASK_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(4, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
// 4. Gap between DRAM and I_Cache
PMA_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
// 5. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration
// This function sets invalid regions but this is a valid memory region configuration that could have
// been configured using PMP as well, but due to insufficient PMP entries we are configuring this using PMA.
// This entry is also required to be set using PMA because the region needs to be configured as cacheable.
PMA_ENTRY_SET_NAPOT(7, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX);
PMA_RESET_AND_ENTRY_SET_NAPOT(7, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX);
// 6. Gap between D_Cache & peripheral addresses
PMA_ENTRY_SET_TOR(8, SOC_DROM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(9, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(8, SOC_DROM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(9, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE);
// 7. End of address space
PMA_ENTRY_SET_TOR(10, SOC_PERIPHERAL_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(11, UINT32_MAX, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(10, SOC_PERIPHERAL_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(11, UINT32_MAX, PMA_TOR | PMA_NONE);
PMA_ENTRY_CFG_RESET(12);
PMA_ENTRY_CFG_RESET(13);
PMA_ENTRY_CFG_RESET(14);
PMA_ENTRY_CFG_RESET(15);
}
void esp_cpu_configure_region_protection(void)

View File

@ -10,8 +10,6 @@
extern "C" {
#endif
// TODO: IDF-9247
#define PMU_EXT0_WAKEUP_EN BIT(0)
#define PMU_EXT1_WAKEUP_EN BIT(1)
#define PMU_GPIO_WAKEUP_EN BIT(2)

View File

@ -476,12 +476,12 @@ typedef struct pmu_sleep_machine_constant {
.reset_wait_time_us = 1, \
.power_supply_wait_time_us = 20, \
.power_up_wait_time_us = 2, \
.regdma_s2m_work_time_us = 172, \
.regdma_s2a_work_time_us = 480, \
.regdma_m2a_work_time_us = 278, \
.regdma_a2s_work_time_us = 382, \
.regdma_rf_on_work_time_us = 70, \
.regdma_rf_off_work_time_us = 23, \
.regdma_s2m_work_time_us = 270, \
.regdma_s2a_work_time_us = 666, \
.regdma_m2a_work_time_us = 296, \
.regdma_a2s_work_time_us = 586, \
.regdma_rf_on_work_time_us = 138, \
.regdma_rf_off_work_time_us = 28, \
.xtal_wait_stable_time_us = 250, \
.pll_wait_stable_time_us = 1 \
} \

View File

@ -38,42 +38,44 @@ static void esp_cpu_configure_invalid_regions(void)
__attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X;
__attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X;
// ROM uses some PMA entries, so we need to clear them before using them in ESP-IDF
// 0. Gap at bottom of address space
PMA_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
// 1. Gap between CPU subsystem region & HP TCM
PMA_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(2, SOC_TCM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(2, SOC_TCM_LOW, PMA_TOR | PMA_NONE);
// 2. Gap between HP TCM and CPU Peripherals
PMA_ENTRY_SET_TOR(3, SOC_TCM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(4, CPU_PERIPH_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(3, SOC_TCM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(4, CPU_PERIPH_LOW, PMA_TOR | PMA_NONE);
// 3. Gap between CPU Peripherals and I_Cache
PMA_ENTRY_SET_TOR(5, CPU_PERIPH_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(5, CPU_PERIPH_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
// 4. Gap between I_Cache and external memory range
PMA_ENTRY_SET_NAPOT(7, SOC_DROM_HIGH, SOC_EXTRAM_LOW - SOC_DROM_HIGH, PMA_NAPOT | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_NAPOT(7, SOC_DROM_HIGH, SOC_EXTRAM_LOW - SOC_DROM_HIGH, PMA_NAPOT | PMA_NONE);
// 5. Gap between external memory and ROM
PMA_ENTRY_SET_TOR(8, SOC_EXTRAM_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(9, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(8, SOC_EXTRAM_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(9, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
// 6. Gap between ROM and internal memory
PMA_ENTRY_SET_TOR(10, SOC_IROM_MASK_HIGH, PMA_NONE);
PMA_ENTRY_SET_TOR(11, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(10, SOC_IROM_MASK_HIGH, PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(11, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
// 7. Gap between internal memory and HP peripherals
PMA_ENTRY_SET_NAPOT(12, SOC_DRAM_HIGH, SOC_PERIPHERAL_LOW - SOC_DRAM_HIGH, PMA_NAPOT | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_NAPOT(12, SOC_DRAM_HIGH, SOC_PERIPHERAL_LOW - SOC_DRAM_HIGH, PMA_NAPOT | PMA_NONE);
// 8. Special case - This whitelists the External flash/RAM, HP ROM and HP L2MEM regions and make them cacheable.
// At the startup, this is done using PMA entry 15 by the ROM code.
PMA_ENTRY_SET_NAPOT(13, SOC_IROM_LOW, SOC_PERIPHERAL_LOW - SOC_IROM_LOW, PMA_NAPOT | PMA_RWX);
PMA_RESET_AND_ENTRY_SET_NAPOT(13, SOC_IROM_LOW, SOC_PERIPHERAL_LOW - SOC_IROM_LOW, PMA_NAPOT | PMA_RWX);
// 9. Gap between Uncacheable L2 Mem and end of address space
PMA_ENTRY_SET_TOR(14, CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_DRAM_HIGH), PMA_NONE);
PMA_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(14, CACHE_LL_L2MEM_NON_CACHE_ADDR(SOC_DRAM_HIGH), PMA_NONE);
PMA_RESET_AND_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE);
}
void esp_cpu_configure_region_protection(void)

View File

@ -157,8 +157,8 @@
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
#elif CONFIG_IDF_TARGET_ESP32C61
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (318)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (56)
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (1148) //TODO: PM-231
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (107)
#elif CONFIG_IDF_TARGET_ESP32H2
#define DEFAULT_SLEEP_OUT_OVERHEAD_US (118)
#define DEFAULT_HARDWARE_OUT_OVERHEAD_US (9)
@ -189,8 +189,12 @@
#endif
#if SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
#if CONFIG_IDF_TARGET_ESP32C61
#define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1232)
#elif CONFIG_IDF_TARGET_ESP32C5
#define SLEEP_MMU_TABLE_RETENTION_OVERHEAD_US (1220)
#endif
#endif
// Minimal amount of time we can sleep for
#define LIGHT_SLEEP_MIN_TIME_US 200
@ -705,7 +709,7 @@ FORCE_INLINE_ATTR void misc_modules_wake_prepare(uint32_t pd_flags)
#if SOC_USB_SERIAL_JTAG_SUPPORTED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP
sleep_console_usj_pad_restore();
#endif
#if !CONFIG_IDF_TARGET_ESP32C61
#if !CONFIG_IDF_TARGET_ESP32C61 // TODO: IDF-9304
sar_periph_ctrl_power_enable();
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
@ -2359,7 +2363,7 @@ static uint32_t get_power_down_flags(void)
}
#endif
#if SOC_PM_SUPPORT_RC32K_PD
#if !SOC_CLK_RC32K_NOT_TO_USE
#if !CONFIG_ESP_CLK_RC32K_NOT_TO_USE
if (s_config.domain[ESP_PD_DOMAIN_RC32K].pd_option != ESP_PD_OPTION_ON) {
pd_flags |= PMU_SLEEP_PD_RC32K;
}

View File

@ -82,10 +82,12 @@ SECONDARY: 103: esp_security_init in components/esp_security/src/init.c on BIT(0
SECONDARY: 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c6/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32c61/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32h2/sleep_clock.c on BIT(0)
SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/lowpower/port/esp32p4/sleep_clock.c on BIT(0)
SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0)
SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c5/sleep_mmu.c on BIT(0)
SECONDARY: 108: sleep_mmu_startup_init in components/esp_hw_support/lowpower/port/esp32c61/sleep_mmu.c on BIT(0)
# app_trace has to be initialized before systemview
SECONDARY: 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES

View File

@ -0,0 +1,172 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-C61 PAU(Power Assist Unit) register operations
#pragma once
#include <stdlib.h>
#include <stdbool.h>
#include "soc/soc.h"
#include "soc/pau_reg.h"
#include "soc/pau_struct.h"
#include "soc/pcr_struct.h"
#include "hal/pau_types.h"
#include "hal/assert.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline void pau_ll_enable_bus_clock(bool enable)
{
if (enable) {
PCR.regdma_conf.regdma_clk_en = 1;
PCR.regdma_conf.regdma_rst_en = 0;
} else {
PCR.regdma_conf.regdma_clk_en = 0;
PCR.regdma_conf.regdma_rst_en = 1;
}
}
static inline uint32_t pau_ll_get_regdma_backup_flow_error(pau_dev_t *dev)
{
return dev->regdma_conf.flow_err;
}
static inline void pau_ll_select_regdma_entry_link(pau_dev_t *dev, int link)
{
dev->regdma_conf.link_sel = link;
}
static inline void pau_ll_set_regdma_entry_link_backup_direction(pau_dev_t *dev, bool to_mem)
{
dev->regdma_conf.to_mem = to_mem ? 1 : 0;
}
static inline void pau_ll_set_regdma_entry_link_backup_start_enable(pau_dev_t *dev)
{
dev->regdma_conf.start = 1;
}
static inline void pau_ll_set_regdma_entry_link_backup_start_disable(pau_dev_t *dev)
{
dev->regdma_conf.start = 0;
}
static inline void pau_ll_set_regdma_select_wifimac_link(pau_dev_t *dev)
{
dev->regdma_conf.sel_mac = 1;
}
static inline void pau_ll_set_regdma_deselect_wifimac_link(pau_dev_t *dev)
{
dev->regdma_conf.sel_mac = 0;
}
static inline void pau_ll_set_regdma_wifimac_link_backup_direction(pau_dev_t *dev, bool to_mem)
{
dev->regdma_conf.to_mem_mac = to_mem ? 1 : 0;
}
static inline void pau_ll_set_regdma_wifimac_link_backup_start_enable(pau_dev_t *dev)
{
dev->regdma_conf.start_mac = 1;
}
static inline void pau_ll_set_regdma_wifimac_link_backup_start_disable(pau_dev_t *dev)
{
dev->regdma_conf.start_mac = 0;
}
static inline void pau_ll_set_regdma_link0_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_0_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_link1_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_1_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_link2_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_2_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_link3_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_3_addr.val = (uint32_t)link_addr;
}
static inline void pau_ll_set_regdma_wifimac_link_addr(pau_dev_t *dev, void *link_addr)
{
dev->regdma_link_mac_addr.val = (uint32_t)link_addr;
}
static inline uint32_t pau_ll_get_regdma_current_link_addr(pau_dev_t *dev)
{
return dev->regdma_current_link_addr.val;
}
static inline uint32_t pau_ll_get_regdma_backup_addr(pau_dev_t *dev)
{
return dev->regdma_backup_addr.val;
}
static inline uint32_t pau_ll_get_regdma_memory_addr(pau_dev_t *dev)
{
return dev->regdma_mem_addr.val;
}
static inline uint32_t pau_ll_get_regdma_intr_raw_signal(pau_dev_t *dev)
{
return dev->int_raw.val;
}
static inline uint32_t pau_ll_get_regdma_intr_status(pau_dev_t *dev)
{
return dev->int_st.val;
}
static inline void pau_ll_set_regdma_backup_done_intr_enable(pau_dev_t *dev)
{
dev->int_ena.done_int_ena = 1;
}
static inline void pau_ll_set_regdma_backup_done_intr_disable(pau_dev_t *dev)
{
dev->int_ena.done_int_ena = 0;
}
static inline void pau_ll_set_regdma_backup_error_intr_enable(pau_dev_t *dev, bool enable)
{
dev->int_ena.error_int_ena = enable;
}
static inline void pau_ll_clear_regdma_backup_done_intr_state(pau_dev_t *dev)
{
dev->int_clr.done_int_clr = 1;
}
static inline void pau_ll_clear_regdma_backup_error_intr_state(pau_dev_t *dev)
{
dev->int_clr.error_int_clr = 1;
}
static inline void pau_ll_set_regdma_link_wait_retry_count(pau_dev_t *dev, int count)
{
dev->regdma_bkp_conf.link_tout_thres = count;
}
static inline void pau_ll_set_regdma_link_wait_read_interval(pau_dev_t *dev, int interval)
{
dev->regdma_bkp_conf.read_interval = interval;
}
#ifdef __cplusplus
}
#endif

View File

@ -24,6 +24,7 @@ extern "C" {
// Get timer group register base address with giving group number
#define TIMER_LL_GET_HW(group_id) ((group_id == 0) ? (&TIMERG0) : (&TIMERG1))
#define TIMER_LL_EVENT_ALARM(timer_id) (1 << (timer_id))
#define TIMER_LL_SLEEP_RETENTION_MODULE_ID(group_id) ((group_id == 0) ? SLEEP_RETENTION_MODULE_TG0_TIMER: SLEEP_RETENTION_MODULE_TG1_TIMER)
#define TIMER_LL_ETM_TASK_TABLE(group, timer, task) \
(uint32_t [2][1][GPTIMER_ETM_TASK_MAX]){{{ \

View File

@ -64,6 +64,10 @@ extern "C" {
((hw) == &UART1) ? PCR.uart1_##reg_suffix.uart1_##field_suffix : \
PCR.uart2_##reg_suffix.uart2_##field_suffix)
// UART sleep retention module
#define UART_LL_SLEEP_RETENTION_MODULE_ID(uart_num) ((uart_num == UART_NUM_0) ? SLEEP_RETENTION_MODULE_UART0 : \
(uart_num == UART_NUM_1) ? SLEEP_RETENTION_MODULE_UART1 : -1)
// Define UART interrupts
typedef enum {
UART_INTR_RXFIFO_FULL = (0x1 << 0),

View File

@ -4,8 +4,6 @@
* SPDX-License-Identifier: Apache-2.0
*/
// The HAL layer for PAU (ESP32-C61 specific part)
#include "soc/soc.h"
#include "esp_attr.h"
#include "hal/pau_hal.h"
@ -59,3 +57,14 @@ void IRAM_ATTR pau_hal_stop_regdma_extra_link(pau_hal_context_t *hal)
pau_ll_select_regdma_entry_link(hal->dev, 0); /* restore link select to default */
pau_ll_clear_regdma_backup_done_intr_state(hal->dev);
}
void pau_hal_set_regdma_work_timeout(pau_hal_context_t *hal, uint32_t loop_num, uint32_t time)
{
}
void pau_hal_set_regdma_wait_timeout(pau_hal_context_t *hal, int count, int interval)
{
HAL_ASSERT(count > 0 && interval > 0);
pau_ll_set_regdma_link_wait_retry_count(hal->dev, count);
pau_ll_set_regdma_link_wait_read_interval(hal->dev, interval);
}

View File

@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-C6 PAU(Power Assist Unit) register operations
// The LL layer for ESP32-P4 PAU(Power Assist Unit) register operations
#pragma once

View File

@ -1355,11 +1355,15 @@ menu "LWIP"
choice LWIP_HOOK_IP6_INPUT
prompt "IPv6 packet input"
depends on LWIP_IPV6
default LWIP_HOOK_IP6_INPUT_NONE
default LWIP_HOOK_IP6_INPUT_DEFAULT
help
Enables custom IPv6 packet input.
Setting this to "default" provides weak implementation
stub that could be overwritten in application code.
Setting this to "default" provides weak IDF implementation,
which drops all incoming IPv6 traffic if the interface has no link local address.
(this default implementation is "weak" and could be still overwritten
in the application if some additional IPv6 input packet filtering is needed)
Setting this to "none" removes this default filter and conforms to the lwIP
implementation (which accepts multicasts even if the interface has no link local address)
Setting this to "custom" provides hook's declaration
only and expects the application to implement it.

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -56,11 +56,25 @@ const ip_addr_t *__weak lwip_hook_ip6_select_source_address(struct netif *netif,
#endif
#ifdef CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT
/**
* @brief The default IPv6 input hook checks if we already have an IPv6 address (netif->ip6_addr[0] is link local),
* so we drop all incoming IPv6 packets if the input netif has no LL address.
*
* LWIP accepts IPv6 multicast packets even if the ip6_addr[] for the given address wasn't set,
* this may cause trouble if we enable IPv6 SLAAC (LWIP_IPV6_AUTOCONFIG), but have not created any LL address.
* If the router sends a packet to all nodes 0xff01::1 with RDNSS servers, it would be accepted and rewrite
* DNS server info with IPv6 values (which won't be routable without any IPv6 address assigned)
*/
int __weak lwip_hook_ip6_input(struct pbuf *p, struct netif *inp)
{
LWIP_UNUSED_ARG(p);
LWIP_UNUSED_ARG(inp);
/* Check if the first IPv6 address (link-local) is unassigned (all zeros).
* If the address is empty, it indicates that no link-local address has been configured,
* and the interface should not accept incoming IPv6 traffic. */
if (ip6_addr_isany(ip_2_ip6(&inp->ip6_addr[0]))) {
/* We don't have an LL address -> eat this packet here, so it won't get accepted on the input netif */
pbuf_free(p);
return 1;
}
return 0;
}
#endif

View File

@ -142,6 +142,18 @@ extern "C" {
RV_WRITE_CSR((CSR_PMAADDR0) + (ENTRY) , 0); \
} while(0)
/* Reset and set the configuration of a particular TOR PMACFG entry */
#define PMA_RESET_AND_ENTRY_SET_TOR(ENTRY, ADDR, CFG) do {\
PMA_ENTRY_CFG_RESET(ENTRY); \
PMA_ENTRY_SET_TOR(ENTRY, ADDR, CFG); \
} while(0)
/* Reset and set the configuration of a particular NAPOT PMACFG entry */
#define PMA_RESET_AND_ENTRY_SET_NAPOT(ENTRY, ADDR, SIZE, CFG) do {\
PMA_ENTRY_CFG_RESET(ENTRY); \
PMA_ENTRY_SET_NAPOT(ENTRY, ADDR, SIZE, CFG); \
} while(0)
/********************************************************
Trigger Module register fields (Debug specification)
********************************************************/

View File

@ -1359,10 +1359,6 @@ config SOC_CLK_LP_FAST_SUPPORT_XTAL
bool
default y
config SOC_CLK_RC32K_NOT_TO_USE
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y

View File

@ -579,7 +579,6 @@
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */
#define SOC_CLK_RC32K_NOT_TO_USE (1) /*!< Due to the poor low-temperature characteristics of RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible. */
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/

View File

@ -131,6 +131,10 @@ config SOC_REG_I2C_SUPPORTED
bool
default y
config SOC_PAU_SUPPORTED
bool
default y
config SOC_LIGHT_SLEEP_SUPPORTED
bool
default y
@ -671,6 +675,14 @@ config SOC_TIMER_GROUP_SUPPORT_RC_FAST
bool
default y
config SOC_TIMER_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_MWDT_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_EFUSE_DIS_DOWNLOAD_ICACHE
bool
default n
@ -771,6 +783,10 @@ config SOC_UART_SUPPORT_WAKEUP_INT
bool
default y
config SOC_UART_SUPPORT_SLEEP_RETENTION
bool
default y
config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND
bool
default y
@ -827,6 +843,10 @@ config SOC_PM_SUPPORT_VDDSDIO_PD
bool
default y
config SOC_PM_SUPPORT_TOP_PD
bool
default y
config SOC_PM_SUPPORT_HP_AON_PD
bool
default y
@ -849,16 +869,32 @@ config SOC_PM_CPU_RETENTION_BY_SW
config SOC_PM_MODEM_RETENTION_BY_REGDMA
bool
default n
default y
config SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN
bool
default y
config SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD
bool
default y
config SOC_PM_PAU_LINK_NUM
int
default 4
config SOC_PM_PAU_REGDMA_LINK_MULTI_ADDR
bool
default y
config SOC_PM_PAU_REGDMA_LINK_WIFIMAC
bool
default y
config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE
bool
default y
config SOC_CLK_RC_FAST_SUPPORT_CALIBRATION
bool
default y
@ -879,10 +915,6 @@ config SOC_CLK_LP_FAST_SUPPORT_XTAL
bool
default y
config SOC_CLK_RC32K_NOT_TO_USE
bool
default y
config SOC_RCC_IS_INDEPENDENT
bool
default y

View File

@ -35,7 +35,7 @@
#define DR_REG_PAU_BASE 0x60093000
#define DR_REG_HP_SYSTEM_BASE 0x60095000
#define DR_REG_PCR_BASE 0x60096000
#define DR_REG_TEE_REG_BASE 0x60098000
#define DR_REG_TEE_BASE 0x60098000
#define DR_REG_HP_APM_BASE 0x60099000
#define DR_REG_MISC_BASE 0x6009F000
#define DR_REG_MODEM0_BASE 0x600A0000
@ -61,4 +61,3 @@
#define DR_REG_INTPRI_BASE 0x600C5000
#define DR_REG_CACHE_BASE 0x600C8000
#define DR_REG_CLINT_M_BASE 0x20000000
#define DR_REG_TEE_BASE DR_REG_TEE_REG_BASE

View File

@ -18,23 +18,29 @@ typedef enum periph_retention_module {
/* clock module, which includes system and modem */
SLEEP_RETENTION_MODULE_CLOCK_SYSTEM = 1,
SLEEP_RETENTION_MODULE_CLOCK_MODEM = 2,
/* modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 10,
SLEEP_RETENTION_MODULE_WIFI_BB = 11,
SLEEP_RETENTION_MODULE_BLE_MAC = 12,
SLEEP_RETENTION_MODULE_BT_BB = 13,
SLEEP_RETENTION_MODULE_802154_MAC = 14,
/* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM,
* TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */
SLEEP_RETENTION_MODULE_SYS_PERIPH = 16,
SLEEP_RETENTION_MODULE_GDMA_CH0 = 24,
SLEEP_RETENTION_MODULE_GDMA_CH1 = 25,
SLEEP_RETENTION_MODULE_GDMA_CH2 = 26,
SLEEP_RETENTION_MODULE_I2C0 = 27,
* TEE, APM, IOMUX, SPIMEM, SysTimer, etc.. */
SLEEP_RETENTION_MODULE_SYS_PERIPH = 3,
/* Timer Group by target */
SLEEP_RETENTION_MODULE_TG0_WDT = 4,
SLEEP_RETENTION_MODULE_TG1_WDT = 5,
SLEEP_RETENTION_MODULE_TG0_TIMER = 6,
SLEEP_RETENTION_MODULE_TG1_TIMER = 7,
/* GDMA by channel */
SLEEP_RETENTION_MODULE_GDMA_CH0 = 8,
SLEEP_RETENTION_MODULE_GDMA_CH1 = 9,
SLEEP_RETENTION_MODULE_GDMA_CH2 = 10,
/* MISC Peripherals */
SLEEP_RETENTION_MODULE_I2C0 = 12,
SLEEP_RETENTION_MODULE_UART0 = 14,
SLEEP_RETENTION_MODULE_UART1 = 15,
/* Modem module, which includes WiFi, BLE and 802.15.4 */
SLEEP_RETENTION_MODULE_WIFI_MAC = 26,
SLEEP_RETENTION_MODULE_WIFI_BB = 27,
SLEEP_RETENTION_MODULE_BLE_MAC = 28,
SLEEP_RETENTION_MODULE_BT_BB = 29,
SLEEP_RETENTION_MODULE_802154_MAC = 30,
SLEEP_RETENTION_MODULE_MAX = 31
} periph_retention_module_t;
@ -42,26 +48,44 @@ typedef enum periph_retention_module_bitmap {
/* clock module, which includes system and modem */
SLEEP_RETENTION_MODULE_BM_CLOCK_SYSTEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_SYSTEM),
SLEEP_RETENTION_MODULE_BM_CLOCK_MODEM = BIT(SLEEP_RETENTION_MODULE_CLOCK_MODEM),
/* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM,
* TEE, APM, IOMUX, SPIMEM, SysTimer, etc.. */
SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH),
/* Timer Group by target*/
SLEEP_RETENTION_MODULE_BM_TASK_WDT = BIT(SLEEP_RETENTION_MODULE_TG0_WDT),
SLEEP_RETENTION_MODULE_BM_INT_WDT = BIT(SLEEP_RETENTION_MODULE_TG1_WDT),
SLEEP_RETENTION_MODULE_BM_TG0_TIMER = BIT(SLEEP_RETENTION_MODULE_TG0_TIMER),
SLEEP_RETENTION_MODULE_BM_TG1_TIMER = BIT(SLEEP_RETENTION_MODULE_TG1_TIMER),
/* GDMA by channel */
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2),
/* MISC Peripherals */
SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0),
SLEEP_RETENTION_MODULE_BM_UART0 = BIT(SLEEP_RETENTION_MODULE_UART0),
SLEEP_RETENTION_MODULE_BM_UART1 = BIT(SLEEP_RETENTION_MODULE_UART1),
/* 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),
SLEEP_RETENTION_MODULE_BM_BLE_MAC = BIT(SLEEP_RETENTION_MODULE_BLE_MAC),
SLEEP_RETENTION_MODULE_BM_BT_BB = BIT(SLEEP_RETENTION_MODULE_BT_BB),
SLEEP_RETENTION_MODULE_BM_802154_MAC = BIT(SLEEP_RETENTION_MODULE_802154_MAC),
/* digital peripheral module, which includes Interrupt Matrix, HP_SYSTEM,
* TEE, APM, UART, Timer Group, IOMUX, SPIMEM, SysTimer, etc.. */
SLEEP_RETENTION_MODULE_BM_SYS_PERIPH = BIT(SLEEP_RETENTION_MODULE_SYS_PERIPH),
SLEEP_RETENTION_MODULE_BM_GDMA_CH0 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH0),
SLEEP_RETENTION_MODULE_BM_GDMA_CH1 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH1),
SLEEP_RETENTION_MODULE_BM_GDMA_CH2 = BIT(SLEEP_RETENTION_MODULE_GDMA_CH2),
SLEEP_RETENTION_MODULE_BM_I2C0 = BIT(SLEEP_RETENTION_MODULE_I2C0),
SLEEP_RETENTION_MODULE_BM_ALL = (uint32_t)-1
} periph_retention_module_bitmap_t;
#define TOP_DOMAIN_PERIPHERALS_BM ( SLEEP_RETENTION_MODULE_BM_SYS_PERIPH \
| SLEEP_RETENTION_MODULE_BM_TASK_WDT \
| SLEEP_RETENTION_MODULE_BM_INT_WDT \
| SLEEP_RETENTION_MODULE_BM_TG0_TIMER \
| SLEEP_RETENTION_MODULE_BM_TG1_TIMER \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH0 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH1 \
| SLEEP_RETENTION_MODULE_BM_GDMA_CH2 \
| SLEEP_RETENTION_MODULE_BM_I2C0 \
| SLEEP_RETENTION_MODULE_BM_UART0 \
| SLEEP_RETENTION_MODULE_BM_UART1 \
)
#ifdef __cplusplus
}
#endif

View File

@ -59,7 +59,7 @@
#define SOC_REG_I2C_SUPPORTED 1
// \#define SOC_ETM_SUPPORTED 0
// \#define SOC_SDIO_SLAVE_SUPPORTED 0
// \#define SOC_PAU_SUPPORTED 0
#define SOC_PAU_SUPPORTED 1
#define SOC_LIGHT_SLEEP_SUPPORTED 1
#define SOC_DEEP_SLEEP_SUPPORTED 1
#define SOC_PM_SUPPORTED 1
@ -349,10 +349,12 @@
#define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (54)
#define SOC_TIMER_GROUP_SUPPORT_XTAL (1)
#define SOC_TIMER_GROUP_SUPPORT_RC_FAST (1)
#define SOC_TIMER_SUPPORT_SLEEP_RETENTION (1)
// #define SOC_TIMER_SUPPORT_ETM (1)
/*--------------------------- WATCHDOG CAPS ---------------------------------------*/
// #define SOC_MWDT_SUPPORT_XTAL (1)
#define SOC_MWDT_SUPPORT_SLEEP_RETENTION (1)
/*-------------------------- eFuse CAPS----------------------------*/
#define SOC_EFUSE_DIS_DOWNLOAD_ICACHE 0
@ -391,7 +393,7 @@
#define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */
#define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */
#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */
#define SOC_UART_SUPPORT_SLEEP_RETENTION (1)
// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled
#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1)
@ -423,7 +425,7 @@
#define SOC_PM_SUPPORT_RC32K_PD (1)
#define SOC_PM_SUPPORT_RC_FAST_PD (1)
#define SOC_PM_SUPPORT_VDDSDIO_PD (1)
// \#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_SUPPORT_TOP_PD (1)
#define SOC_PM_SUPPORT_HP_AON_PD (1)
#define SOC_PM_SUPPORT_MAC_BB_PD (1)
#define SOC_PM_SUPPORT_RTC_PERIPH_PD (1)
@ -433,9 +435,15 @@
#define MAC_SUPPORT_PMU_MODEM_STATE SOC_PM_SUPPORT_PMU_MODEM_STATE
#define SOC_PM_CPU_RETENTION_BY_SW (1)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (0)
#define SOC_PM_MODEM_RETENTION_BY_REGDMA (1)
#define SOC_EXT_MEM_CACHE_TAG_IN_CPU_DOMAIN (1)
#define SOC_PM_PAU_LINK_NUM (4)
#define SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD (1)
#define SOC_PM_PAU_LINK_NUM (4)
#define SOC_PM_PAU_REGDMA_LINK_MULTI_ADDR (1)
#define SOC_PM_PAU_REGDMA_LINK_WIFIMAC (1)
#define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1)
/*-------------------------- CLOCK SUBSYSTEM CAPS ----------------------------------------*/
#define SOC_CLK_RC_FAST_SUPPORT_CALIBRATION (1)
@ -444,7 +452,6 @@
#define SOC_CLK_XTAL32K_SUPPORTED (1) /*!< Support to connect an external low frequency crystal */
#define SOC_CLK_OSC_SLOW_SUPPORTED (1) /*!< Support to connect an external oscillator, not a crystal */
#define SOC_CLK_LP_FAST_SUPPORT_XTAL (1) /*!< Support XTAL clock as the LP_FAST clock source */
#define SOC_CLK_RC32K_NOT_TO_USE (1) /*!< Due to the poor low-temperature characteristics of RC32K (it cannot operate below -40 degrees Celsius), please avoid using it whenever possible. */
#define SOC_RCC_IS_INDEPENDENT 1 /*!< Reset and Clock Control is independent, thanks to the PCR registers */
/*-------------------------- Temperature Sensor CAPS -------------------------------------*/

View File

@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "soc/soc_caps.h"
#include "soc/regdma.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Provide access to interrupt matrix configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define INT_MTX_RETENTION_LINK_LEN 1
extern const regdma_entries_config_t intr_matrix_regs_retention[INT_MTX_RETENTION_LINK_LEN];
/**
* @brief Provide access to hp_system configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define HP_SYSTEM_RETENTION_LINK_LEN 1
extern const regdma_entries_config_t hp_system_regs_retention[HP_SYSTEM_RETENTION_LINK_LEN];
/**
* @brief Provide access to TEE_APM configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define TEE_APM_RETENTION_LINK_LEN 2
extern const regdma_entries_config_t tee_apm_regs_retention[TEE_APM_RETENTION_LINK_LEN];
#define TEE_APM_HIGH_PRI_RETENTION_LINK_LEN 1
extern const regdma_entries_config_t tee_apm_highpri_regs_retention[TEE_APM_HIGH_PRI_RETENTION_LINK_LEN];
/**
* @brief Provide access to IOMUX configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define IOMUX_RETENTION_LINK_LEN 7
extern const regdma_entries_config_t iomux_regs_retention[IOMUX_RETENTION_LINK_LEN];
/**
* @brief Provide access to spimem configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define SPIMEM_RETENTION_LINK_LEN 8
extern const regdma_entries_config_t flash_spimem_regs_retention[SPIMEM_RETENTION_LINK_LEN];
/**
* @brief Provide access to systimer configuration registers retention
* context definition.
*
* This is an internal function of the sleep retention driver, and is not
* useful for external use.
*/
#define SYSTIMER_RETENTION_LINK_LEN 19
extern const regdma_entries_config_t systimer_regs_retention[SYSTIMER_RETENTION_LINK_LEN];
#ifdef __cplusplus
}
#endif

View File

@ -769,9 +769,9 @@ extern "C" {
* Version control register
*/
#define TEE_DATE 0x0FFFFFFFU
#define TEE_DATE_REG_M (TEE_DATE_REG_V << TEE_DATE_REG_S)
#define TEE_DATE_REG_V 0x0FFFFFFFU
#define TEE_DATE_REG_S 0
#define TEE_DATE_M (TEE_DATE_REG_V << TEE_DATE_REG_S)
#define TEE_DATE_V 0x0FFFFFFFU
#define TEE_DATE_S 0
#ifdef __cplusplus
}

View File

@ -0,0 +1,121 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/regdma.h"
#include "soc/system_periph_retention.h"
#include "soc/timer_periph.h"
#include "soc/uart_reg.h"
#include "soc/systimer_reg.h"
#include "soc/timer_group_reg.h"
#include "soc/spi_mem_reg.h"
#include "soc/hp_system_reg.h"
#include "soc/tee_reg.h"
#include "soc/hp_apm_reg.h"
#include "soc/gpio_reg.h"
#include "soc/io_mux_reg.h"
#include "soc/interrupt_matrix_reg.h"
/* Interrupt Matrix Registers Context */
#define N_REGS_INTR_MATRIX() (((INTERRUPT_CORE0_CLOCK_GATE_REG - DR_REG_INTERRUPT_CORE0_BASE) / 4) + 1)
const regdma_entries_config_t intr_matrix_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_INTMTX_LINK(0), DR_REG_INTERRUPT_CORE0_BASE, DR_REG_INTERRUPT_CORE0_BASE, N_REGS_INTR_MATRIX(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* intr matrix */
};
_Static_assert(ARRAY_SIZE(intr_matrix_regs_retention) == INT_MTX_RETENTION_LINK_LEN, "Inconsistent INT_MTX retention link length definitions");
/* HP System Registers Context */
#define N_REGS_HP_SYSTEM() (((HP_SYSTEM_CLOCK_GATE_REG - DR_REG_HP_SYSTEM_BASE) / 4) + 1)
const regdma_entries_config_t hp_system_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_HPSYS_LINK(0), DR_REG_HP_SYSTEM_BASE, DR_REG_HP_SYSTEM_BASE, N_REGS_HP_SYSTEM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* hp system */
};
_Static_assert(ARRAY_SIZE(hp_system_regs_retention) == HP_SYSTEM_RETENTION_LINK_LEN, "Inconsistent HP_SYSTEM retention link length definitions");
/* TEE/APM Registers Context */
#define N_REGS_TEE() (((TEE_CLOCK_GATE_REG - DR_REG_TEE_BASE) / 4) + 1)
#define N_REGS_APM() (((HP_APM_CLOCK_GATE_REG - DR_REG_HP_APM_BASE) / 4) + 1)
const regdma_entries_config_t tee_apm_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(0), DR_REG_HP_APM_BASE, DR_REG_HP_APM_BASE, N_REGS_APM(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* apm */
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TEEAPM_LINK(1), DR_REG_TEE_BASE, DR_REG_TEE_BASE, N_REGS_TEE(), 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* tee */
};
const regdma_entries_config_t tee_apm_highpri_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT(REGDMA_TEEAPM_LINK(2), TEE_M4_MODE_CTRL_REG, 0x0, 0xffffffff, 1, 0), .owner = ENTRY(2) }
};
_Static_assert((ARRAY_SIZE(tee_apm_regs_retention) == TEE_APM_RETENTION_LINK_LEN) && (ARRAY_SIZE(tee_apm_highpri_regs_retention) == TEE_APM_HIGH_PRI_RETENTION_LINK_LEN), "Inconsistent TEE_APM retention link length definitions");
/* IO MUX Registers Context */
#define N_REGS_IOMUX_0() (((PERIPHS_IO_MUX_U_PAD_SPID - REG_IO_MUX_BASE) / 4) + 1)
#define N_REGS_IOMUX_1() (((GPIO_FUNC21_OUT_SEL_CFG_REG - GPIO_FUNC0_OUT_SEL_CFG_REG) / 4) + 1)
#define N_REGS_IOMUX_2() (((GPIO_FUNC121_IN_SEL_CFG_REG - GPIO_FUNC0_IN_SEL_CFG_REG) / 4) + 1)
#define N_REGS_IOMUX_3() (((GPIO_PIN21_REG - GPIO_PIN0_REG) / 4) + 1)
#define N_REGS_IOMUX_4() (1)
#define N_REGS_IOMUX_5() (1)
#define N_REGS_IOMUX_6() (1)
const regdma_entries_config_t iomux_regs_retention[] = {
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x00), REG_IO_MUX_BASE, REG_IO_MUX_BASE, N_REGS_IOMUX_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* io_mux */
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x01), GPIO_FUNC0_OUT_SEL_CFG_REG, GPIO_FUNC0_OUT_SEL_CFG_REG, N_REGS_IOMUX_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x02), GPIO_FUNC0_IN_SEL_CFG_REG, GPIO_FUNC0_IN_SEL_CFG_REG, N_REGS_IOMUX_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x03), GPIO_PIN0_REG, GPIO_PIN0_REG, N_REGS_IOMUX_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x04), GPIO_STATUS_REG, GPIO_STATUS_REG, N_REGS_IOMUX_4(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x05), GPIO_ENABLE_REG, GPIO_ENABLE_REG, N_REGS_IOMUX_5(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_IOMUX_LINK(0x06), GPIO_OUT_REG, GPIO_OUT_REG, N_REGS_IOMUX_6(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }
};
_Static_assert(ARRAY_SIZE(iomux_regs_retention) == IOMUX_RETENTION_LINK_LEN, "Inconsistent IOMUX retention link length definitions");
/* Memory SPI Registers Context */
#define N_REGS_SPI1_MEM_0() (((SPI_SMEM_DDR_REG(1) - REG_SPI_MEM_BASE(1)) / 4) + 1)
#define N_REGS_SPI1_MEM_1() (1)
#define N_REGS_SPI1_MEM_2() (1)
#define N_REGS_SPI0_MEM_0() (((SPI_SMEM_DDR_REG(0) - REG_SPI_MEM_BASE(0)) / 4) + 1)
#define N_REGS_SPI0_MEM_1() (((SPI_SMEM_AC_REG(0) - SPI_FMEM_PMS0_ATTR_REG(0)) / 4) + 1)
#define N_REGS_SPI0_MEM_2() (1)
#define N_REGS_SPI0_MEM_3() (((SPI_MEM_XTS_PSEUDO_ROUND_CONF_REG(0) - SPI_MEM_MMU_POWER_CTRL_REG(0)) / 4) + 1)
const regdma_entries_config_t flash_spimem_regs_retention[] = {
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
[0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x00), REG_SPI_MEM_BASE(1), REG_SPI_MEM_BASE(1), N_REGS_SPI1_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi1_mem */
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x01), SPI_MEM_TIMING_CALI_REG(1), SPI_MEM_TIMING_CALI_REG(1), N_REGS_SPI1_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x02), SPI_MEM_CLOCK_GATE_REG(1), SPI_MEM_CLOCK_GATE_REG(1), N_REGS_SPI1_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
/* Note: SPI mem should not to write mmu SPI_MEM_MMU_ITEM_CONTENT_REG and SPI_MEM_MMU_ITEM_INDEX_REG */
[3] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x03), REG_SPI_MEM_BASE(0), REG_SPI_MEM_BASE(0), N_REGS_SPI0_MEM_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* spi0_mem */
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x04), SPI_FMEM_PMS0_ATTR_REG(0), SPI_FMEM_PMS0_ATTR_REG(0), N_REGS_SPI0_MEM_1(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x05), SPI_MEM_CLOCK_GATE_REG(0), SPI_MEM_CLOCK_GATE_REG(0), N_REGS_SPI0_MEM_2(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SPIMEM_LINK(0x06), SPI_MEM_MMU_POWER_CTRL_REG(0), SPI_MEM_MMU_POWER_CTRL_REG(0), N_REGS_SPI0_MEM_3(), 0, 0), .owner = ENTRY(0) | ENTRY(2) },
/* Note: spimem register should set update reg to make the configuration take effect */
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SPIMEM_LINK(0x07), SPI_MEM_TIMING_CALI_REG(0), SPI_MEM_TIMING_CALI_UPDATE, SPI_MEM_TIMING_CALI_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }
};
_Static_assert(ARRAY_SIZE(flash_spimem_regs_retention) == SPIMEM_RETENTION_LINK_LEN, "Inconsistent SPI Mem retention link length definitions");
/* Systimer Registers Context */
#define N_REGS_SYSTIMER_0() (((SYSTIMER_TARGET2_CONF_REG - SYSTIMER_TARGET0_HI_REG) / 4) + 1)
const regdma_entries_config_t systimer_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x00), SYSTIMER_UNIT0_OP_REG, SYSTIMER_TIMER_UNIT0_UPDATE_M, SYSTIMER_TIMER_UNIT0_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) }, /* Systimer */
[1] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_SYSTIMER_LINK(0x01), SYSTIMER_UNIT0_OP_REG, SYSTIMER_TIMER_UNIT0_VALUE_VALID, SYSTIMER_TIMER_UNIT0_VALUE_VALID, 0, 1), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x02), SYSTIMER_UNIT0_VALUE_HI_REG, SYSTIMER_UNIT0_LOAD_HI_REG, 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x03), SYSTIMER_UNIT0_LOAD_REG, SYSTIMER_TIMER_UNIT0_LOAD_M, SYSTIMER_TIMER_UNIT0_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x04), SYSTIMER_UNIT1_OP_REG, SYSTIMER_TIMER_UNIT1_UPDATE_M, SYSTIMER_TIMER_UNIT1_UPDATE_M, 0, 1), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_SYSTIMER_LINK(0x05), SYSTIMER_UNIT1_OP_REG, SYSTIMER_TIMER_UNIT1_VALUE_VALID, SYSTIMER_TIMER_UNIT1_VALUE_VALID, 0, 1), .owner = ENTRY(0) | ENTRY(2) },
[6] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x06), SYSTIMER_UNIT1_VALUE_HI_REG, SYSTIMER_UNIT1_LOAD_HI_REG, 2, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[7] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x07), SYSTIMER_UNIT1_LOAD_REG, SYSTIMER_TIMER_UNIT1_LOAD_M, SYSTIMER_TIMER_UNIT1_LOAD_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[8] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x08), SYSTIMER_TARGET0_HI_REG, SYSTIMER_TARGET0_HI_REG, N_REGS_SYSTIMER_0(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* Systimer target value & period */
[9] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x09), SYSTIMER_COMP0_LOAD_REG, SYSTIMER_TIMER_COMP0_LOAD, SYSTIMER_TIMER_COMP0_LOAD, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[10] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0a), SYSTIMER_COMP1_LOAD_REG, SYSTIMER_TIMER_COMP1_LOAD, SYSTIMER_TIMER_COMP1_LOAD, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[11] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0b), SYSTIMER_COMP2_LOAD_REG, SYSTIMER_TIMER_COMP2_LOAD, SYSTIMER_TIMER_COMP2_LOAD, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[12] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0c), SYSTIMER_TARGET0_CONF_REG, 0, SYSTIMER_TARGET0_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[13] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0d), SYSTIMER_TARGET0_CONF_REG, SYSTIMER_TARGET0_PERIOD_MODE_M, SYSTIMER_TARGET0_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[14] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0e), SYSTIMER_TARGET1_CONF_REG, 0, SYSTIMER_TARGET1_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[15] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x0f), SYSTIMER_TARGET1_CONF_REG, SYSTIMER_TARGET1_PERIOD_MODE_M, SYSTIMER_TARGET1_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[16] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_SYSTIMER_LINK(0x10), SYSTIMER_TARGET2_CONF_REG, 0, SYSTIMER_TARGET2_PERIOD_MODE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[17] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x11), SYSTIMER_CONF_REG, SYSTIMER_CONF_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* Systimer work enable */
[18] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_SYSTIMER_LINK(0x12), SYSTIMER_INT_ENA_REG, SYSTIMER_INT_ENA_REG, 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) } /* Systimer intr enable */
};
_Static_assert(ARRAY_SIZE(systimer_regs_retention) == SYSTIMER_RETENTION_LINK_LEN, "Inconsistent Systimer retention link length definitions");

View File

@ -22,3 +22,112 @@ const timer_group_signal_conn_t timer_group_periph_signals = {
}
}
};
/* Registers in retention context:
* TIMG_T0CONFIG_REG
* TIMG_T0ALARMLO_REG
* TIMG_T0ALARMHI_REG
* TIMG_T0LOADLO_REG
* TIMG_T0LOADHI_REG
* TIMG_INT_ENA_TIMERS_REG
* TIMG_REGCLK_REG
*/
#define TG_TIMER_RETENTION_REGS_CNT 7
static const uint32_t tg_timer_regs_map[4] = {0x100000f1, 0x80000000, 0x0, 0x0};
const regdma_entries_config_t tg0_timer_regdma_entries[] = {
// backup stage: trigger a soft capture
[0] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x00),
TIMG_T0UPDATE_REG(0), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: wait for the capture done
[1] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG0_TIMER_LINK(0x01),
TIMG_T0UPDATE_REG(0), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save the captured counter value
// restore stage: store the captured counter value to the loader register
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x02),
TIMG_T0LO_REG(0), TIMG_T0LOADLO_REG(0), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
[3] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_TIMER_LINK(0x03),
TIMG_T0HI_REG(0), TIMG_T0LOADHI_REG(0), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[4] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG0_TIMER_LINK(0x04),
TIMG_T0LOAD_REG(0), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[5] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG0_TIMER_LINK(0x05),
TIMG_T0CONFIG_REG(0), TIMG_T0CONFIG_REG(0),
TG_TIMER_RETENTION_REGS_CNT, 0, 0,
tg_timer_regs_map[0], tg_timer_regs_map[1],
tg_timer_regs_map[2], tg_timer_regs_map[3]),
.owner = TIMG_RETENTION_ENTRY
},
};
const regdma_entries_config_t tg1_timer_regdma_entries[] = {
// backup stage: trigger a soft capture
[0] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x00),
TIMG_T0UPDATE_REG(1), TIMG_T0_UPDATE, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: wait for the capture done
[1] = {
.config = REGDMA_LINK_WAIT_INIT(REGDMA_TG1_TIMER_LINK(0x01),
TIMG_T0UPDATE_REG(1), 0x0, TIMG_T0_UPDATE_M, 0, 1),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save the captured counter value
// restore stage: store the captured counter value to the loader register
[2] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x02),
TIMG_T0LO_REG(1), TIMG_T0LOADLO_REG(1), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
[3] = {
.config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_TIMER_LINK(0x03),
TIMG_T0HI_REG(1), TIMG_T0LOADHI_REG(1), 2, 0, 0),
.owner = TIMG_RETENTION_ENTRY
},
// restore stage: trigger a soft reload, so the timer can continue from where it was backed up
[4] = {
.config = REGDMA_LINK_WRITE_INIT(REGDMA_TG1_TIMER_LINK(0x04),
TIMG_T0LOAD_REG(1), 0x1, TIMG_T0_LOAD_M, 1, 0),
.owner = TIMG_RETENTION_ENTRY
},
// backup stage: save other configuration and status registers
// restore stage: restore the configuration and status registers
[5] = {
.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_TG1_TIMER_LINK(0x05),
TIMG_T0CONFIG_REG(1), TIMG_T0CONFIG_REG(1),
TG_TIMER_RETENTION_REGS_CNT, 0, 0,
tg_timer_regs_map[0], tg_timer_regs_map[1],
tg_timer_regs_map[2], tg_timer_regs_map[3]),
.owner = TIMG_RETENTION_ENTRY
},
};
const tg_timer_reg_retention_info_t tg_timer_reg_retention_info[SOC_TIMER_GROUPS] = {
[0] = {
.regdma_entry_array = tg0_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg0_timer_regdma_entries)
},
[1] = {
.regdma_entry_array = tg1_timer_regdma_entries,
.array_size = ARRAY_SIZE(tg1_timer_regdma_entries)
},
};

View File

@ -5,6 +5,7 @@
*/
#include "soc/uart_periph.h"
#include "soc/uart_reg.h"
/*
Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc
@ -108,3 +109,52 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
.irq = ETS_UART2_INTR_SOURCE,
},
};
/**
* UART registers to be saved during sleep retention
*
* Reset TXFIFO and RXFIFO
* UART registers require set the reg_update bit to make the configuration take effect
*
* UART_INT_ENA_REG, UART_CLKDIV_SYNC_REG, UART_RX_FILT_REG, UART_CONF0_SYNC_REG, UART_CONF1_REG,
* UART_HWFC_CONF_SYNC_REG, UART_SLEEP_CONF0_REG, UART_SLEEP_CONF1_REG, UART_SLEEP_CONF2_REG,
* UART_SWFC_CONF0_SYNC_REG, UART_SWFC_CONF1_REG, UART_TXBRK_CONF_SYNC_REG, UART_IDLE_CONF_SYNC_REG,
* UART_RS485_CONF_SYNC_REG, UART_AT_CMD_PRECNT_SYNC_REG, UART_AT_CMD_POSTCNT_SYNC_REG, UART_AT_CMD_GAPTOUT_SYNC_REG,
* UART_AT_CMD_CHAR_SYNC_REG, UART_MEM_CONF_REG, UART_TOUT_CONF_SYNC_REG, UART_ID_REG
*/
#define UART_RETENTION_ADDR_MAP_REGS_CNT 21
#define UART_RETENTION_REGS_BASE(i) UART_INT_ENA_REG(i)
static const uint32_t uart_regs_map[4] = {0x7fff6d, 0x10, 0x0, 0x0};
#define UART_SLEEP_RETENTION_ENTRIES(uart_num) { \
[0] = {.config = REGDMA_LINK_ADDR_MAP_INIT(REGDMA_UART_LINK(0x00), \
UART_RETENTION_REGS_BASE(uart_num), UART_RETENTION_REGS_BASE(uart_num), \
UART_RETENTION_ADDR_MAP_REGS_CNT, 0, 0, \
uart_regs_map[0], uart_regs_map[1], \
uart_regs_map[2], uart_regs_map[3] \
), \
.owner = ENTRY(0) | ENTRY(2) }, \
[1] = {.config = REGDMA_LINK_WRITE_INIT(REGDMA_UART_LINK(0x01), \
UART_REG_UPDATE_REG(uart_num), UART_REG_UPDATE, \
UART_REG_UPDATE_M, 1, 0 \
), \
.owner = ENTRY(0) | ENTRY(2) }, \
[2] = {.config = REGDMA_LINK_WAIT_INIT(REGDMA_UART_LINK(0x02), \
UART_REG_UPDATE_REG(uart_num), 0x0, \
UART_REG_UPDATE_M, 1, 0 \
), \
.owner = ENTRY(0) | ENTRY(2) }, \
}
static const regdma_entries_config_t uart0_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(0);
static const regdma_entries_config_t uart1_regdma_entries[] = UART_SLEEP_RETENTION_ENTRIES(1);
const uart_reg_retention_info_t uart_reg_retention_info[SOC_UART_HP_NUM] = {
[0] = {
.regdma_entry_array = uart0_regdma_entries,
.array_size = ARRAY_SIZE(uart0_regdma_entries),
},
[1] = {
.regdma_entry_array = uart1_regdma_entries,
.array_size = ARRAY_SIZE(uart1_regdma_entries),
},
};

View File

@ -5,3 +5,28 @@
*/
#include "soc/wdt_periph.h"
#define N_REGS_TGWDT 6 // TIMG_WDTCONFIG0_REG ... TIMG_WDTCONFIG5_REG & TIMG_INT_ENA_TIMERS_REG
static const regdma_entries_config_t tg0_wdt_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x01), TIMG_WDTCONFIG0_REG(0), TIMG_WDTCONFIG0_REG(0), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x02), TIMG_WDTCONFIG0_REG(0), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x03), TIMG_WDTFEED_REG(0), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[4] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG0_WDT_LINK(0x04), TIMG_INT_ENA_TIMERS_REG(0),TIMG_INT_ENA_TIMERS_REG(0), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x05), TIMG_WDTWPROTECT_REG(0), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
};
static const regdma_entries_config_t tg1_wdt_regs_retention[] = {
[0] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x00), TIMG_WDTWPROTECT_REG(1), TIMG_WDT_WKEY_VALUE, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[1] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x01), TIMG_INT_ENA_TIMERS_REG(1),TIMG_INT_ENA_TIMERS_REG(1), 1, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[2] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_TG1_WDT_LINK(0x02), TIMG_WDTCONFIG0_REG(1), TIMG_WDTCONFIG0_REG(1), N_REGS_TGWDT, 0, 0), .owner = ENTRY(0) | ENTRY(2) },
[3] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x03), TIMG_WDTCONFIG0_REG(1), TIMG_WDT_CONF_UPDATE_EN, TIMG_WDT_CONF_UPDATE_EN_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[4] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG0_WDT_LINK(0x04), TIMG_WDTFEED_REG(1), TIMG_WDT_FEED, TIMG_WDT_FEED_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
[5] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_TG1_WDT_LINK(0x05), TIMG_WDTWPROTECT_REG(1), 0, TIMG_WDT_WKEY_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) },
};
const tg_reg_ctx_link_t tg_wdt_regs_retention[SOC_TIMER_GROUPS] = {
[0] = {tg0_wdt_regs_retention, ARRAY_SIZE(tg0_wdt_regs_retention)},
[1] = {tg1_wdt_regs_retention, ARRAY_SIZE(tg1_wdt_regs_retention)},
};

View File

@ -52,7 +52,8 @@ endif()
if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
list(APPEND srcs
"lp_core/lp_core.c"
"lp_core/shared/ulp_lp_core_memory_shared.c")
"lp_core/shared/ulp_lp_core_memory_shared.c"
"lp_core/shared/ulp_lp_core_critical_section_shared.c")
if(CONFIG_SOC_ULP_LP_UART_SUPPORTED)
list(APPEND srcs "lp_core/lp_core_uart.c")

View File

@ -125,7 +125,8 @@ function(ulp_apply_default_sources ulp_app_name)
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_i2c.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_spi.c"
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_ubsan.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_adc_shared.c")
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_adc_shared.c"
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_critical_section_shared.c")
set(target_folder ${IDF_TARGET})

View File

@ -0,0 +1,62 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
LOCK_CANDIDATE_LP_CORE = 0,
LOCK_CANDIDATE_HP_CORE_0,
#if CONFIG_FREERTOS_NUMBER_OF_CORES > 1
LOCK_CANDIDATE_HP_CORE_1,
#endif
LOCK_CANDIDATE_NUM_MAX,
} ulp_lp_core_spinlock_candidate_t;
typedef struct {
volatile int level[LOCK_CANDIDATE_NUM_MAX];
volatile int last_to_enter[LOCK_CANDIDATE_NUM_MAX - 1];
volatile unsigned int prev_int_level;
} ulp_lp_core_spinlock_t;
/**
* @brief Initialize the spinlock that protects shared resources between main CPU and LP CPU.
*
* @note The spinlock can be initialized in either main program or LP program.
*
* @param lock Pointer to lock struct
*/
void ulp_lp_core_spinlock_init(ulp_lp_core_spinlock_t *lock);
/**
* @brief Enter the critical section that protects shared resources between main CPU and LP CPU.
*
* @note This critical section is designed for being used by multiple threads, it is safe to try to enter it
* simultaneously from multiple threads on multiple main CPU cores and LP CPU.
*
* @note This critical section does not support nesting entering and exiting.
*
* @param lock Pointer to lock struct
*/
void ulp_lp_core_enter_critical(ulp_lp_core_spinlock_t *lock);
/**
* @brief Exit the critical section that protect shared resource between main CPU and LP CPU.
*
* @note This critical section does not support nesting entering and exiting.
*
* @param lock Pointer to lock struct
*/
void ulp_lp_core_exit_critical(ulp_lp_core_spinlock_t *lock);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,158 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_lp_core_critical_section_shared.h"
#include "esp_cpu.h"
#if IS_ULP_COCPU
#include "ulp_lp_core_interrupts.h"
#endif
/* Masked interrupt threshold varies between different types of interrupt controller */
#if !SOC_INT_CLIC_SUPPORTED
#define INT_MASK_THRESHOLD RVHAL_EXCM_LEVEL
#else /* SOC_INT_CLIC_SUPPORTED */
#define INT_MASK_THRESHOLD RVHAL_EXCM_LEVEL_CLIC
#endif /* !SOC_INIT_CLIC_SUPPORTED */
void ulp_lp_core_spinlock_init(ulp_lp_core_spinlock_t *lock)
{
int i = 0;
for (i = 0; i < LOCK_CANDIDATE_NUM_MAX; i++) {
lock->level[i] = -1;
}
for (i = 0; i < LOCK_CANDIDATE_NUM_MAX - 1; i++) {
lock->last_to_enter[i] = 0;
}
}
#if RTC_MEM_AMO_INSTRUCTIONS_VERIFIED
/* ULP spinlock ACQ/REL functions also have a hardware implementation base on AMOSWAP instructions,
which has much better performance but have not been thoroughly verified yet on RTC memory. This set
of implementation will be adapted once it's verified.
*/
static void ulp_lp_core_spinlock_acquire(ulp_lp_core_spinlock_t *lock)
{
/* Based on sample code for AMOSWAP from RISCV specs v2.1 */
asm volatile(
"li t0, 1\n" // Initialize swap value.
"1:\n"
"lw t1, (%0)\n" // Check if lock is held.
"bnez t1, 1b\n" // Retry if held.
"amoswap.w.aq t1, t0, (%0)\n" // Attempt to acquire lock.
"bnez t1, 1b\n" // Retry if held.
:
: "r"(lock)
: "t0", "t1", "memory"
);
}
static void ulp_lp_core_spinlock_release(ulp_lp_core_spinlock_t *lock)
{
asm volatile(
"amoswap.w.rl x0, x0, (%0)\n" // Release lock by storing 0
:
: "r"(lock)
: "memory"
);
}
#else // !RTC_MEM_AMO_INSTRUCTIONS_VERIFIED
/**
* @brief Obtain the id of current lock candidate.
*
* @return lock candidate id
*/
static int ulp_lp_core_spinlock_get_candidate_id(void)
{
int lock_candidate_id = 0;
#if !IS_ULP_COCPU
/* Refer to ulp_lp_core_spinlock_candidate_t, each HP_CORE lock candidate's index is the core id plus 1 */
lock_candidate_id = esp_cpu_get_core_id() + 1;
#else
lock_candidate_id = LOCK_CANDIDATE_LP_CORE;
#endif
return lock_candidate_id;
}
/**
* @brief Software lock implementation is based on the filter algorithm, which is a generalization of Peterson's algorithm, https://en.wikipedia.org/wiki/Peterson%27s_algorithm#Filter_algorithm:_Peterson's_algorithm_for_more_than_two_processes
*
*/
/**
* @brief Attempt to acquire the lock. Spins until lock is acquired.
*
* @note This lock is designed for being used by multiple threads, it is safe to try to acquire it
* simultaneously from multiple threads on multiple main CPU cores and LP CPU.
*
* @note This function is private to ulp lp core critical section and shall not be called from anywhere else.
*
* @param lock Pointer to lock struct, shared with ULP
*/
static void ulp_lp_core_spinlock_acquire(ulp_lp_core_spinlock_t *lock)
{
/* Level index */
int lv = 0;
/* Candidate index */
int candidate = 0;
/* Index of the current lock candidate */
int lock_candidate_id = ulp_lp_core_spinlock_get_candidate_id();
for (lv = 0; lv < (int)LOCK_CANDIDATE_NUM_MAX - 1; lv++) {
/* Each candidate has to go through all the levels in order to get the spinlock. Start by notifying other candidates, we have reached level `lv` */
lock->level[lock_candidate_id] = lv;
/* Notify other candidates we are the latest one who entered level `lv` */
lock->last_to_enter[lv] = lock_candidate_id;
/* If there is any candidate that reached the same or a higher level than this candidate, wait for it to finish. Advance to the next level if another candidate becomes the latest one to arrive at our current level */
for (candidate = 0; candidate < (int)LOCK_CANDIDATE_NUM_MAX; candidate++) {
while ((candidate != lock_candidate_id) && (lock->level[candidate] >= lv && lock->last_to_enter[lv] == lock_candidate_id)) {
}
}
}
}
/**
* @brief Release the lock.
*
* @note This function is private to ulp lp core critical section and shall not be called from anywhere else.
*
* @param lock Pointer to lock struct, shared with ULP
*/
static void ulp_lp_core_spinlock_release(ulp_lp_core_spinlock_t *lock)
{
int lock_candidate_id = ulp_lp_core_spinlock_get_candidate_id();
lock->level[lock_candidate_id] = -1;
}
#endif
void ulp_lp_core_enter_critical(ulp_lp_core_spinlock_t *lock)
{
/* disable interrupt */
#if !IS_ULP_COCPU // HP core
unsigned prev_int_level = rv_utils_set_intlevel_regval(INT_MASK_THRESHOLD);
lock->prev_int_level = prev_int_level;
#else // LP core
ulp_lp_core_intr_disable();
#endif
/* Busy-wait to acquire the spinlock. Use caution when deploying this lock in time-sensitive scenarios. */
ulp_lp_core_spinlock_acquire(lock);
}
void ulp_lp_core_exit_critical(ulp_lp_core_spinlock_t *lock)
{
ulp_lp_core_spinlock_release(lock);
/* re-enable interrupt */
#if !IS_ULP_COCPU // HP core
unsigned prev_int_level = lock->prev_int_level;
rv_utils_restore_intlevel_regval(prev_int_level);
#else // LP core
ulp_lp_core_intr_enable();
#endif
}

View File

@ -19,6 +19,7 @@
#include "esp_wifi_types.h"
#include "esp_wpa3_i.h"
#include "esp_wps.h"
#include "esp_wps_i.h"
#define WIFI_PASSWORD_LEN_MAX 65
@ -236,6 +237,9 @@ bool hostap_deinit(void *data)
esp_wifi_unset_appie_internal(WIFI_APPIE_WPA);
esp_wifi_unset_appie_internal(WIFI_APPIE_ASSOC_RESP);
#ifdef CONFIG_WPS_REGISTRAR
wifi_ap_wps_disable_internal();
#endif
#ifdef CONFIG_SAE
wpa3_hostap_auth_deinit();
/* Wait till lock is released by wpa3 task */

View File

@ -167,22 +167,31 @@ int esp_handle_beacon_probe(u8 type, u8 *frame, size_t len, u8 *sender,
return 0;
}
#ifdef CONFIG_WNM
void get_scan_channel_bitmap(struct wpa_supplicant *wpa_s, wifi_scan_config_t *params)
static void get_scan_channel_bitmap(struct wpa_supplicant *wpa_s, wifi_scan_config_t *params)
{
const int MAX_2GHZ_CHANNEL = 14;
if (!wpa_s->wnm_num_neighbor_report) {
wpa_printf(MSG_DEBUG, "No Neighbor Report to gather scan channel list");
return;
}
params->channel_bitmap.ghz_2_channels = 0;
params->channel_bitmap.ghz_5_channels = 0;
for (int i = 0; i < wpa_s->wnm_num_neighbor_report; i++) {
struct neighbor_report *nei;
nei = &wpa_s->wnm_neighbor_report_elements[i];
params->channel_bitmap.ghz_2_channels |= (1 << nei->channel_number);
struct neighbor_report *nei = &wpa_s->wnm_neighbor_report_elements[i];
if (nei->channel_number <= MAX_2GHZ_CHANNEL) {
params->channel_bitmap.ghz_2_channels |= CHANNEL_TO_BIT(nei->channel_number);
} else {
params->channel_bitmap.ghz_5_channels |= CHANNEL_TO_BIT(nei->channel_number);
}
}
}
#endif /*CONFIG_WNM*/
static int issue_scan(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *scan_params)
{

View File

@ -367,16 +367,19 @@ int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data)
if (g_wpa3_hostap_evt_queue == NULL) {
WPA3_HOSTAP_AUTH_API_UNLOCK();
os_free(evt);
wpa_printf(MSG_DEBUG, "hostap evt queue NULL");
return ESP_FAIL;
}
} else {
os_free(evt);
wpa_printf(MSG_DEBUG, "g_wpa3_hostap_auth_api_lock not found");
return ESP_FAIL;
}
if (evt->id == SIG_WPA3_RX_CONFIRM || evt->id == SIG_TASK_DEL) {
/* prioritising confirm for completing handshake for committed sta */
if (os_queue_send_to_front(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
WPA3_HOSTAP_AUTH_API_UNLOCK();
wpa_printf(MSG_DEBUG, "failed to add msg to queue front");
os_free(evt);
return ESP_FAIL;
}
@ -384,6 +387,7 @@ int wpa3_hostap_post_evt(uint32_t evt_id, uint32_t data)
if (os_queue_send(g_wpa3_hostap_evt_queue, &evt, 0) != pdPASS) {
WPA3_HOSTAP_AUTH_API_UNLOCK();
os_free(evt);
wpa_printf(MSG_DEBUG, "failed to send msg to queue");
return ESP_FAIL;
}
}

View File

@ -72,6 +72,7 @@ void wifi_station_wps_msg_timeout(void *data, void *user_ctx);
void wifi_station_wps_eapol_start_handle(void *data, void *user_ctx);
void wifi_station_wps_success(void *data, void *user_ctx);
void wifi_station_wps_timeout(void *data, void *user_ctx);
int wps_delete_timer(void);
struct wps_sm *gWpsSm = NULL;
static wps_factory_information_t *s_factory_info = NULL;
@ -623,14 +624,14 @@ int wps_process_wps_mX_req(u8 *ubuf, int len, enum wps_process_res *res)
if (expd->opcode != WSC_Start) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d "
"in WAIT_START state", expd->opcode);
return ESP_FAIL;
return ESP_ERR_INVALID_STATE;
}
wpa_printf(MSG_DEBUG, "EAP-WSC: Received start");
sm->state = WPA_MESG;
} else if (expd->opcode == WSC_Start) {
wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d",
expd->opcode);
return ESP_FAIL;
return ESP_ERR_INVALID_STATE;
}
flag = *(u8 *)(ubuf + sizeof(struct eap_expand));
@ -834,7 +835,8 @@ int wps_finish(void)
if (sm->wps->state == WPS_FINISHED) {
wpa_printf(MSG_DEBUG, "wps finished------>");
wps_set_status(WPS_STATUS_SUCCESS);
wps_stop_connection_timers(sm);
/* WPS finished, dequeue all timers */
wps_delete_timer();
if (sm->ap_cred_cnt == 1) {
wifi_config_t *config = os_zalloc(sizeof(wifi_config_t));
@ -844,6 +846,7 @@ int wps_finish(void)
}
esp_wifi_get_config(WIFI_IF_STA, config);
esp_wifi_disconnect();
os_memcpy(config->sta.ssid, sm->creds[0].ssid, sm->creds[0].ssid_len);
os_memcpy(config->sta.password, sm->creds[0].key, sm->creds[0].key_len);
os_memcpy(config->sta.bssid, sm->bssid, ETH_ALEN);
@ -857,6 +860,7 @@ int wps_finish(void)
config->sta.bssid_set = 0;
config->sta.sae_pwe_h2e = 0;
esp_wifi_set_config(WIFI_IF_STA, config);
esp_wifi_connect();
os_free(config);
}
@ -1092,6 +1096,8 @@ int wps_sm_rx_eapol_internal(u8 *src_addr, u8 *buf, u32 len)
wpa_printf(MSG_DEBUG, "sm->wps->state = %d", sm->wps->state);
wps_start_msg_timer();
}
} else if (ret == ESP_ERR_INVALID_STATE) {
ret = ESP_OK;
} else {
ret = ESP_FAIL;
}
@ -1654,6 +1660,7 @@ wifi_wps_scan_done(void *arg, ETS_STATUS status)
esp_wifi_set_config(0, &wifi_config);
wpa_printf(MSG_DEBUG, "WPS: neg start");
wifi_config.sta.failure_retry_cnt = 2;
esp_wifi_connect();
sm->state = WAIT_START;
eloop_cancel_timeout(wifi_station_wps_msg_timeout, NULL, NULL);

View File

@ -138,3 +138,4 @@ static inline int wps_set_status(uint32_t status)
bool is_wps_enabled(void);
int wps_init_cfg_pin(struct wps_config *cfg);
void wifi_station_wps_eapol_start_handle(void *data, void *user_ctx);
int wifi_ap_wps_disable_internal(void);

View File

@ -299,6 +299,12 @@ examples/system/ulp/lp_core/gpio_intr_pulse_counter:
depends_components:
- ulp
examples/system/ulp/lp_core/inter_cpu_critical_section/:
enable:
- if: SOC_LP_CORE_SUPPORTED == 1
depends_components:
- ulp
examples/system/ulp/lp_core/interrupt:
enable:
- if: SOC_LP_CORE_SUPPORTED == 1

View File

@ -71,7 +71,8 @@ void app_main(void)
int64_t t2 = esp_timer_get_time();
ESP_LOGI(TAG, "Woke up from light sleep, time since boot: %lld us", t2);
assert(llabs((t2 - t1) - 500000) < 1200);
// TODO: PM-232
assert(((t2 - t1 - 500000) < 1000) && ((t2 - t1 - 500000) > -2000));
#endif
/* Let the timer run for a little bit more */

View File

@ -81,7 +81,7 @@ def test_esp_timer(dut: Dut) -> None:
logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format(
sleep_enter_time, sleep_exit_time, sleep_time))
assert abs(sleep_time - LIGHT_SLEEP_TIME) < 1200
assert -2000 < sleep_time - LIGHT_SLEEP_TIME < 1000
for i in range(5, 7):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)

View File

@ -62,5 +62,6 @@ def test_light_sleep(dut: Dut) -> None:
logging.info('Went to sleep again')
match = dut.expect(EXIT_SLEEP_REGEX)
assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 1 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1
# TODO: Need to support dynamically change retention overhead for chips which support pmu (PM-232)
assert match.group(1).decode('utf8') == 'timer' and int(match.group(3)) >= WAKEUP_INTERVAL_MS - 2 and int(match.group(3)) <= WAKEUP_INTERVAL_MS + 1
logging.info('Woke up from timer again')

View File

@ -0,0 +1,7 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
list(APPEND SDKCONFIG_DEFAULTS "sdkconfig.defaults")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(lp_inter_cpu_critical_section_example)

View File

@ -0,0 +1,34 @@
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
| ----------------- | -------- | -------- | -------- |
# LP Core simple example with inter-CPU critical section:
(See the README.md file in the upper level 'examples' directory for more information about examples.)
## Overview
This example demonstrates the use of an inter-CPU critical section to safeguard shared resources between the main program and the ULP (Ultra-Low-Power) processor.
In this example, a global shared counter `shared_cnt` is incremented by both the high-performance CPU (HP CPU) and the low-power CPU (LP CPU) in turn. To ensure mutual exclusion, a global inter-CPU spinlock is used. With this protection in place, both the HP and LP CPUs attempt to increment the shared counter 100,000 times each.
The inter-CPU critical section is implemented using a global spinlock of type ulp_lp_core_spinlock_t. This type of spinlock is especially designed to protect shared resources between main program and ULP program. It supports multiple threads to attempt to enter critical section simultaneously, while eventually only one thread can succeed. This spinlock must be declared within the ULP program and shall be initialized in either the main program or the ULP program before using it. Note that this critical section doesn't support nested entering and exiting.
## How to use this example
### Build and Flash
Enter `idf.py -p PORT flash monitor` to build, flash and monitor the project.
(To exit the serial monitor, type ``Ctrl-]``.)
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
To observe the mutual exclusion between HP and LP CPUs straight forward, the output of LP CPU is routed to HP CPUs console.
## Example output
```
LP CPU's increment starts, shared counter = 0
core 0 started, cnt = 5868
HP CPU's increment ends, shared counter = 165882
LP CPU's increment ends, shared counter = 250000
...
```

View File

@ -0,0 +1,24 @@
# Register the component
idf_component_register(SRCS "lp_inter_cpu_critical_section_main.c"
INCLUDE_DIRS ""
REQUIRES ulp)
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The LP Core app name must be unique (if multiple components use LP Core).
set(ulp_app_name lp_core_${COMPONENT_NAME})
#
# 2. Specify all C files.
# Files should be placed into a separate directory (in this case, lp_core/),
# which should not be added to COMPONENT_SRCS.
set(ulp_lp_core_sources "lp_core/main.c")
#
# 3. List all the component source files which include automatically
# generated LP Core export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "lp_inter_cpu_critical_section_main..c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} "${ulp_lp_core_sources}" "${ulp_exp_dep_srcs}")

View File

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_lp_core_print.h"
#include "ulp_lp_core_utils.h"
#include "ulp_lp_core_critical_section_shared.h"
volatile uint32_t shared_cnt = 0;
ulp_lp_core_spinlock_t lp_spinlock;
int main (void)
{
/* Initialize the inter-processor spinlock. This must be done on either of HP core and LP core */
ulp_lp_core_spinlock_init(&lp_spinlock);
/* Delay 10ms in case of interleaved console output */
ulp_lp_core_delay_us(10000);
lp_core_printf("LP CPU's increment starts, shared counter = %d\r\n", shared_cnt);
for (int i = 0; i < 100000; i++) {
ulp_lp_core_enter_critical(&lp_spinlock);
shared_cnt++;
ulp_lp_core_exit_critical(&lp_spinlock);
}
lp_core_printf("LP CPU's increment ends, shared counter = %d\r\n", shared_cnt);
return 0;
}

View File

@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "lp_core_main.h"
#include "ulp_lp_core.h"
#include "freertos/FreeRTOS.h"
#include "ulp_lp_core_critical_section_shared.h"
extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_main_bin_start");
extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_main_bin_end");
static void lp_core_init(void)
{
/* Set LP core wakeup source as the HP CPU */
ulp_lp_core_cfg_t cfg = {
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
.lp_timer_sleep_duration_us = 10000,
};
/* Load LP core firmware */
ESP_ERROR_CHECK(ulp_lp_core_load_binary(lp_core_main_bin_start, (lp_core_main_bin_end - lp_core_main_bin_start)));
/* Run LP core */
ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));
printf("LP core loaded with firmware and running successfully\n");
}
static void inc_num_spinlock_iter(void *arg)
{
int core_id = esp_cpu_get_core_id();
/* Delay 100ms in case of interleaved console output and ensure LP CPU starts first */
vTaskDelay(pdMS_TO_TICKS(100));
printf("core %d started, cnt = %ld\n", core_id, ulp_shared_cnt);
for (int i = 0; i < 100000; i++) {
ulp_lp_core_enter_critical((ulp_lp_core_spinlock_t*)&ulp_lp_spinlock);
ulp_shared_cnt++;
ulp_lp_core_exit_critical((ulp_lp_core_spinlock_t*)&ulp_lp_spinlock);
}
printf("HP CPU's increment ends, shared counter = %ld\n", ulp_shared_cnt);
vTaskDelete(NULL);
}
void app_main(void)
{
/* If user is using USB-serial-jtag then idf monitor needs some time to
* re-connect to the USB port. We wait 1 sec here to allow for it to make the reconnection
* before we print anything. Otherwise the chip will go back to sleep again before the user
* has time to monitor any output.
*/
/* Load LP Core binary and start the coprocessor */
lp_core_init();
// create tasks on each core which would be accessing a shared resource protected by spinlock
for (int core_id = 0; core_id < CONFIG_FREERTOS_NUMBER_OF_CORES; core_id++) {
xTaskCreatePinnedToCore(inc_num_spinlock_iter, NULL, 4096, NULL, 3, NULL, core_id);
}
}

View File

@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.esp32c5
@pytest.mark.esp32c6
@pytest.mark.generic
def test_lp_core_critical_section_main_1_task(dut: Dut) -> None:
dut.expect("LP CPU's increment starts, shared counter = 0")
dut.expect(r'core 0 started, cnt = \d+')
# Either LP and HP can stop increasing earlier
dut.expect('increment ends, shared counter = 200000')
@pytest.mark.esp32p4
@pytest.mark.generic
def test_lp_core_critical_section_main_2_tasks(dut: Dut) -> None:
dut.expect("LP CPU's increment starts, shared counter = 0")
dut.expect(r'core 0 started, cnt = \d+')
dut.expect(r'core 1 started, cnt = \d+')
# Either LP and HP can stop increasing earlier
dut.expect('increment ends, shared counter = 300000')

View File

@ -0,0 +1,11 @@
# Enable LP Core
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_TYPE_LP_CORE=y
CONFIG_ULP_COPROC_RESERVE_MEM=8192
# Route LP Core output to HP
CONFIG_ULP_PANIC_OUTPUT_ENABLE=y
CONFIG_ULP_HP_UART_CONSOLE_PRINT=y
# Extend Task Watchdog timeout period to 10 seconds
CONFIG_ESP_TASK_WDT_TIMEOUT_S=10

View File

@ -57,12 +57,22 @@ examples/wifi/itwt:
examples/wifi/power_save:
<<: *wifi_depends_default
disable:
- if: (SOC_WIFI_SUPPORTED != 1)
- if: SOC_WIFI_SUPPORTED != 1
- if: IDF_TARGET in ["esp32c61"]
temporary: true
reason: PM-234
disable_test:
- if: IDF_TARGET == "esp32c61"
temporary: true
reason: lack of runners
depends_components:
- esp_wifi
- esp_phy
- esp_netif
- lwip
- esp_event
- esp_coex
- wpa_supplicant
- esp_driver_uart
examples/wifi/wifi_aware:

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- |
# Wifi Power Save Example

View File

@ -628,13 +628,14 @@ def test_panic_delay(dut: PanicTestDut) -> None:
#########################
# Memprot-related tests are supported only on targets with PMS/PMA peripheral;
# currently ESP32-S2, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-C6, ESP32-P4 and ESP32-C5 are supported
# currently ESP32-S2, ESP32-C3, ESP32-C2, ESP32-H2, ESP32-C6, ESP32-P4, ESP32-C5 and ESP32-C61 are supported
CONFIGS_MEMPROT_IDRAM = [
pytest.param('memprot_esp32s2', marks=[pytest.mark.esp32s2]),
pytest.param('memprot_esp32c3', marks=[pytest.mark.esp32c3]),
pytest.param('memprot_esp32c2', marks=[pytest.mark.esp32c2]),
pytest.param('memprot_esp32c5', marks=[pytest.mark.esp32c5]),
pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]),
pytest.param('memprot_esp32c61', marks=[pytest.mark.esp32c61]),
pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]),
pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4])
]
@ -659,6 +660,7 @@ CONFIGS_MEMPROT_RTC_SLOW_MEM = [
CONFIGS_MEMPROT_FLASH_IDROM = [
pytest.param('memprot_esp32c5', marks=[pytest.mark.esp32c5]),
pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]),
pytest.param('memprot_esp32c61', marks=[pytest.mark.esp32c61]),
pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]),
pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4])
]
@ -666,6 +668,7 @@ CONFIGS_MEMPROT_FLASH_IDROM = [
CONFIGS_MEMPROT_INVALID_REGION_PROTECTION_USING_PMA = [
pytest.param('memprot_esp32c5', marks=[pytest.mark.esp32c5]),
pytest.param('memprot_esp32c6', marks=[pytest.mark.esp32c6]),
pytest.param('memprot_esp32c61', marks=[pytest.mark.esp32c61]),
pytest.param('memprot_esp32h2', marks=[pytest.mark.esp32h2]),
pytest.param('memprot_esp32p4', marks=[pytest.mark.esp32p4])
]
@ -704,7 +707,7 @@ def test_iram_reg1_write_violation(dut: PanicTestDut, test_func_name: str) -> No
dut.expect_backtrace()
elif dut.target == 'esp32c3':
dut.expect_exact(r'Test error: Test function has returned')
elif dut.target in ['esp32c2', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4']:
else:
dut.expect_gme('Store access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
@ -729,7 +732,7 @@ def test_iram_reg2_write_violation(dut: PanicTestDut, test_func_name: str) -> No
dut.expect(r' operation type: (\S+)')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
elif dut.target in ['esp32c2', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4']:
else:
dut.expect_gme('Store access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
@ -754,7 +757,7 @@ def test_iram_reg3_write_violation(dut: PanicTestDut, test_func_name: str) -> No
dut.expect(r' operation type: (\S+)')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
elif dut.target in ['esp32c2', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4']:
else:
dut.expect_gme('Store access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
@ -781,7 +784,7 @@ def test_iram_reg4_write_violation(dut: PanicTestDut, test_func_name: str) -> No
dut.expect(r' operation type: (\S+)')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
elif dut.target in ['esp32c2', 'esp32c6', 'eps32h2']:
else:
dut.expect_gme('Store access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
@ -801,7 +804,7 @@ def test_dram_reg1_execute_violation(dut: PanicTestDut, test_func_name: str) ->
dut.expect(r'Unknown operation at address [0-9xa-f]+ not permitted \((\S+)\)')
dut.expect_reg_dump(0)
dut.expect_backtrace(corrupted=True)
elif dut.target in ['esp32c3', 'esp32c2', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4']:
else:
dut.expect_gme('Instruction access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
@ -820,7 +823,7 @@ def test_dram_reg2_execute_violation(dut: PanicTestDut, test_func_name: str) ->
dut.expect_gme('InstructionFetchError')
dut.expect_reg_dump(0)
dut.expect_backtrace(corrupted=True)
elif dut.target in ['esp32c3', 'esp32c2', 'esp32c5', 'esp32c6', 'esp32h2', 'esp32p4']:
else:
dut.expect_gme('Instruction access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
@ -876,7 +879,7 @@ def test_rtc_fast_reg3_execute_violation(dut: PanicTestDut, test_func_name: str)
dut.expect(r' operation type: (\S+)')
dut.expect_reg_dump(0)
dut.expect_stack_dump()
elif dut.target in ['esp32c5', 'esp32c6', 'esp32h2', 'esp32p4']:
else:
dut.expect_gme('Instruction access fault')
dut.expect_reg_dump(0)
dut.expect_stack_dump()