mirror of
https://github.com/espressif/esp-idf.git
synced 2025-10-02 18:10:57 +02:00
change(esp_hw_support): update sleep cpu flow
This commit is contained in:
@@ -97,10 +97,10 @@ static void * cache_sleep_frame_init(void)
|
|||||||
static void * clint_sleep_frame_init(void)
|
static void * clint_sleep_frame_init(void)
|
||||||
{
|
{
|
||||||
const static cpu_domain_dev_regs_region_t regions[] = {
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
{ .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_SIP_REG + 4 },
|
{ .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 },
|
||||||
{ .start = CLINT_MINT_MTIMECMP_L_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 },
|
{ .start = CPU_DOMAIN_DEV_START_ADDR1, .end = CPU_DOMAIN_DEV_END_ADDR1 },
|
||||||
{ .start = CLINT_MINT_TIMECTL_REG, .end = CLINT_MINT_TIMECTL_REG + 4 },
|
{ .start = CPU_DOMAIN_DEV_START_ADDR2, .end = CPU_DOMAIN_DEV_END_ADDR2 },
|
||||||
{ .start = CLINT_MINT_MTIME_L_REG, .end = CLINT_MINT_MTIME_H_REG + 4 }
|
{ .start = CPU_DOMAIN_DEV_START_ADDR3, .end = CPU_DOMAIN_DEV_END_ADDR3 }
|
||||||
};
|
};
|
||||||
static uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(4)] __attribute__((aligned(4)));
|
static uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(4)] __attribute__((aligned(4)));
|
||||||
return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame);
|
return cpu_domain_dev_sleep_frame_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame);
|
||||||
|
@@ -162,7 +162,6 @@ STRUCT_BEGIN
|
|||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG2, pmpcfg2)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG3, pmpcfg3)
|
||||||
|
|
||||||
#if SOC_CPU_HAS_PMA
|
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR0, pmaaddr0)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR0, pmaaddr0)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR1, pmaaddr1)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR1, pmaaddr1)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR2, pmaaddr2)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMAADDR2, pmaaddr2)
|
||||||
@@ -195,7 +194,6 @@ STRUCT_BEGIN
|
|||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG13, pmacfg13)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG13, pmacfg13)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG14, pmacfg14)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG14, pmacfg14)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG15, pmacfg15)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMACFG15, pmacfg15)
|
||||||
#endif // SOC_CPU_HAS_PMA
|
|
||||||
|
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCYCLE, mcycle)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCYCLE, mcycle)
|
||||||
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVT, mtvt)
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVT, mtvt)
|
||||||
|
@@ -12,86 +12,44 @@
|
|||||||
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_check.h"
|
#include "esp_check.h"
|
||||||
|
#include "esp_ipc_isr.h"
|
||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_crc.h"
|
#include "esp_rom_crc.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
#include "riscv/csr.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
|
#include "soc/intpri_reg.h"
|
||||||
|
#include "soc/cache_reg.h"
|
||||||
|
#include "soc/clint_reg.h"
|
||||||
|
#include "soc/clic_reg.h"
|
||||||
|
#include "soc/pcr_reg.h"
|
||||||
|
#include "soc/rtc_periph.h"
|
||||||
|
#include "esp_private/esp_pmu.h"
|
||||||
#include "esp_private/sleep_cpu.h"
|
#include "esp_private/sleep_cpu.h"
|
||||||
#include "esp_private/sleep_event.h"
|
#include "esp_private/sleep_event.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if SOC_PMU_SUPPORTED
|
#include "esp32h4/rom/rtc.h"
|
||||||
#include "esp_private/esp_pmu.h"
|
#include "esp32h4/rom/cache.h"
|
||||||
#else
|
#include "rvsleep-frames.h"
|
||||||
#include "hal/rtc_hal.h"
|
#include "sleep_cpu_retention.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||||
#include "esp_private/system_internal.h"
|
#include "esp_private/system_internal.h"
|
||||||
#include "hal/clk_gate_ll.h"
|
|
||||||
#include "hal/uart_hal.h"
|
#include "hal/uart_hal.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "soc/rtc_periph.h"
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
#include "esp32h4/rom/rtc.h"
|
|
||||||
#include "rvsleep-frames.h"
|
|
||||||
#include "soc/intpri_reg.h"
|
|
||||||
#include "soc/cache_reg.h"
|
|
||||||
#include "soc/clint_reg.h"
|
|
||||||
#include "esp32h4/rom/cache.h"
|
|
||||||
#include "esp_ipc_isr.h"
|
|
||||||
#include "soc/pcr_reg.h"
|
|
||||||
|
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
|
||||||
#include <stdatomic.h>
|
|
||||||
#include "soc/hp_system_reg.h"
|
|
||||||
typedef enum {
|
|
||||||
SMP_IDLE,
|
|
||||||
SMP_BACKUP_START,
|
|
||||||
SMP_BACKUP_DONE,
|
|
||||||
SMP_RESTORE_START,
|
|
||||||
SMP_RESTORE_DONE,
|
|
||||||
SMP_SKIP_RETENTION,
|
|
||||||
} smp_retention_state_t;
|
|
||||||
|
|
||||||
static DRAM_ATTR smp_retention_state_t s_smp_retention_state[portNUM_PROCESSORS];
|
static DRAM_ATTR smp_retention_state_t s_smp_retention_state[portNUM_PROCESSORS];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static __attribute__((unused)) const char *TAG = "sleep";
|
static __attribute__((unused)) const char *TAG = "sleep";
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t start;
|
|
||||||
uint32_t end;
|
|
||||||
} cpu_domain_dev_regs_region_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
cpu_domain_dev_regs_region_t *region;
|
|
||||||
int region_num;
|
|
||||||
uint32_t *regs_frame;
|
|
||||||
} cpu_domain_dev_sleep_frame_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal structure which holds all requested light sleep cpu retention parameters
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
struct {
|
|
||||||
RvCoreCriticalSleepFrame *critical_frame[portNUM_PROCESSORS];
|
|
||||||
RvCoreNonCriticalSleepFrame *non_critical_frame[portNUM_PROCESSORS];
|
|
||||||
cpu_domain_dev_sleep_frame_t *cache_config_frame;
|
|
||||||
cpu_domain_dev_sleep_frame_t *clint_frame[portNUM_PROCESSORS];
|
|
||||||
cpu_domain_dev_sleep_frame_t *clic_frame[portNUM_PROCESSORS];
|
|
||||||
} retent;
|
|
||||||
} sleep_cpu_retention_t;
|
|
||||||
|
|
||||||
static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
||||||
|
|
||||||
|
|
||||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
|
||||||
|
|
||||||
#define CUSTOM_CSR_MTVT (0x307)
|
#define CUSTOM_CSR_MTVT (0x307)
|
||||||
#define CUSTOM_CSR_MNXTI (0x345)
|
#define CUSTOM_CSR_MNXTI (0x345)
|
||||||
#define CUSTOM_CSR_MINTTHRESH (0x347)
|
#define CUSTOM_CSR_MINTTHRESH (0x347)
|
||||||
@@ -107,155 +65,14 @@ static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
|||||||
|
|
||||||
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||||
|
|
||||||
static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num)
|
FORCE_INLINE_ATTR uint32_t save_mstatus_and_disable_global_int(void)
|
||||||
{
|
{
|
||||||
const int region_sz = sizeof(cpu_domain_dev_regs_region_t) * region_num;
|
return RV_READ_MSTATUS_AND_DISABLE_INTR();
|
||||||
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(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
|
||||||
if (frame) {
|
|
||||||
cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t));
|
|
||||||
memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t));
|
|
||||||
void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz;
|
|
||||||
memset(regs_frame, 0, regs_frame_sz);
|
|
||||||
*(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) {
|
|
||||||
.region = region,
|
|
||||||
.region_num = region_num,
|
|
||||||
.regs_frame = (uint32_t *)regs_frame
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void)
|
FORCE_INLINE_ATTR void restore_mstatus(uint32_t mstatus_val)
|
||||||
{
|
{
|
||||||
const static cpu_domain_dev_regs_region_t regions[] = {
|
RV_WRITE_CSR(mstatus, mstatus_val);
|
||||||
{ .start = CACHE_L1_ICACHE_CTRL_REG, .end = CACHE_L1_DCACHE_CTRL_REG + 4 },
|
|
||||||
{ .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 }
|
|
||||||
};
|
|
||||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(uint8_t core_id)
|
|
||||||
{
|
|
||||||
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = {
|
|
||||||
[0 ... portNUM_PROCESSORS - 1] = {
|
|
||||||
{ .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_SIP_REG + 4 },
|
|
||||||
{ .start = CLINT_MINT_MTIMECMP_L_REG, .end = CLINT_MINT_TIMECTL_REG + 4 },
|
|
||||||
{ .start = CLINT_MINT_MTIME_L_REG, .end = CLINT_MINT_MTIME_H_REG + 4 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(cpu_domain_dev_regs_region_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id)
|
|
||||||
{
|
|
||||||
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][4] = {
|
|
||||||
[0 ... portNUM_PROCESSORS - 1] = {
|
|
||||||
{ .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 },
|
|
||||||
{ .start = CLIC_INT_CTRL_REG(3), .end = CLIC_INT_CTRL_REG(3) + 4 },
|
|
||||||
{ .start = CLIC_INT_CTRL_REG(7), .end = CLIC_INT_CTRL_REG(7) + 4 },
|
|
||||||
{ .start = CLIC_INT_CTRL_REG(16), .end = CLIC_INT_CTRL_REG(47) + 4 },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(cpu_domain_dev_regs_region_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t esp_sleep_cpu_retention_init_impl(void)
|
|
||||||
{
|
|
||||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
|
||||||
if (s_cpu_retention.retent.critical_frame[core_id] == NULL) {
|
|
||||||
void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
|
||||||
if (frame == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
s_cpu_retention.retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
|
||||||
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.non_critical_frame[core_id] == NULL) {
|
|
||||||
void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
|
||||||
if (frame == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
s_cpu_retention.retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame;
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.clic_frame[core_id] == NULL) {
|
|
||||||
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
|
||||||
if (frame == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
s_cpu_retention.retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.clint_frame[core_id] == NULL) {
|
|
||||||
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id);
|
|
||||||
if (frame == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
s_cpu_retention.retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.cache_config_frame == NULL) {
|
|
||||||
void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init();
|
|
||||||
if (frame == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
s_cpu_retention.retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
|
||||||
}
|
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
|
||||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
|
||||||
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return ESP_OK;
|
|
||||||
err:
|
|
||||||
esp_sleep_cpu_retention_deinit();
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t esp_sleep_cpu_retention_deinit_impl(void)
|
|
||||||
{
|
|
||||||
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
|
||||||
if (s_cpu_retention.retent.critical_frame[core_id]) {
|
|
||||||
heap_caps_free((void *)s_cpu_retention.retent.critical_frame[core_id]);
|
|
||||||
s_cpu_retention.retent.critical_frame[core_id] = NULL;
|
|
||||||
rv_core_critical_regs_frame[core_id] = NULL;
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.non_critical_frame[core_id]) {
|
|
||||||
heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame[core_id]);
|
|
||||||
s_cpu_retention.retent.non_critical_frame[core_id] = NULL;
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.clic_frame[core_id]) {
|
|
||||||
heap_caps_free((void *)s_cpu_retention.retent.clic_frame[core_id]);
|
|
||||||
s_cpu_retention.retent.clic_frame[core_id] = NULL;
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.clint_frame[core_id]) {
|
|
||||||
heap_caps_free((void *)s_cpu_retention.retent.clint_frame[core_id]);
|
|
||||||
s_cpu_retention.retent.clint_frame[core_id] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (s_cpu_retention.retent.cache_config_frame) {
|
|
||||||
heap_caps_free((void *)s_cpu_retention.retent.cache_config_frame);
|
|
||||||
s_cpu_retention.retent.cache_config_frame = NULL;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline IRAM_ATTR uint32_t save_mstatus_and_disable_global_int(void)
|
|
||||||
{
|
|
||||||
uint32_t mstatus;
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"csrr %0, mstatus\n"
|
|
||||||
"csrci mstatus, 0x8\n"
|
|
||||||
: "=r"(mstatus)
|
|
||||||
);
|
|
||||||
return mstatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline IRAM_ATTR void restore_mstatus(uint32_t mstatus)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__ ("csrw mstatus, %0\n" :: "r"(mstatus));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
|
static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
|
||||||
@@ -313,7 +130,6 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi
|
|||||||
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
|
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
|
||||||
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
|
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
|
||||||
|
|
||||||
#if SOC_CPU_HAS_PMA
|
|
||||||
frame->pmaaddr0 = RV_READ_CSR(CSR_PMAADDR(0));
|
frame->pmaaddr0 = RV_READ_CSR(CSR_PMAADDR(0));
|
||||||
frame->pmaaddr1 = RV_READ_CSR(CSR_PMAADDR(1));
|
frame->pmaaddr1 = RV_READ_CSR(CSR_PMAADDR(1));
|
||||||
frame->pmaaddr2 = RV_READ_CSR(CSR_PMAADDR(2));
|
frame->pmaaddr2 = RV_READ_CSR(CSR_PMAADDR(2));
|
||||||
@@ -346,7 +162,6 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi
|
|||||||
frame->pmacfg13 = RV_READ_CSR(CSR_PMACFG(13));
|
frame->pmacfg13 = RV_READ_CSR(CSR_PMACFG(13));
|
||||||
frame->pmacfg14 = RV_READ_CSR(CSR_PMACFG(14));
|
frame->pmacfg14 = RV_READ_CSR(CSR_PMACFG(14));
|
||||||
frame->pmacfg15 = RV_READ_CSR(CSR_PMACFG(15));
|
frame->pmacfg15 = RV_READ_CSR(CSR_PMACFG(15));
|
||||||
#endif // SOC_CPU_HAS_PMA
|
|
||||||
|
|
||||||
frame->mcycle = RV_READ_CSR(mcycle);
|
frame->mcycle = RV_READ_CSR(mcycle);
|
||||||
frame->mtvt = RV_READ_CSR(CUSTOM_CSR_MTVT);
|
frame->mtvt = RV_READ_CSR(CUSTOM_CSR_MTVT);
|
||||||
@@ -414,7 +229,6 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
|
|||||||
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
|
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
|
||||||
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
|
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
|
||||||
|
|
||||||
#if SOC_CPU_HAS_PMA
|
|
||||||
RV_WRITE_CSR(CSR_PMAADDR(0), frame->pmaaddr0);
|
RV_WRITE_CSR(CSR_PMAADDR(0), frame->pmaaddr0);
|
||||||
RV_WRITE_CSR(CSR_PMAADDR(1), frame->pmaaddr1);
|
RV_WRITE_CSR(CSR_PMAADDR(1), frame->pmaaddr1);
|
||||||
RV_WRITE_CSR(CSR_PMAADDR(2), frame->pmaaddr2);
|
RV_WRITE_CSR(CSR_PMAADDR(2), frame->pmaaddr2);
|
||||||
@@ -447,7 +261,6 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
|
|||||||
RV_WRITE_CSR(CSR_PMACFG(13), frame->pmacfg13);
|
RV_WRITE_CSR(CSR_PMACFG(13), frame->pmacfg13);
|
||||||
RV_WRITE_CSR(CSR_PMACFG(14), frame->pmacfg14);
|
RV_WRITE_CSR(CSR_PMACFG(14), frame->pmacfg14);
|
||||||
RV_WRITE_CSR(CSR_PMACFG(15), frame->pmacfg15);
|
RV_WRITE_CSR(CSR_PMACFG(15), frame->pmacfg15);
|
||||||
#endif //SOC_CPU_HAS_PMA
|
|
||||||
|
|
||||||
RV_WRITE_CSR(mcycle, frame->mcycle);
|
RV_WRITE_CSR(mcycle, frame->mcycle);
|
||||||
|
|
||||||
@@ -491,12 +304,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *
|
|||||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||||
static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||||
{
|
{
|
||||||
*(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size);
|
*(frame_crc_ptr) = esp_rom_crc32_le(0, (void *)frame_ptr, frame_check_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
|
||||||
{
|
{
|
||||||
if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){
|
if(*(frame_crc_ptr) != esp_rom_crc32_le(0, (void *)(frame_ptr), frame_check_size)){
|
||||||
// resume uarts
|
// resume uarts
|
||||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
||||||
@@ -522,7 +335,11 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
|||||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||||
{
|
{
|
||||||
__attribute__((unused)) uint8_t core_id = esp_cpu_get_core_id();
|
__attribute__((unused)) uint8_t core_id = esp_cpu_get_core_id();
|
||||||
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
|
/* mstatus is core privated CSR, do it near the core critical regs restore */
|
||||||
|
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
||||||
|
rv_core_critical_regs_save();
|
||||||
|
|
||||||
|
RvCoreCriticalSleepFrame * frame = s_cpu_retention.retent.critical_frame[core_id];
|
||||||
if ((frame->pmufunc & 0x3) == 0x1) {
|
if ((frame->pmufunc & 0x3) == 0x1) {
|
||||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0);
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0);
|
||||||
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
|
||||||
@@ -531,7 +348,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
|||||||
#endif
|
#endif
|
||||||
REG_WRITE(RTC_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
REG_WRITE(RTC_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
||||||
|
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE);
|
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE);
|
||||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_BACKUP_DONE) {
|
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_BACKUP_DONE) {
|
||||||
;
|
;
|
||||||
@@ -545,7 +362,7 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
|
|||||||
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
restore_mstatus(mstatus);
|
||||||
return pmu_sleep_finish(dslp);
|
return pmu_sleep_finish(dslp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,9 +370,8 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
|
|||||||
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||||
{
|
{
|
||||||
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0);
|
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0);
|
||||||
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
|
||||||
uint8_t core_id = esp_cpu_get_core_id();
|
uint8_t core_id = esp_cpu_get_core_id();
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START);
|
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -576,7 +392,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
|
|||||||
validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
// Start core1
|
// Start core1
|
||||||
if (core_id == 0) {
|
if (core_id == 0) {
|
||||||
REG_SET_BIT(PCR_CORE1_CONF_REG, PCR_CORE1_CLK_EN);
|
REG_SET_BIT(PCR_CORE1_CONF_REG, PCR_CORE1_CLK_EN);
|
||||||
@@ -590,38 +406,27 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
|
|||||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame);
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame);
|
||||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]);
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]);
|
||||||
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame[core_id]);
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame[core_id]);
|
||||||
restore_mstatus(mstatus);
|
|
||||||
|
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE);
|
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE);
|
||||||
#endif
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
|
||||||
|
|
||||||
|
|
||||||
#if SOC_PM_SUPPORT_CPU_PD
|
|
||||||
|
|
||||||
esp_err_t esp_sleep_cpu_retention_init(void)
|
esp_err_t esp_sleep_cpu_retention_init(void)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
#if SOC_PM_CPU_RETENTION_BY_SW
|
return esp_sleep_cpu_retention_init_impl(& s_cpu_retention, s_smp_retention_state);
|
||||||
err = esp_sleep_cpu_retention_init_impl();
|
#else
|
||||||
|
return esp_sleep_cpu_retention_init_impl(& s_cpu_retention);
|
||||||
#endif
|
#endif
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_sleep_cpu_retention_deinit(void)
|
esp_err_t esp_sleep_cpu_retention_deinit(void)
|
||||||
{
|
{
|
||||||
esp_err_t err = ESP_OK;
|
return esp_sleep_cpu_retention_deinit_impl(& s_cpu_retention);
|
||||||
#if SOC_PM_CPU_RETENTION_BY_SW
|
|
||||||
err = esp_sleep_cpu_retention_deinit_impl();
|
|
||||||
#endif
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool cpu_domain_pd_allowed(void)
|
bool cpu_domain_pd_allowed(void)
|
||||||
{
|
{
|
||||||
bool allowed = true;
|
bool allowed = true;
|
||||||
@@ -639,7 +444,7 @@ bool cpu_domain_pd_allowed(void)
|
|||||||
|
|
||||||
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
||||||
{
|
{
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||||
if (light_sleep_enable) {
|
if (light_sleep_enable) {
|
||||||
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
|
||||||
} else {
|
} else {
|
||||||
@@ -649,10 +454,8 @@ esp_err_t sleep_cpu_configure(bool light_sleep_enable)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !CONFIG_FREERTOS_UNICORE
|
#if !CONFIG_FREERTOS_UNICORE
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||||
static IRAM_ATTR void smp_core_do_retention(void)
|
static IRAM_ATTR void smp_core_do_retention(void)
|
||||||
{
|
{
|
||||||
uint8_t core_id = esp_cpu_get_core_id();
|
uint8_t core_id = esp_cpu_get_core_id();
|
||||||
@@ -726,7 +529,7 @@ IRAM_ATTR void esp_sleep_cpu_skip_retention(void) {
|
|||||||
|
|
||||||
void sleep_smp_cpu_sleep_prepare(void)
|
void sleep_smp_cpu_sleep_prepare(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||||
while (atomic_load(&s_smp_retention_state[!esp_cpu_get_core_id()]) != SMP_IDLE) {
|
while (atomic_load(&s_smp_retention_state[!esp_cpu_get_core_id()]) != SMP_IDLE) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -738,7 +541,7 @@ void sleep_smp_cpu_sleep_prepare(void)
|
|||||||
|
|
||||||
void sleep_smp_cpu_wakeup_prepare(void)
|
void sleep_smp_cpu_wakeup_prepare(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
|
#if ESP_SLEEP_POWER_DOWN_CPU
|
||||||
uint8_t core_id = esp_cpu_get_core_id();
|
uint8_t core_id = esp_cpu_get_core_id();
|
||||||
if (atomic_load(&s_smp_retention_state[core_id]) == SMP_RESTORE_DONE) {
|
if (atomic_load(&s_smp_retention_state[core_id]) == SMP_RESTORE_DONE) {
|
||||||
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_RESTORE_DONE) {
|
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_RESTORE_DONE) {
|
||||||
|
@@ -6,14 +6,11 @@
|
|||||||
|
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "rvsleep-frames.h"
|
#include "rvsleep-frames.h"
|
||||||
#include "soc/soc_caps.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "freertos/FreeRTOSConfig.h"
|
#include "freertos/FreeRTOSConfig.h"
|
||||||
#define MTVT (0x307)
|
#include "sdkconfig.h"
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5 && !CONFIG_IDF_TARGET_ESP32H4
|
|
||||||
#include "soc/lp_aon_reg.h"
|
#include "soc/cache_reg.h"
|
||||||
#include "soc/extmem_reg.h"
|
#define CACHE_MAP_L1_CACHE_MASK (BIT(0) | BIT(1) | BIT(4))
|
||||||
#endif
|
|
||||||
|
|
||||||
.section .data1,"aw"
|
.section .data1,"aw"
|
||||||
.global rv_core_critical_regs_frame
|
.global rv_core_critical_regs_frame
|
||||||
@@ -24,6 +21,7 @@ rv_core_critical_regs_frame:
|
|||||||
.word 0
|
.word 0
|
||||||
.endr
|
.endr
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
This assembly subroutine is used to save the critical registers of the CPU
|
This assembly subroutine is used to save the critical registers of the CPU
|
||||||
@@ -65,7 +63,6 @@ rv_core_critical_regs_save:
|
|||||||
*/
|
*/
|
||||||
mv a0, t0
|
mv a0, t0
|
||||||
sw a0, RV_SLP_CTX_A0(t0)
|
sw a0, RV_SLP_CTX_A0(t0)
|
||||||
|
|
||||||
sw a1, RV_SLP_CTX_A1(t0)
|
sw a1, RV_SLP_CTX_A1(t0)
|
||||||
sw a2, RV_SLP_CTX_A2(t0)
|
sw a2, RV_SLP_CTX_A2(t0)
|
||||||
sw a3, RV_SLP_CTX_A3(t0)
|
sw a3, RV_SLP_CTX_A3(t0)
|
||||||
@@ -120,30 +117,6 @@ rv_core_critical_regs_save:
|
|||||||
mv t3, t0
|
mv t3, t0
|
||||||
csrr t0, mscratch
|
csrr t0, mscratch
|
||||||
sw t0, RV_SLP_CTX_T0(t3)
|
sw t0, RV_SLP_CTX_T0(t3)
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C6 && !CONFIG_IDF_TARGET_ESP32H2 && !CONFIG_IDF_TARGET_ESP32C5 && !CONFIG_IDF_TARGET_ESP32H4
|
|
||||||
/* writeback dcache is required here!!! */
|
|
||||||
la t0, EXTMEM_CACHE_SYNC_MAP_REG
|
|
||||||
li t1, 0x10
|
|
||||||
sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */
|
|
||||||
la t2, EXTMEM_CACHE_SYNC_ADDR_REG
|
|
||||||
sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */
|
|
||||||
la t0, EXTMEM_CACHE_SYNC_SIZE_REG
|
|
||||||
sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */
|
|
||||||
|
|
||||||
la t1, EXTMEM_CACHE_SYNC_CTRL_REG
|
|
||||||
lw t2, 0x0(t1)
|
|
||||||
ori t2, t2, 0x4
|
|
||||||
sw t2, 0x0(t1)
|
|
||||||
|
|
||||||
li t0, 0x10 /* SYNC_DONE bit */
|
|
||||||
wait_sync_done:
|
|
||||||
lw t2, 0x0(t1)
|
|
||||||
and t2, t0, t2
|
|
||||||
beqz t2, wait_sync_done
|
|
||||||
#endif
|
|
||||||
|
|
||||||
lw t0, RV_SLP_CTX_T0(t3)
|
|
||||||
lw t1, RV_SLP_CTX_T1(t3)
|
lw t1, RV_SLP_CTX_T1(t3)
|
||||||
lw t2, RV_SLP_CTX_T2(t3)
|
lw t2, RV_SLP_CTX_T2(t3)
|
||||||
lw t3, RV_SLP_CTX_T3(t3)
|
lw t3, RV_SLP_CTX_T3(t3)
|
||||||
@@ -152,14 +125,6 @@ wait_sync_done:
|
|||||||
|
|
||||||
.size rv_core_critical_regs_save, . - rv_core_critical_regs_save
|
.size rv_core_critical_regs_save, . - rv_core_critical_regs_save
|
||||||
|
|
||||||
|
|
||||||
#define CSR_PCER_U 0x800
|
|
||||||
#define CSR_PCMR_U 0x801
|
|
||||||
#define PCER_CYCLES (1<<0) /* count clock cycles */
|
|
||||||
#define PCMR_GLOBAL_EN (1<<0) /* enable count */
|
|
||||||
#define pcer CSR_PCER_U
|
|
||||||
#define pcmr CSR_PCMR_U
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
This assembly subroutine is used to restore the CPU core critical register
|
This assembly subroutine is used to restore the CPU core critical register
|
||||||
@@ -183,7 +148,6 @@ _rv_core_critical_regs_restore: /* export a strong symbol to jump to here, used
|
|||||||
nop
|
nop
|
||||||
|
|
||||||
rv_core_critical_regs_restore:
|
rv_core_critical_regs_restore:
|
||||||
|
|
||||||
la t0, rv_core_critical_regs_frame
|
la t0, rv_core_critical_regs_frame
|
||||||
csrr t1, mhartid
|
csrr t1, mhartid
|
||||||
slli t1, t1, 2
|
slli t1, t1, 2
|
||||||
|
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "soc/cache_reg.h"
|
||||||
|
#include "soc/clint_reg.h"
|
||||||
|
#include "soc/clic_reg.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
|
#include "rvsleep-frames.h"
|
||||||
|
#include "sleep_cpu_retention.h"
|
||||||
|
|
||||||
|
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||||
|
|
||||||
|
static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num)
|
||||||
|
{
|
||||||
|
const int region_sz = sizeof(cpu_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(cpu_domain_dev_sleep_frame_t) + region_sz + regs_frame_sz, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||||
|
if (frame) {
|
||||||
|
cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t));
|
||||||
|
memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t));
|
||||||
|
void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz;
|
||||||
|
memset(regs_frame, 0, regs_frame_sz);
|
||||||
|
*(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) {
|
||||||
|
.region = region,
|
||||||
|
.region_num = region_num,
|
||||||
|
.regs_frame = (uint32_t *)regs_frame
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
|
{ .start = CACHE_L1_ICACHE_CTRL_REG, .end = CACHE_L1_DCACHE_CTRL_REG + 4 },
|
||||||
|
{ .start = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG, .end = CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4 }
|
||||||
|
};
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(uint8_t core_id)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = {
|
||||||
|
[0 ... portNUM_PROCESSORS - 1] = {
|
||||||
|
{ .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_SIP_REG + 4 },
|
||||||
|
{ .start = CLINT_MINT_MTIMECMP_L_REG, .end = CLINT_MINT_TIMECTL_REG + 4 },
|
||||||
|
{ .start = CLINT_MINT_MTIME_L_REG, .end = CLINT_MINT_MTIME_H_REG + 4 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][4] = {
|
||||||
|
[0 ... portNUM_PROCESSORS - 1] = {
|
||||||
|
{ .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 },
|
||||||
|
{ .start = CLIC_INT_CTRL_REG(3), .end = CLIC_INT_CTRL_REG(3) + 4 },
|
||||||
|
{ .start = CLIC_INT_CTRL_REG(7), .end = CLIC_INT_CTRL_REG(7) + 4 },
|
||||||
|
{ .start = CLIC_INT_CTRL_REG(16), .end = CLIC_INT_CTRL_REG(47) + 4 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
|
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state)
|
||||||
|
{
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||||
|
void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||||
|
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||||
|
void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init();
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
err:
|
||||||
|
esp_sleep_cpu_retention_deinit();
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||||
|
{
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||||
|
void *frame = heap_caps_calloc(1, RV_SLEEP_CTX_FRMSZ, MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||||
|
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||||
|
void *frame = heap_caps_calloc(1, sizeof(RvCoreNonCriticalSleepFrame), MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id);
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init();
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
err:
|
||||||
|
esp_sleep_cpu_retention_deinit();
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||||
|
{
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id]) {
|
||||||
|
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.critical_frame[core_id]);
|
||||||
|
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = NULL;
|
||||||
|
rv_core_critical_regs_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]) {
|
||||||
|
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]);
|
||||||
|
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id]) {
|
||||||
|
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clic_frame[core_id]);
|
||||||
|
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clint_frame[core_id]) {
|
||||||
|
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.clint_frame[core_id]);
|
||||||
|
sleep_cpu_retention_ptr->retent.clint_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.cache_config_frame) {
|
||||||
|
heap_caps_free((void *)sleep_cpu_retention_ptr->retent.cache_config_frame);
|
||||||
|
sleep_cpu_retention_ptr->retent.cache_config_frame = NULL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SLEEP_CPU_RETENTION_H__
|
||||||
|
#define __SLEEP_CPU_RETENTION_H__
|
||||||
|
|
||||||
|
#include "rvsleep-frames.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include "soc/hp_system_reg.h"
|
||||||
|
typedef enum {
|
||||||
|
SMP_IDLE,
|
||||||
|
SMP_BACKUP_START,
|
||||||
|
SMP_BACKUP_DONE,
|
||||||
|
SMP_RESTORE_START,
|
||||||
|
SMP_RESTORE_DONE,
|
||||||
|
SMP_SKIP_RETENTION,
|
||||||
|
} smp_retention_state_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t start;
|
||||||
|
uint32_t end;
|
||||||
|
} cpu_domain_dev_regs_region_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
cpu_domain_dev_regs_region_t *region;
|
||||||
|
int region_num;
|
||||||
|
uint32_t *regs_frame;
|
||||||
|
} cpu_domain_dev_sleep_frame_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal structure which holds all requested light sleep cpu retention parameters
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
RvCoreCriticalSleepFrame *critical_frame[portNUM_PROCESSORS];
|
||||||
|
RvCoreNonCriticalSleepFrame *non_critical_frame[portNUM_PROCESSORS];
|
||||||
|
cpu_domain_dev_sleep_frame_t *cache_config_frame;
|
||||||
|
cpu_domain_dev_sleep_frame_t *clic_frame[portNUM_PROCESSORS];
|
||||||
|
cpu_domain_dev_sleep_frame_t *clint_frame[portNUM_PROCESSORS];
|
||||||
|
} retent;
|
||||||
|
} sleep_cpu_retention_t;
|
||||||
|
|
||||||
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
|
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state);
|
||||||
|
#else
|
||||||
|
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr);
|
||||||
|
|
||||||
|
#endif /* #ifndef __SLEEP_CPU_RETENTION_H__ */
|
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "soc/cache_reg.h"
|
||||||
|
#include "soc/clint_reg.h"
|
||||||
|
#include "soc/clic_reg.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
|
||||||
|
#include "rvsleep-frames.h"
|
||||||
|
#include "sleep_cpu_retention.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
|
||||||
|
|
||||||
|
#define R_CONCAT(s1, s2) _R_CONCAT(s1, s2)
|
||||||
|
#define _R_CONCAT(s1, s2) s1 ## s2
|
||||||
|
|
||||||
|
#define CPU_DOMAIN_DEV_SZ0 (CPU_DOMAIN_DEV_END_ADDR0 - CPU_DOMAIN_DEV_START_ADDR0)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ1 (CPU_DOMAIN_DEV_END_ADDR1 - CPU_DOMAIN_DEV_START_ADDR1)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ2 (CPU_DOMAIN_DEV_END_ADDR2 - CPU_DOMAIN_DEV_START_ADDR2)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ3 (CPU_DOMAIN_DEV_END_ADDR3 - CPU_DOMAIN_DEV_START_ADDR3)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ4 (CPU_DOMAIN_DEV_END_ADDR4 - CPU_DOMAIN_DEV_START_ADDR4)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ5 (CPU_DOMAIN_DEV_END_ADDR5 - CPU_DOMAIN_DEV_START_ADDR5)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ6 (CPU_DOMAIN_DEV_END_ADDR6 - CPU_DOMAIN_DEV_START_ADDR6)
|
||||||
|
#define CPU_DOMAIN_DEV_SZ7 (CPU_DOMAIN_DEV_END_ADDR7 - CPU_DOMAIN_DEV_START_ADDR7)
|
||||||
|
|
||||||
|
#define CPU_DOMAIN_DEV_TOTAL_SZ(n) (R_CONCAT(__TOTAL_SZ, n))
|
||||||
|
|
||||||
|
#define __TOTAL_SZ0 (sizeof(cpu_domain_dev_sleep_frame_t))
|
||||||
|
#define __TOTAL_SZ1 ((__TOTAL_SZ0) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ0)
|
||||||
|
#define __TOTAL_SZ2 ((__TOTAL_SZ1) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ1)
|
||||||
|
#define __TOTAL_SZ3 ((__TOTAL_SZ2) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ2)
|
||||||
|
#define __TOTAL_SZ4 ((__TOTAL_SZ3) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ3)
|
||||||
|
#define __TOTAL_SZ5 ((__TOTAL_SZ4) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ4)
|
||||||
|
#define __TOTAL_SZ6 ((__TOTAL_SZ5) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ5)
|
||||||
|
#define __TOTAL_SZ7 ((__TOTAL_SZ6) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ6)
|
||||||
|
#define __TOTAL_SZ8 ((__TOTAL_SZ7) + (sizeof(cpu_domain_dev_regs_region_t)) + CPU_DOMAIN_DEV_SZ7)
|
||||||
|
|
||||||
|
static void * cpu_domain_dev_sleep_frame_alloc_and_init(const cpu_domain_dev_regs_region_t *regions, const int region_num, void * frame)
|
||||||
|
{
|
||||||
|
const int region_sz = sizeof(cpu_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;
|
||||||
|
}
|
||||||
|
if (frame) {
|
||||||
|
cpu_domain_dev_regs_region_t *region = (cpu_domain_dev_regs_region_t *)(frame + sizeof(cpu_domain_dev_sleep_frame_t));
|
||||||
|
memcpy(region, regions, region_num * sizeof(cpu_domain_dev_regs_region_t));
|
||||||
|
void *regs_frame = frame + sizeof(cpu_domain_dev_sleep_frame_t) + region_sz;
|
||||||
|
memset(regs_frame, 0, regs_frame_sz);
|
||||||
|
*(cpu_domain_dev_sleep_frame_t *)frame = (cpu_domain_dev_sleep_frame_t) {
|
||||||
|
.region = region,
|
||||||
|
.region_num = region_num,
|
||||||
|
.regs_frame = (uint32_t *)regs_frame
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR0
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR0
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR1
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR1
|
||||||
|
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR0 (CACHE_L1_ICACHE_CTRL_REG)
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR0 (CACHE_L1_DCACHE_CTRL_REG + 4)
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR1 (CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG)
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR1 (CACHE_L1_CACHE_WRAP_AROUND_CTRL_REG + 4)
|
||||||
|
|
||||||
|
static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
|
{ .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 },
|
||||||
|
{ .start = CPU_DOMAIN_DEV_START_ADDR1, .end = CPU_DOMAIN_DEV_END_ADDR1 }
|
||||||
|
};
|
||||||
|
static uint8_t sleep_frame[CPU_DOMAIN_DEV_TOTAL_SZ(2)] __attribute__((aligned(4)));
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]), sleep_frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR0
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR0
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR1
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR1
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR2
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR2
|
||||||
|
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR0 (CLINT_MINT_SIP_REG)
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR0 (CLINT_MINT_SIP_REG + 4)
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR1 (CLINT_MINT_MTIMECMP_L_REG)
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR1 (CLINT_MINT_TIMECTL_REG + 4)
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR2 (CLINT_MINT_MTIME_L_REG)
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR2 (CLINT_MINT_MTIME_H_REG + 4)
|
||||||
|
|
||||||
|
static inline void * cpu_domain_clint_sleep_frame_alloc_and_init(uint8_t core_id)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][3] = {
|
||||||
|
[0 ... portNUM_PROCESSORS - 1] = {
|
||||||
|
{ .start = CPU_DOMAIN_DEV_START_ADDR0, .end = CPU_DOMAIN_DEV_END_ADDR0 },
|
||||||
|
{ .start = CPU_DOMAIN_DEV_START_ADDR1, .end = CPU_DOMAIN_DEV_END_ADDR1 },
|
||||||
|
{ .start = CPU_DOMAIN_DEV_START_ADDR2, .end = CPU_DOMAIN_DEV_END_ADDR2 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static DRAM_ATTR uint8_t sleep_frame[portNUM_PROCESSORS][CPU_DOMAIN_DEV_TOTAL_SZ(3)] __attribute__((aligned(4)));
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]), sleep_frame[core_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR0
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR0
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR1
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR1
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR2
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR2
|
||||||
|
#undef CPU_DOMAIN_DEV_START_ADDR3
|
||||||
|
#undef CPU_DOMAIN_DEV_END_ADDR3
|
||||||
|
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR0 (CLIC_INT_CONFIG_REG)
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR0 (CLIC_INT_THRESH_REG + 4)
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR1 (CLIC_INT_CTRL_REG(3))
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR1 (CLIC_INT_CTRL_REG(3) + 4)
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR2 (CLIC_INT_CTRL_REG(7))
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR2 (CLIC_INT_CTRL_REG(7) + 4)
|
||||||
|
#define CPU_DOMAIN_DEV_START_ADDR3 (CLIC_INT_CTRL_REG(16))
|
||||||
|
#define CPU_DOMAIN_DEV_END_ADDR3 (CLIC_INT_CTRL_REG(47) + 4)
|
||||||
|
|
||||||
|
static inline void * cpu_domain_clic_sleep_frame_alloc_and_init(uint8_t core_id)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[portNUM_PROCESSORS][4] = {
|
||||||
|
[0 ... portNUM_PROCESSORS - 1] = {
|
||||||
|
{ .start = CLIC_INT_CONFIG_REG, .end = CLIC_INT_THRESH_REG + 4 },
|
||||||
|
{ .start = CLIC_INT_CTRL_REG(3), .end = CLIC_INT_CTRL_REG(3) + 4 },
|
||||||
|
{ .start = CLIC_INT_CTRL_REG(7), .end = CLIC_INT_CTRL_REG(7) + 4 },
|
||||||
|
{ .start = CLIC_INT_CTRL_REG(16), .end = CLIC_INT_CTRL_REG(47) + 4 },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static DRAM_ATTR uint8_t sleep_frame[portNUM_PROCESSORS][CPU_DOMAIN_DEV_TOTAL_SZ(4)] __attribute__((aligned(4)));
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions[core_id], sizeof(regions[core_id]) / sizeof(regions[core_id][0]), sleep_frame[core_id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
|
||||||
|
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr, smp_retention_state_t *s_smp_retention_state)
|
||||||
|
{
|
||||||
|
static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ * portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||||
|
static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)* portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||||
|
void * regs = rv_core_critical_regs + core_id * RV_SLEEP_CTX_FRMSZ;
|
||||||
|
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||||
|
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||||
|
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)(rv_core_non_critical_regs+core_id * sizeof(RvCoreNonCriticalSleepFrame));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id);
|
||||||
|
sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||||
|
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init();
|
||||||
|
sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
esp_err_t esp_sleep_cpu_retention_init_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||||
|
{
|
||||||
|
static DRAM_ATTR uint8_t rv_core_critical_regs[RV_SLEEP_CTX_FRMSZ * portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||||
|
static DRAM_ATTR uint8_t rv_core_non_critical_regs[sizeof(RvCoreNonCriticalSleepFrame)* portNUM_PROCESSORS] __attribute__((aligned(4)));
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id] == NULL) {
|
||||||
|
void * regs = rv_core_critical_regs + core_id * RV_SLEEP_CTX_FRMSZ;
|
||||||
|
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||||
|
rv_core_critical_regs_frame[core_id] = (RvCoreCriticalSleepFrame *) regs;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] == NULL) {
|
||||||
|
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = (RvCoreNonCriticalSleepFrame *)(rv_core_non_critical_regs+core_id * sizeof(RvCoreNonCriticalSleepFrame));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clint_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init(core_id);
|
||||||
|
sleep_cpu_retention_ptr->retent.clint_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id] == NULL) {
|
||||||
|
void *frame = cpu_domain_clic_sleep_frame_alloc_and_init(core_id);
|
||||||
|
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.cache_config_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_cache_config_sleep_frame_alloc_and_init();
|
||||||
|
sleep_cpu_retention_ptr->retent.cache_config_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_sleep_cpu_retention_deinit_impl(sleep_cpu_retention_t *sleep_cpu_retention_ptr)
|
||||||
|
{
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.critical_frame[core_id]) {
|
||||||
|
sleep_cpu_retention_ptr->retent.critical_frame[core_id] = NULL;
|
||||||
|
rv_core_critical_regs_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.non_critical_frame[core_id]) {
|
||||||
|
sleep_cpu_retention_ptr->retent.non_critical_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clint_frame[core_id]) {
|
||||||
|
sleep_cpu_retention_ptr->retent.clint_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.clic_frame[core_id]) {
|
||||||
|
sleep_cpu_retention_ptr->retent.clic_frame[core_id] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sleep_cpu_retention_ptr->retent.cache_config_frame) {
|
||||||
|
sleep_cpu_retention_ptr->retent.cache_config_frame = NULL;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@@ -5,7 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
Reference in New Issue
Block a user