mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-10 04:43:33 +00:00
cpu retention: software cpu retention support for esp32c6
cpu retention: add riscv core sleep critical and non-critical register layout structure definition cpu retention: add assembly subroutine for cpu critical register backup and restore cpu retention: add cpu core critical register context backup and restore support cpu retention: add cpu core non-critical register context backup and restore support cpu retention: add interrupt priority register context backup and restore support cpu retention: add cache config register context backup and restore support cpu retention: add plic interrupt register context backup and restore support cpu retention: add clint interrupt register context backup and restore support cpu retention: wait icache state idle before pmu enter sleep
This commit is contained in:
@@ -73,6 +73,14 @@ if(NOT BOOTLOADER_BUILD)
|
|||||||
list(APPEND srcs "esp_ds.c")
|
list(APPEND srcs "esp_ds.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_SOC_PM_CPU_RETENTION_BY_SW)
|
||||||
|
list(APPEND srcs "sleep_cpu_asm.S")
|
||||||
|
set_property(TARGET ${COMPONENT_LIB}
|
||||||
|
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u rv_core_critical_regs_save")
|
||||||
|
set_property(TARGET ${COMPONENT_LIB}
|
||||||
|
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u rv_core_critical_regs_restore")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT)
|
if(CONFIG_SOC_MODEM_CLOCK_IS_INDEPENDENT)
|
||||||
list(APPEND srcs "modem_clock.c")
|
list(APPEND srcs "modem_clock.c")
|
||||||
endif()
|
endif()
|
||||||
|
@@ -50,6 +50,14 @@ void sleep_disable_cpu_retention(void);
|
|||||||
|
|
||||||
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||||
|
|
||||||
|
|
||||||
|
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
|
||||||
|
esp_err_t esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||||
|
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
|
||||||
|
|
||||||
|
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
|
||||||
@@ -16,22 +17,55 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "hal/rtc_hal.h"
|
|
||||||
#include "esp_private/sleep_cpu.h"
|
#include "esp_private/sleep_cpu.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if !SOC_PMU_SUPPORTED
|
||||||
|
#include "hal/rtc_hal.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "soc/rtc_periph.h"
|
||||||
|
|
||||||
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
#ifdef CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/cache.h"
|
#include "esp32s3/rom/cache.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
#include "esp32c6/rom/rtc.h"
|
||||||
|
#include "riscv/rvsleep-frames.h"
|
||||||
|
#include "soc/intpri_reg.h"
|
||||||
|
#include "soc/extmem_reg.h"
|
||||||
|
#include "soc/plic_reg.h"
|
||||||
|
#include "soc/clint_reg.h"
|
||||||
|
#include "esp32c6/rom/cache.h"
|
||||||
#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
|
* Internal structure which holds all requested light sleep cpu retention parameters
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||||
rtc_cntl_sleep_retent_t retent;
|
rtc_cntl_sleep_retent_t retent;
|
||||||
|
#elif SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
struct {
|
||||||
|
RvCoreCriticalSleepFrame *critical_frame;
|
||||||
|
RvCoreNonCriticalSleepFrame *non_critical_frame;
|
||||||
|
cpu_domain_dev_sleep_frame_t *intpri_frame;
|
||||||
|
cpu_domain_dev_sleep_frame_t *cache_config_frame;
|
||||||
|
cpu_domain_dev_sleep_frame_t *plic_frame;
|
||||||
|
cpu_domain_dev_sleep_frame_t *clint_frame;
|
||||||
|
} retent;
|
||||||
#endif
|
#endif
|
||||||
} sleep_cpu_retention_t;
|
} sleep_cpu_retention_t;
|
||||||
|
|
||||||
@@ -40,12 +74,12 @@ static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
|
|||||||
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||||
|
|
||||||
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
#if CONFIG_PM_POWER_DOWN_TAGMEM_IN_LIGHT_SLEEP
|
||||||
static int cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size)
|
static uint32_t cache_tagmem_retention_setup(uint32_t code_seg_vaddr, uint32_t code_seg_size, uint32_t data_seg_vaddr, uint32_t data_seg_size)
|
||||||
{
|
{
|
||||||
int sets; /* i/d-cache total set counts */
|
uint32_t sets; /* i/d-cache total set counts */
|
||||||
int index; /* virtual address mapping i/d-cache row offset */
|
uint32_t index; /* virtual address mapping i/d-cache row offset */
|
||||||
int waysgrp;
|
uint32_t waysgrp;
|
||||||
int icache_tagmem_blk_gs, dcache_tagmem_blk_gs;
|
uint32_t icache_tagmem_blk_gs, dcache_tagmem_blk_gs;
|
||||||
struct cache_mode imode = { .icache = 1 };
|
struct cache_mode imode = { .icache = 1 };
|
||||||
struct cache_mode dmode = { .icache = 0 };
|
struct cache_mode dmode = { .icache = 0 };
|
||||||
|
|
||||||
@@ -117,14 +151,13 @@ static esp_err_t esp_sleep_tagmem_pd_low_init(void)
|
|||||||
uint32_t data_start = SOC_DROM_LOW;
|
uint32_t data_start = SOC_DROM_LOW;
|
||||||
uint32_t data_size = SOC_EXTRAM_DATA_SIZE;
|
uint32_t data_size = SOC_EXTRAM_DATA_SIZE;
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGI(TAG, "Code start at %08x, total %.2f KiB, data start at %08x, total %.2f KiB",
|
ESP_LOGI(TAG, "Code start at 0x%08"PRIx32", total %"PRIu32", data start at 0x%08"PRIx32", total %"PRIu32" Bytes",
|
||||||
code_start, (float)code_size/1024, data_start, (float)data_size/1024);
|
code_start, code_size, data_start, data_size);
|
||||||
int tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size);
|
uint32_t tagmem_sz = cache_tagmem_retention_setup(code_start, code_size, data_start, data_size);
|
||||||
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN,
|
void *buf = heap_caps_aligned_calloc(SOC_RTC_CNTL_TAGMEM_PD_DMA_ADDR_ALIGN, 1,
|
||||||
tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE,
|
tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||||
MALLOC_CAP_RETENTION);
|
MALLOC_CAP_RETENTION);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
memset(buf, 0, tagmem_sz + RTC_HAL_DMA_LINK_NODE_SIZE);
|
|
||||||
s_cpu_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf,
|
s_cpu_retention.retent.tagmem.link_addr = rtc_cntl_hal_dma_link_init(buf,
|
||||||
buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL);
|
buf + RTC_HAL_DMA_LINK_NODE_SIZE, tagmem_sz, NULL);
|
||||||
} else {
|
} else {
|
||||||
@@ -161,11 +194,10 @@ static esp_err_t esp_sleep_tagmem_pd_low_deinit(void)
|
|||||||
esp_err_t esp_sleep_cpu_pd_low_init(void)
|
esp_err_t esp_sleep_cpu_pd_low_init(void)
|
||||||
{
|
{
|
||||||
if (s_cpu_retention.retent.cpu_pd_mem == NULL) {
|
if (s_cpu_retention.retent.cpu_pd_mem == NULL) {
|
||||||
void *buf = heap_caps_aligned_alloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN,
|
void *buf = heap_caps_aligned_calloc(SOC_RTC_CNTL_CPU_PD_DMA_ADDR_ALIGN, 1,
|
||||||
SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
|
SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE,
|
||||||
MALLOC_CAP_RETENTION);
|
MALLOC_CAP_RETENTION);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
memset(buf, 0, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE + RTC_HAL_DMA_LINK_NODE_SIZE);
|
|
||||||
s_cpu_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
|
s_cpu_retention.retent.cpu_pd_mem = rtc_cntl_hal_dma_link_init(buf,
|
||||||
buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
|
buf + RTC_HAL_DMA_LINK_NODE_SIZE, SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE, NULL);
|
||||||
} else {
|
} else {
|
||||||
@@ -204,25 +236,371 @@ esp_err_t esp_sleep_cpu_pd_low_deinit(void)
|
|||||||
|
|
||||||
void sleep_enable_cpu_retention(void)
|
void sleep_enable_cpu_retention(void)
|
||||||
{
|
{
|
||||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA
|
|
||||||
rtc_cntl_hal_enable_cpu_retention(&s_cpu_retention.retent);
|
rtc_cntl_hal_enable_cpu_retention(&s_cpu_retention.retent);
|
||||||
#endif
|
|
||||||
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA
|
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||||
rtc_cntl_hal_enable_tagmem_retention(&s_cpu_retention.retent);
|
rtc_cntl_hal_enable_tagmem_retention(&s_cpu_retention.retent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR sleep_disable_cpu_retention(void)
|
void IRAM_ATTR sleep_disable_cpu_retention(void)
|
||||||
{
|
{
|
||||||
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA
|
|
||||||
rtc_cntl_hal_disable_cpu_retention(&s_cpu_retention.retent);
|
rtc_cntl_hal_disable_cpu_retention(&s_cpu_retention.retent);
|
||||||
#endif
|
|
||||||
#if SOC_PM_SUPPORT_TAGMEM_PD && SOC_PM_CPU_RETENTION_BY_REGDMA
|
#if SOC_PM_SUPPORT_TAGMEM_PD
|
||||||
rtc_cntl_hal_disable_tagmem_retention(&s_cpu_retention.retent);
|
rtc_cntl_hal_disable_tagmem_retention(&s_cpu_retention.retent);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_REGDMA
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
|
||||||
|
#define CUSTOM_CSR_PCER_MACHINE 0x7e0
|
||||||
|
#define CUSTOM_CSR_PCMR_MACHINE 0x7e1
|
||||||
|
#define CUSTOM_CSR_PCCR_MACHINE 0x7e2
|
||||||
|
#define CUSTOM_CSR_CPU_TESTBUS_CTRL 0x7e3
|
||||||
|
#define CUSTOM_CSR_PCER_USER 0x800
|
||||||
|
#define CUSTOM_CSR_PCMR_USER 0x801
|
||||||
|
#define CUSTOM_CSR_PCCR_USER 0x802
|
||||||
|
#define CUSTOM_CSR_GPIO_OEN_USER 0x803
|
||||||
|
#define CUSTOM_CSR_GPIO_IN_USER 0x804
|
||||||
|
#define CUSTOM_CSR_GPIO_OUT_USER 0x805
|
||||||
|
#define CUSTOM_CSR_CO_EXCEPTION_CAUSE 0x7f0
|
||||||
|
#define CUSTOM_CSR_CO_HWLP 0x7f1
|
||||||
|
#define CUSTOM_CSR_CO_AIA 0x7f2
|
||||||
|
|
||||||
|
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame;
|
||||||
|
|
||||||
|
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_intpri_sleep_frame_alloc_and_init(void)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
|
{ .start = INTPRI_CORE0_CPU_INT_ENABLE_REG, .end = INTPRI_RND_ECO_LOW_REG + 4 },
|
||||||
|
{ .start = INTPRI_RND_ECO_HIGH_REG, .end = INTPRI_RND_ECO_HIGH_REG + 4 }
|
||||||
|
};
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void * cpu_domain_cache_config_sleep_frame_alloc_and_init(void)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
|
{ .start = EXTMEM_DCACHE_CTRL_REG, .end = EXTMEM_DCACHE_CTRL_REG + 4 },
|
||||||
|
{ .start = EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, .end = EXTMEM_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_plic_sleep_frame_alloc_and_init(void)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
|
{ .start = PLIC_MXINT_ENABLE_REG, .end = PLIC_MXINT_CLAIM_REG + 4 },
|
||||||
|
{ .start = PLIC_MXINT_CONF_REG, .end = PLIC_MXINT_CONF_REG + 4 },
|
||||||
|
{ .start = PLIC_UXINT_ENABLE_REG, .end = PLIC_UXINT_CLAIM_REG + 4 },
|
||||||
|
{ .start = PLIC_UXINT_CONF_REG, .end = PLIC_UXINT_CONF_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(void)
|
||||||
|
{
|
||||||
|
const static cpu_domain_dev_regs_region_t regions[] = {
|
||||||
|
{ .start = CLINT_MINT_SIP_REG, .end = CLINT_MINT_MTIMECMP_H_REG + 4 },
|
||||||
|
{ .start = CLINT_UINT_SIP_REG, .end = CLINT_UINT_UTIMECMP_H_REG + 4 }
|
||||||
|
};
|
||||||
|
return cpu_domain_dev_sleep_frame_alloc_and_init(regions, sizeof(regions) / sizeof(regions[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t esp_sleep_cpu_retention_init_impl(void)
|
||||||
|
{
|
||||||
|
if (s_cpu_retention.retent.critical_frame == 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 = (RvCoreCriticalSleepFrame *)frame;
|
||||||
|
rv_core_critical_regs_frame = (RvCoreCriticalSleepFrame *)frame;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.non_critical_frame == 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 = (RvCoreNonCriticalSleepFrame *)frame;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.intpri_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_intpri_sleep_frame_alloc_and_init();
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
s_cpu_retention.retent.intpri_frame = (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 (s_cpu_retention.retent.plic_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_plic_sleep_frame_alloc_and_init();
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
s_cpu_retention.retent.plic_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.clint_frame == NULL) {
|
||||||
|
void *frame = cpu_domain_clint_sleep_frame_alloc_and_init();
|
||||||
|
if (frame == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
s_cpu_retention.retent.clint_frame = (cpu_domain_dev_sleep_frame_t *)frame;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (s_cpu_retention.retent.critical_frame) {
|
||||||
|
heap_caps_free((void *)s_cpu_retention.retent.critical_frame);
|
||||||
|
s_cpu_retention.retent.critical_frame = NULL;
|
||||||
|
rv_core_critical_regs_frame = NULL;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.non_critical_frame) {
|
||||||
|
heap_caps_free((void *)s_cpu_retention.retent.non_critical_frame);
|
||||||
|
s_cpu_retention.retent.non_critical_frame = NULL;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.intpri_frame) {
|
||||||
|
heap_caps_free((void *)s_cpu_retention.retent.intpri_frame);
|
||||||
|
s_cpu_retention.retent.intpri_frame = 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;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.plic_frame) {
|
||||||
|
heap_caps_free((void *)s_cpu_retention.retent.plic_frame);
|
||||||
|
s_cpu_retention.retent.plic_frame = NULL;
|
||||||
|
}
|
||||||
|
if (s_cpu_retention.retent.clint_frame) {
|
||||||
|
heap_caps_free((void *)s_cpu_retention.retent.clint_frame);
|
||||||
|
s_cpu_retention.retent.clint_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)
|
||||||
|
{
|
||||||
|
assert(s_cpu_retention.retent.non_critical_frame);
|
||||||
|
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame;
|
||||||
|
frame->mscratch = RV_READ_CSR(mscratch);
|
||||||
|
frame->mideleg = RV_READ_CSR(mideleg);
|
||||||
|
frame->misa = RV_READ_CSR(misa);
|
||||||
|
frame->tselect = RV_READ_CSR(tselect);
|
||||||
|
frame->tdata1 = RV_READ_CSR(tdata1);
|
||||||
|
frame->tdata2 = RV_READ_CSR(tdata2);
|
||||||
|
frame->tcontrol = RV_READ_CSR(tcontrol);
|
||||||
|
frame->pmpcfg0 = RV_READ_CSR(pmpcfg0);
|
||||||
|
frame->pmpcfg1 = RV_READ_CSR(pmpcfg1);
|
||||||
|
frame->pmpcfg2 = RV_READ_CSR(pmpcfg2);
|
||||||
|
frame->pmpcfg3 = RV_READ_CSR(pmpcfg3);
|
||||||
|
frame->pmpaddr0 = RV_READ_CSR(pmpaddr0);
|
||||||
|
frame->pmpaddr1 = RV_READ_CSR(pmpaddr1);
|
||||||
|
frame->pmpaddr2 = RV_READ_CSR(pmpaddr2);
|
||||||
|
frame->pmpaddr3 = RV_READ_CSR(pmpaddr3);
|
||||||
|
frame->pmpaddr4 = RV_READ_CSR(pmpaddr4);
|
||||||
|
frame->pmpaddr5 = RV_READ_CSR(pmpaddr5);
|
||||||
|
frame->pmpaddr6 = RV_READ_CSR(pmpaddr6);
|
||||||
|
frame->pmpaddr7 = RV_READ_CSR(pmpaddr7);
|
||||||
|
frame->pmpaddr8 = RV_READ_CSR(pmpaddr8);
|
||||||
|
frame->pmpaddr9 = RV_READ_CSR(pmpaddr9);
|
||||||
|
frame->pmpaddr10 = RV_READ_CSR(pmpaddr10);
|
||||||
|
frame->pmpaddr11 = RV_READ_CSR(pmpaddr11);
|
||||||
|
frame->pmpaddr12 = RV_READ_CSR(pmpaddr12);
|
||||||
|
frame->pmpaddr13 = RV_READ_CSR(pmpaddr13);
|
||||||
|
frame->pmpaddr14 = RV_READ_CSR(pmpaddr14);
|
||||||
|
frame->pmpaddr15 = RV_READ_CSR(pmpaddr15);
|
||||||
|
|
||||||
|
frame->utvec = RV_READ_CSR(utvec);
|
||||||
|
frame->ustatus = RV_READ_CSR(ustatus);
|
||||||
|
frame->uepc = RV_READ_CSR(uepc);
|
||||||
|
frame->ucause = RV_READ_CSR(ucause);
|
||||||
|
|
||||||
|
frame->mpcer = RV_READ_CSR(CUSTOM_CSR_PCER_MACHINE);
|
||||||
|
frame->mpcmr = RV_READ_CSR(CUSTOM_CSR_PCMR_MACHINE);
|
||||||
|
frame->mpccr = RV_READ_CSR(CUSTOM_CSR_PCCR_MACHINE);
|
||||||
|
frame->cpu_testbus_ctrl = RV_READ_CSR(CUSTOM_CSR_CPU_TESTBUS_CTRL);
|
||||||
|
frame->upcer = RV_READ_CSR(CUSTOM_CSR_PCER_USER);
|
||||||
|
frame->upcmr = RV_READ_CSR(CUSTOM_CSR_PCMR_USER);
|
||||||
|
frame->upccr = RV_READ_CSR(CUSTOM_CSR_PCCR_USER);
|
||||||
|
frame->ugpio_oen = RV_READ_CSR(CUSTOM_CSR_GPIO_OEN_USER);
|
||||||
|
frame->ugpio_in = RV_READ_CSR(CUSTOM_CSR_GPIO_IN_USER);
|
||||||
|
frame->ugpio_out = RV_READ_CSR(CUSTOM_CSR_GPIO_OUT_USER);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR void rv_core_noncritical_regs_restore(RvCoreNonCriticalSleepFrame *frame)
|
||||||
|
{
|
||||||
|
assert(frame);
|
||||||
|
RV_WRITE_CSR(mscratch, frame->mscratch);
|
||||||
|
RV_WRITE_CSR(mideleg, frame->mideleg);
|
||||||
|
RV_WRITE_CSR(misa, frame->misa);
|
||||||
|
RV_WRITE_CSR(tselect, frame->tselect);
|
||||||
|
RV_WRITE_CSR(tdata1, frame->tdata1);
|
||||||
|
RV_WRITE_CSR(tdata2, frame->tdata2);
|
||||||
|
RV_WRITE_CSR(tcontrol, frame->tcontrol);
|
||||||
|
RV_WRITE_CSR(pmpcfg0, frame->pmpcfg0);
|
||||||
|
RV_WRITE_CSR(pmpcfg1, frame->pmpcfg1);
|
||||||
|
RV_WRITE_CSR(pmpcfg2, frame->pmpcfg2);
|
||||||
|
RV_WRITE_CSR(pmpcfg3, frame->pmpcfg3);
|
||||||
|
RV_WRITE_CSR(pmpaddr0, frame->pmpaddr0);
|
||||||
|
RV_WRITE_CSR(pmpaddr1, frame->pmpaddr1);
|
||||||
|
RV_WRITE_CSR(pmpaddr2, frame->pmpaddr2);
|
||||||
|
RV_WRITE_CSR(pmpaddr3, frame->pmpaddr3);
|
||||||
|
RV_WRITE_CSR(pmpaddr4, frame->pmpaddr4);
|
||||||
|
RV_WRITE_CSR(pmpaddr5, frame->pmpaddr5);
|
||||||
|
RV_WRITE_CSR(pmpaddr6, frame->pmpaddr6);
|
||||||
|
RV_WRITE_CSR(pmpaddr7, frame->pmpaddr7);
|
||||||
|
RV_WRITE_CSR(pmpaddr8, frame->pmpaddr8);
|
||||||
|
RV_WRITE_CSR(pmpaddr9, frame->pmpaddr9);
|
||||||
|
RV_WRITE_CSR(pmpaddr10,frame->pmpaddr10);
|
||||||
|
RV_WRITE_CSR(pmpaddr11,frame->pmpaddr11);
|
||||||
|
RV_WRITE_CSR(pmpaddr12,frame->pmpaddr12);
|
||||||
|
RV_WRITE_CSR(pmpaddr13,frame->pmpaddr13);
|
||||||
|
RV_WRITE_CSR(pmpaddr14,frame->pmpaddr14);
|
||||||
|
RV_WRITE_CSR(pmpaddr15,frame->pmpaddr15);
|
||||||
|
|
||||||
|
RV_WRITE_CSR(utvec, frame->utvec);
|
||||||
|
RV_WRITE_CSR(ustatus, frame->ustatus);
|
||||||
|
RV_WRITE_CSR(uepc, frame->uepc);
|
||||||
|
RV_WRITE_CSR(ucause, frame->ucause);
|
||||||
|
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_PCER_MACHINE, frame->mpcer);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_PCMR_MACHINE, frame->mpcmr);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_PCCR_MACHINE, frame->mpccr);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_CPU_TESTBUS_CTRL, frame->cpu_testbus_ctrl);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_PCER_USER, frame->upcer);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_PCMR_USER, frame->upcmr);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_PCCR_USER, frame->upccr);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_GPIO_OEN_USER,frame->ugpio_oen);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_GPIO_IN_USER, frame->ugpio_in);
|
||||||
|
RV_WRITE_CSR(CUSTOM_CSR_GPIO_OUT_USER,frame->ugpio_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
|
||||||
|
{
|
||||||
|
assert(frame);
|
||||||
|
cpu_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) {
|
||||||
|
regs_frame[offset++] = *(uint32_t *)addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
|
||||||
|
{
|
||||||
|
assert(frame);
|
||||||
|
cpu_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) {
|
||||||
|
*(uint32_t *)addr = regs_frame[offset++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void);
|
||||||
|
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
|
||||||
|
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
RvCoreCriticalSleepFrame * frame = rv_core_critical_regs_save();
|
||||||
|
if ((frame->pmufunc & 0x3) == 0x1) {
|
||||||
|
REG_CLR_BIT(SLEEP_MODE_REG, BIT(0)); /* Tell rom to run light sleep wake stub */
|
||||||
|
REG_WRITE(LIGHT_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
|
||||||
|
return (*goto_sleep)(wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
|
||||||
|
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
|
||||||
|
{
|
||||||
|
uint32_t mstatus = save_mstatus_and_disable_global_int();
|
||||||
|
|
||||||
|
/* wait cache idle */
|
||||||
|
Cache_Freeze_ICache_Enable(CACHE_FREEZE_ACK_BUSY);
|
||||||
|
Cache_Freeze_ICache_Disable();
|
||||||
|
|
||||||
|
cpu_domain_dev_regs_save(s_cpu_retention.retent.plic_frame);
|
||||||
|
cpu_domain_dev_regs_save(s_cpu_retention.retent.clint_frame);
|
||||||
|
cpu_domain_dev_regs_save(s_cpu_retention.retent.intpri_frame);
|
||||||
|
cpu_domain_dev_regs_save(s_cpu_retention.retent.cache_config_frame);
|
||||||
|
RvCoreNonCriticalSleepFrame *frame = rv_core_noncritical_regs_save();
|
||||||
|
|
||||||
|
esp_err_t err = do_cpu_retention(goto_sleep, wakeup_opt, reject_opt, lslp_mem_inf_fpu, dslp);
|
||||||
|
|
||||||
|
rv_core_noncritical_regs_restore(frame);
|
||||||
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.cache_config_frame);
|
||||||
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.intpri_frame);
|
||||||
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clint_frame);
|
||||||
|
cpu_domain_dev_regs_restore(s_cpu_retention.retent.plic_frame);
|
||||||
|
|
||||||
|
restore_mstatus(mstatus);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // SOC_PM_SUPPORT_CPU_PD && SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
|
||||||
|
|
||||||
#if SOC_PM_SUPPORT_CPU_PD
|
#if SOC_PM_SUPPORT_CPU_PD
|
||||||
@@ -232,6 +610,8 @@ esp_err_t esp_sleep_cpu_retention_init(void)
|
|||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||||
err = esp_sleep_cpu_pd_low_init();
|
err = esp_sleep_cpu_pd_low_init();
|
||||||
|
#elif SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
err = esp_sleep_cpu_retention_init_impl();
|
||||||
#endif
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -241,6 +621,8 @@ esp_err_t esp_sleep_cpu_retention_deinit(void)
|
|||||||
esp_err_t err = ESP_OK;
|
esp_err_t err = ESP_OK;
|
||||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||||
err = esp_sleep_cpu_pd_low_deinit();
|
err = esp_sleep_cpu_pd_low_deinit();
|
||||||
|
#elif SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
err = esp_sleep_cpu_retention_deinit_impl();
|
||||||
#endif
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -249,6 +631,13 @@ bool cpu_domain_pd_allowed(void)
|
|||||||
{
|
{
|
||||||
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
|
||||||
return (s_cpu_retention.retent.cpu_pd_mem != NULL);
|
return (s_cpu_retention.retent.cpu_pd_mem != NULL);
|
||||||
|
#elif SOC_PM_CPU_RETENTION_BY_SW
|
||||||
|
return (s_cpu_retention.retent.critical_frame != NULL) && \
|
||||||
|
(s_cpu_retention.retent.non_critical_frame != NULL) && \
|
||||||
|
(s_cpu_retention.retent.intpri_frame != NULL) && \
|
||||||
|
(s_cpu_retention.retent.cache_config_frame != NULL) && \
|
||||||
|
(s_cpu_retention.retent.plic_frame != NULL) && \
|
||||||
|
(s_cpu_retention.retent.clint_frame != NULL);
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
239
components/esp_hw_support/sleep_cpu_asm.S
Normal file
239
components/esp_hw_support/sleep_cpu_asm.S
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "soc/soc.h"
|
||||||
|
#include "riscv/rvsleep-frames.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
#include "soc/lp_aon_reg.h"
|
||||||
|
#include "soc/extmem_reg.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.section .data1,"aw"
|
||||||
|
.global rv_core_critical_regs_frame
|
||||||
|
.type rv_core_critical_regs_frame,@object
|
||||||
|
.align 4
|
||||||
|
rv_core_critical_regs_frame:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
This assembly subroutine is used to save the critical registers of the CPU
|
||||||
|
core to the internal RAM before sleep, and modify the PMU control flag to
|
||||||
|
indicate that the system needs to sleep. When the subroutine returns, it
|
||||||
|
will return the memory pointer that saves the context information of the CPU
|
||||||
|
critical registers.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section .iram1,"ax"
|
||||||
|
.global rv_core_critical_regs_save
|
||||||
|
.type rv_core_critical_regs_save,@function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
rv_core_critical_regs_save:
|
||||||
|
|
||||||
|
/* arrived here in critical section. we need:
|
||||||
|
save riscv core critical registers to RvCoreCriticalSleepFrame
|
||||||
|
*/
|
||||||
|
csrw mscratch, t0 /* use mscratch as temp storage */
|
||||||
|
la t0, rv_core_critical_regs_frame
|
||||||
|
lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */
|
||||||
|
|
||||||
|
sw ra, RV_SLP_CTX_RA(t0)
|
||||||
|
sw sp, RV_SLP_CTX_SP(t0)
|
||||||
|
sw gp, RV_SLP_CTX_GP(t0)
|
||||||
|
sw tp, RV_SLP_CTX_TP(t0)
|
||||||
|
sw t1, RV_SLP_CTX_T1(t0)
|
||||||
|
sw t2, RV_SLP_CTX_T2(t0)
|
||||||
|
sw s0, RV_SLP_CTX_S0(t0)
|
||||||
|
sw s1, RV_SLP_CTX_S1(t0)
|
||||||
|
sw a0, RV_SLP_CTX_A0(t0)
|
||||||
|
|
||||||
|
/* !! WARNING, do not use the a0 register below, a0 carries important sleep
|
||||||
|
* information and will be returned as the return value !! */
|
||||||
|
mv a0, t0
|
||||||
|
|
||||||
|
sw a1, RV_SLP_CTX_A1(t0)
|
||||||
|
sw a2, RV_SLP_CTX_A2(t0)
|
||||||
|
sw a3, RV_SLP_CTX_A3(t0)
|
||||||
|
sw a4, RV_SLP_CTX_A4(t0)
|
||||||
|
sw a5, RV_SLP_CTX_A5(t0)
|
||||||
|
sw a6, RV_SLP_CTX_A6(t0)
|
||||||
|
sw a7, RV_SLP_CTX_A7(t0)
|
||||||
|
sw s2, RV_SLP_CTX_S2(t0)
|
||||||
|
sw s3, RV_SLP_CTX_S3(t0)
|
||||||
|
sw s4, RV_SLP_CTX_S4(t0)
|
||||||
|
sw s5, RV_SLP_CTX_S5(t0)
|
||||||
|
sw s6, RV_SLP_CTX_S6(t0)
|
||||||
|
sw s7, RV_SLP_CTX_S7(t0)
|
||||||
|
sw s8, RV_SLP_CTX_S8(t0)
|
||||||
|
sw s9, RV_SLP_CTX_S9(t0)
|
||||||
|
sw s10, RV_SLP_CTX_S10(t0)
|
||||||
|
sw s11, RV_SLP_CTX_S11(t0)
|
||||||
|
sw t3, RV_SLP_CTX_T3(t0)
|
||||||
|
sw t4, RV_SLP_CTX_T4(t0)
|
||||||
|
sw t5, RV_SLP_CTX_T5(t0)
|
||||||
|
sw t6, RV_SLP_CTX_T6(t0)
|
||||||
|
|
||||||
|
csrr t1, mstatus
|
||||||
|
sw t1, RV_SLP_CTX_MSTATUS(t0)
|
||||||
|
csrr t2, mtvec
|
||||||
|
sw t2, RV_SLP_CTX_MTVEC(t0)
|
||||||
|
csrr t3, mcause
|
||||||
|
sw t3, RV_SLP_CTX_MCAUSE(t0)
|
||||||
|
|
||||||
|
csrr t1, mtval
|
||||||
|
sw t1, RV_SLP_CTX_MTVAL(t0)
|
||||||
|
csrr t2, mie
|
||||||
|
sw t2, RV_SLP_CTX_MIE(t0)
|
||||||
|
csrr t3, mip
|
||||||
|
sw t3, RV_SLP_CTX_MIP(t0)
|
||||||
|
csrr t1, mepc
|
||||||
|
sw t1, RV_SLP_CTX_MEPC(t0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
!!! Let idf knows it's going to sleep !!!
|
||||||
|
|
||||||
|
RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or
|
||||||
|
has just been awakened. We use the lowest 2 bits as indication information,
|
||||||
|
3 means being awakened, 1 means going to sleep.
|
||||||
|
*/
|
||||||
|
li t1, ~0x3
|
||||||
|
lw t2, RV_SLP_CTX_PMUFUNC(t0)
|
||||||
|
and t2, t1, t2
|
||||||
|
ori t2, t2, 0x1
|
||||||
|
sw t2, RV_SLP_CTX_PMUFUNC(t0)
|
||||||
|
|
||||||
|
mv t3, t0
|
||||||
|
csrr t0, mscratch
|
||||||
|
sw t0, RV_SLP_CTX_T0(t3)
|
||||||
|
|
||||||
|
#if !CONFIG_IDF_TARGET_ESP32C6
|
||||||
|
/* 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 t2, RV_SLP_CTX_T2(t3)
|
||||||
|
lw t3, RV_SLP_CTX_T3(t3)
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
.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
|
||||||
|
context before sleep after system wakes up, modify the PMU control
|
||||||
|
information, and return the critical register context memory object pointer.
|
||||||
|
After the subroutine returns, continue to restore other modules of the
|
||||||
|
system.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
.section .iram1,"ax"
|
||||||
|
.global rv_core_critical_regs_restore
|
||||||
|
.type rv_core_critical_regs_restore,@function
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
rv_core_critical_regs_restore:
|
||||||
|
|
||||||
|
la t0, rv_core_critical_regs_frame
|
||||||
|
lw t0, 0(t0) /* t0 pointer to RvCoreCriticalSleepFrame object */
|
||||||
|
beqz t0, .skip_restore /* make sure we do not jump to zero address */
|
||||||
|
|
||||||
|
/*
|
||||||
|
!!! Let idf knows it's sleep awake. !!!
|
||||||
|
|
||||||
|
RV_SLP_STK_PMUFUNC field is used to identify whether it is going to sleep or
|
||||||
|
has just been awakened. We use the lowest 2 bits as indication information,
|
||||||
|
3 means being awakened, 1 means going to sleep.
|
||||||
|
*/
|
||||||
|
lw t1, RV_SLP_CTX_PMUFUNC(t0)
|
||||||
|
ori t1, t1, 0x3
|
||||||
|
sw t1, RV_SLP_CTX_PMUFUNC(t0)
|
||||||
|
|
||||||
|
lw t2, RV_SLP_CTX_MEPC(t0)
|
||||||
|
csrw mepc, t2
|
||||||
|
lw t3, RV_SLP_CTX_MIP(t0)
|
||||||
|
csrw mip, t3
|
||||||
|
lw t1, RV_SLP_CTX_MIE(t0)
|
||||||
|
csrw mie, t1
|
||||||
|
lw t2, RV_SLP_CTX_MSTATUS(t0)
|
||||||
|
csrw mstatus, t2
|
||||||
|
|
||||||
|
lw t3, RV_SLP_CTX_MTVEC(t0)
|
||||||
|
csrw mtvec, t3
|
||||||
|
lw t1, RV_SLP_CTX_MCAUSE(t0)
|
||||||
|
csrw mcause, t1
|
||||||
|
lw t2, RV_SLP_CTX_MTVAL(t0)
|
||||||
|
csrw mtval, t2
|
||||||
|
|
||||||
|
lw t6, RV_SLP_CTX_T6(t0)
|
||||||
|
lw t5, RV_SLP_CTX_T5(t0)
|
||||||
|
lw t4, RV_SLP_CTX_T4(t0)
|
||||||
|
lw t3, RV_SLP_CTX_T3(t0)
|
||||||
|
lw s11, RV_SLP_CTX_S11(t0)
|
||||||
|
lw s10, RV_SLP_CTX_S10(t0)
|
||||||
|
lw s9, RV_SLP_CTX_S9(t0)
|
||||||
|
lw s8, RV_SLP_CTX_S8(t0)
|
||||||
|
lw s7, RV_SLP_CTX_S7(t0)
|
||||||
|
lw s6, RV_SLP_CTX_S6(t0)
|
||||||
|
lw s5, RV_SLP_CTX_S5(t0)
|
||||||
|
lw s4, RV_SLP_CTX_S4(t0)
|
||||||
|
lw s3, RV_SLP_CTX_S3(t0)
|
||||||
|
lw s2, RV_SLP_CTX_S2(t0)
|
||||||
|
lw a7, RV_SLP_CTX_A7(t0)
|
||||||
|
lw a6, RV_SLP_CTX_A6(t0)
|
||||||
|
lw a5, RV_SLP_CTX_A5(t0)
|
||||||
|
lw a4, RV_SLP_CTX_A4(t0)
|
||||||
|
lw a3, RV_SLP_CTX_A3(t0)
|
||||||
|
lw a2, RV_SLP_CTX_A2(t0)
|
||||||
|
lw a1, RV_SLP_CTX_A1(t0)
|
||||||
|
lw a0, RV_SLP_CTX_A0(t0)
|
||||||
|
lw s1, RV_SLP_CTX_S1(t0)
|
||||||
|
lw s0, RV_SLP_CTX_S0(t0)
|
||||||
|
lw t2, RV_SLP_CTX_T2(t0)
|
||||||
|
lw t1, RV_SLP_CTX_T1(t0)
|
||||||
|
lw tp, RV_SLP_CTX_TP(t0)
|
||||||
|
lw gp, RV_SLP_CTX_GP(t0)
|
||||||
|
lw sp, RV_SLP_CTX_SP(t0)
|
||||||
|
lw ra, RV_SLP_CTX_RA(t0)
|
||||||
|
lw t0, RV_SLP_CTX_T0(t0)
|
||||||
|
|
||||||
|
.skip_restore:
|
||||||
|
ret
|
||||||
|
|
||||||
|
.size rv_core_critical_regs_restore, . - rv_core_critical_regs_restore
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -32,7 +32,7 @@ extern "C" {
|
|||||||
* Please do not use reserved or used rtc memory or registers. *
|
* Please do not use reserved or used rtc memory or registers. *
|
||||||
* *
|
* *
|
||||||
*************************************************************************************
|
*************************************************************************************
|
||||||
* RTC Memory & Store Register usage
|
* LP Memory & Store Register usage
|
||||||
*************************************************************************************
|
*************************************************************************************
|
||||||
* rtc memory addr type size usage
|
* rtc memory addr type size usage
|
||||||
* 0x3f421000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry
|
* 0x3f421000(0x50000000) Slow SIZE_CP Co-Processor code/Reset Entry
|
||||||
@@ -42,25 +42,29 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
*************************************************************************************
|
*************************************************************************************
|
||||||
* RTC store registers usage
|
* RTC store registers usage
|
||||||
* RTC_CNTL_STORE0_REG Reserved
|
* LP_AON_STORE0_REG Reserved
|
||||||
* RTC_CNTL_STORE1_REG RTC_SLOW_CLK calibration value
|
* LP_AON_STORE1_REG RTC_SLOW_CLK calibration value
|
||||||
* RTC_CNTL_STORE2_REG Boot time, low word
|
* LP_AON_STORE2_REG Boot time, low word
|
||||||
* RTC_CNTL_STORE3_REG Boot time, high word
|
* LP_AON_STORE3_REG Boot time, high word
|
||||||
* RTC_CNTL_STORE4_REG External XTAL frequency
|
* LP_AON_STORE4_REG External XTAL frequency
|
||||||
* RTC_CNTL_STORE5_REG APB bus frequency
|
* LP_AON_STORE5_REG FAST_RTC_MEMORY_LENGTH
|
||||||
* RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY
|
* LP_AON_STORE6_REG FAST_RTC_MEMORY_ENTRY
|
||||||
* RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC
|
* LP_AON_STORE7_REG FAST_RTC_MEMORY_CRC
|
||||||
|
* LP_AON_STORE8_REG Store light sleep wake stub addr
|
||||||
|
* LP_AON_STORE9_REG Store the sleep mode at bit[0] (0:light sleep 1:deep sleep)
|
||||||
*************************************************************************************
|
*************************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RTC_SLOW_CLK_CAL_REG LP_AON_STORE1_REG
|
#define RTC_SLOW_CLK_CAL_REG LP_AON_STORE1_REG
|
||||||
#define RTC_BOOT_TIME_LOW_REG LP_AON_STORE2_REG
|
#define RTC_BOOT_TIME_LOW_REG LP_AON_STORE2_REG
|
||||||
#define RTC_BOOT_TIME_HIGH_REG LP_AON_STORE3_REG
|
#define RTC_BOOT_TIME_HIGH_REG LP_AON_STORE3_REG
|
||||||
#define RTC_XTAL_FREQ_REG LP_AON_STORE4_REG
|
#define RTC_XTAL_FREQ_REG LP_AON_STORE4_REG
|
||||||
#define RTC_APB_FREQ_REG LP_AON_STORE5_REG
|
#define RTC_ENTRY_LENGTH_REG LP_AON_STORE5_REG
|
||||||
#define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG
|
#define RTC_ENTRY_ADDR_REG LP_AON_STORE6_REG
|
||||||
#define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG
|
#define RTC_RESET_CAUSE_REG LP_AON_STORE6_REG
|
||||||
#define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG
|
#define RTC_MEMORY_CRC_REG LP_AON_STORE7_REG
|
||||||
|
#define LIGHT_SLEEP_WAKE_STUB_ADDR_REG LP_AON_STORE8_REG
|
||||||
|
#define SLEEP_MODE_REG LP_AON_STORE9_REG
|
||||||
|
|
||||||
#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code.
|
#define RTC_DISABLE_ROM_LOG ((1 << 0) | (1 << 16)) //!< Disable logging from the ROM code.
|
||||||
|
|
||||||
|
153
components/riscv/include/riscv/rvsleep-frames.h
Normal file
153
components/riscv/include/riscv/rvsleep-frames.h
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __RVSLEEP_FRAMES_H__
|
||||||
|
#define __RVSLEEP_FRAMES_H__
|
||||||
|
|
||||||
|
/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
|
||||||
|
#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n))
|
||||||
|
|
||||||
|
#ifdef STRUCT_BEGIN
|
||||||
|
#undef STRUCT_BEGIN
|
||||||
|
#undef STRUCT_FIELD
|
||||||
|
#undef STRUCT_AFIELD
|
||||||
|
#undef STRUCT_END
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||||
|
#ifdef __clang__
|
||||||
|
#define STRUCT_BEGIN .set RV_STRUCT_OFFSET, 0
|
||||||
|
#define STRUCT_FIELD(ctype,size,asname,name) .set asname, RV_STRUCT_OFFSET; .set RV_STRUCT_OFFSET, asname + size
|
||||||
|
#define STRUCT_AFIELD(ctype,size,asname,name,n) .set asname, RV_STRUCT_OFFSET;\
|
||||||
|
.set RV_STRUCT_OFFSET, asname + (size)*(n);
|
||||||
|
#define STRUCT_END(sname) .set sname##Size, RV_STRUCT_OFFSET;
|
||||||
|
#else // __clang__
|
||||||
|
#define STRUCT_BEGIN .pushsection .text; .struct 0
|
||||||
|
#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size
|
||||||
|
#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n)
|
||||||
|
#define STRUCT_END(sname) sname##Size:; .popsection
|
||||||
|
#endif // __clang__
|
||||||
|
#else
|
||||||
|
#define STRUCT_BEGIN typedef struct {
|
||||||
|
#define STRUCT_FIELD(ctype,size,asname,name) ctype name;
|
||||||
|
#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n];
|
||||||
|
#define STRUCT_END(sname) } sname;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -------------------------------------------------------------------------------
|
||||||
|
* RISC-V CORE CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP
|
||||||
|
* -------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
STRUCT_BEGIN
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MEPC, mepc) /* Machine Exception Program Counter */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_RA, ra) /* Return address */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_SP, sp) /* Stack pointer */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_GP, gp) /* Global pointer */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_TP, tp) /* Thread pointer */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T0, t0) /* Temporary/alternate link register */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T1, t1) /* t1-2: Temporaries */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T2, t2)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S0, s0) /* Saved register/frame pointer */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S1, s1) /* Saved register */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A0, a0) /* a0-1: Function arguments/return address */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A1, a1)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A2, a2) /* a2-7: Function arguments */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A3, a3)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A4, a4)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A5, a5)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A6, a6)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_A7, a7)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S2, s2) /* s2-11: Saved registers */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S3, s3)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S4, s4)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S5, s5)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S6, s6)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S7, s7)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S8, s8)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S9, s9)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S10, s10)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_S11, s11)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T3, t3) /* t3-6: Temporaries */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T4, t4)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T5, t5)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_T6, t6)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSTATUS, mstatus) /* Machine Status */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVEC, mtvec) /* Machine Trap-Vector Base Address */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MCAUSE, mcause) /* Machine Trap Cause */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MTVAL, mtval) /* Machine Trap Value */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIE, mie) /* Machine intr enable */
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIP, mip) /* Machine intr pending */
|
||||||
|
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMUFUNC, pmufunc) /* A field is used to identify whether it is going
|
||||||
|
* to sleep or has just been awakened. We use the
|
||||||
|
* lowest 2 bits as indication infomation, 3 means
|
||||||
|
* being awakened, 1 means going to sleep */
|
||||||
|
STRUCT_END(RvCoreCriticalSleepFrame)
|
||||||
|
|
||||||
|
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||||
|
#define RV_SLEEP_CTX_SZ1 RvCoreCriticalSleepFrameSize
|
||||||
|
#else
|
||||||
|
#define RV_SLEEP_CTX_SZ1 sizeof(RvCoreCriticalSleepFrame)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sleep stack frame size, after align up to 16 bytes boundary
|
||||||
|
*/
|
||||||
|
#define RV_SLEEP_CTX_FRMSZ (ALIGNUP(0x10, RV_SLEEP_CTX_SZ1))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* -------------------------------------------------------------------------------
|
||||||
|
* RISC-V CORE NON-CRITICAL REGISTER CONTEXT LAYOUT FOR SLEEP
|
||||||
|
* -------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
STRUCT_BEGIN
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MSCRATCH, mscratch)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MIDELEG, mideleg)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MISA, misa)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_TSELECT, tselect)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA1, tdata1)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_TDATA2, tdata2)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_TCONTROL, tcontrol)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG0, pmpcfg0)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPCFG1, pmpcfg1)
|
||||||
|
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_PMPADDR0, pmpaddr0)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR1, pmpaddr1)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR2, pmpaddr2)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR3, pmpaddr3)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR4, pmpaddr4)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR5, pmpaddr5)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR6, pmpaddr6)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR7, pmpaddr7)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR8, pmpaddr8)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR9, pmpaddr9)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR10, pmpaddr10)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR11, pmpaddr11)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR12, pmpaddr12)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR13, pmpaddr13)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR14, pmpaddr14)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_PMPADDR15, pmpaddr15)
|
||||||
|
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UTVEC, utvec)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_USTATUS, ustatus)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UEPC, uepc)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UCAUSE, ucause)
|
||||||
|
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCER, mpcer)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCMR, mpcmr)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_MPCCR, mpccr)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_CPU_TESTBUS_CTRL, cpu_testbus_ctrl)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCER, upcer)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCMR, upcmr)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UPCCR, upccr)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OEN, ugpio_oen)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_IN, ugpio_in)
|
||||||
|
STRUCT_FIELD (long, 4, RV_SLP_CTX_UGPIO_OUT, ugpio_out)
|
||||||
|
STRUCT_END(RvCoreNonCriticalSleepFrame)
|
||||||
|
|
||||||
|
#endif /* #ifndef __RVSLEEP_FRAMES_H__ */
|
@@ -156,3 +156,4 @@ components/espcoredump/include/port/xtensa/esp_core_dump_summary_port.h
|
|||||||
components/riscv/include/esp_private/panic_reason.h
|
components/riscv/include/esp_private/panic_reason.h
|
||||||
components/riscv/include/riscv/interrupt.h
|
components/riscv/include/riscv/interrupt.h
|
||||||
components/riscv/include/riscv/rvruntime-frames.h
|
components/riscv/include/riscv/rvruntime-frames.h
|
||||||
|
components/riscv/include/riscv/rvsleep-frames.h
|
||||||
|
Reference in New Issue
Block a user