fix(esp_hw_support): add p4 rev3.0 MSPI workaround for deepsleep

This commit is contained in:
wuzhenghui
2025-10-27 20:06:09 +08:00
parent 596e32312e
commit e9da2e3606
15 changed files with 207 additions and 14 deletions
@@ -263,7 +263,11 @@ rtc_retain_mem_t* bootloader_common_get_rtc_retain_mem(void)
#ifdef BOOTLOADER_BUILD
#if ESP_ROM_HAS_LP_ROM
#if CONFIG_IDF_TARGET_ESP32P4
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW + CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE)
#else
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_LOW)
#endif
#else
/* Since the structure containing the retain_mem_t is aligned on 8 by the linker, make sure we align this
* structure size here too */
+1
View File
@@ -299,4 +299,5 @@ menu "Hardware Settings"
bool "Place esp_intr_alloc functions in IRAM" if SPI_FLASH_AUTO_SUSPEND
default y
orsource "./lowpower/port/esp32p4/Kconfig.p4_rev3_mspi_workaround"
endmenu
@@ -23,6 +23,12 @@ if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR
endif()
endif()
if(CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND)
list(APPEND srcs "port/esp32p4/p4_rev3_mspi_workaround.S")
set_property(TARGET ${COMPONENT_LIB}
APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u p4_rev3_mspi_workaround")
endif()
if(CONFIG_SOC_PM_MMU_TABLE_RETENTION_WHEN_TOP_PD AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)
list(APPEND srcs "port/${target}/sleep_mmu.c")
endif()
@@ -0,0 +1,10 @@
config P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
bool
depends on IDF_TARGET_ESP32P4
default y if ESP32P4_REV_MIN_300
config P4_REV3_MSPI_WORKAROUND_SIZE
hex
depends on IDF_TARGET_ESP32P4
default 0x100 if ESP32P4_REV_MIN_300
default 0
@@ -0,0 +1,110 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/reg_base.h"
#define HP_SYSTEM_CORE_ERR_RESP_DIS_REG (DR_REG_HP_SYS_BASE + 0x1a4)
/* Clock related */
#define DR_REG_LP_CLKRST_BASE (DR_REG_LPAON_BASE + 0x1000)
#define LP_CLKRST_HPCPU_RESET_CTRL0_REG (DR_REG_LP_CLKRST_BASE + 0x14)
#define LP_CLKRST_HPCORE0_STAT_VECTOR_SEL (1 << 15)
#define HP_SYS_CLKRST_HP_RST_EN0_REG (DR_REG_HP_SYS_CLKRST_BASE + 0xc0)
#define HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI (1 << 22)
#define HP_SYS_CLKRST_REG_RST_EN_MSPI_APB (1 << 24)
/* SPIMEM related */
#define DR_REG_FLASH_SPI0_BASE (DR_REG_HPPERIPH0_BASE + 0x8C000)
#define SPI_MEM_C_CACHE_FCTRL_REG (DR_REG_FLASH_SPI0_BASE + 0x3c)
#define SPI_MEM_C_CLOSE_AXI_INF_EN (1 << 31)
#define SPI_MEM_C_AXI_REQ_EN (1 << 0)
#define SPI_MEM_C_MMU_ITEM_INDEX_REG (DR_REG_FLASH_SPI0_BASE + 0x380)
#define SPI_MEM_C_MMU_ITEM_CONTENT_REG (DR_REG_FLASH_SPI0_BASE + 0x37c)
.macro REG_SET_BIT addr, value
li a0, \addr
li a1, \value
lw a2, (a0)
or a2, a2, a1
sw a2, (a0)
.endm
.macro REG_CLR_BIT addr, value
li a0, \addr
/* Since all our parameters will be constants, we can pre-calculate it at assemble time */
li a1, ~\value
lw a2, (a0)
and a2, a2, a1
sw a2, (a0)
.endm
.macro REG_WRITE addr, value
li a0, \addr
li a1, \value
sw a1, (a0)
.endm
.macro REG_READ addr
li a0, \addr
lw a1, (a0)
.endm
.macro DELAY_US us
li t3, (40 * \us) /* CPU @40MHz after reset */
csrr t0, cycle
add t1, t0, t3
1: csrr t2, cycle
blt t2, t1, 1b
.endm
/**
* @brief Workaround for MSPI issues on ESP32-P4 revision 3
*
* This function implements a workaround for MSPI-related issues on ESP32-P4 revision 3.
* It performs 2 flash dummy reads to stabilize the MSPI functionality before jumping to
* ROM code after deepsleep wakeup.
*/
.global p4_rev3_mspi_workaround
.section .p4_rev3_mspi_workaround.rtc_text,"ax"
p4_rev3_mspi_workaround:
# Recover the reset vector to HP ROM
REG_SET_BIT LP_CLKRST_HPCPU_RESET_CTRL0_REG, LP_CLKRST_HPCORE0_STAT_VECTOR_SEL
# Clear the bit to close AXI interface and then set the AXI request enable bit
REG_CLR_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_CLOSE_AXI_INF_EN
REG_SET_BIT SPI_MEM_C_CACHE_FCTRL_REG, SPI_MEM_C_AXI_REQ_EN
# Set 1 mspi mmu entry for axi addr to flash addr
REG_WRITE SPI_MEM_C_MMU_ITEM_INDEX_REG, 0
REG_WRITE SPI_MEM_C_MMU_ITEM_CONTENT_REG, 0x1000
# Disable cpu get error response
REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0x7
# Perform dummy reads
REG_READ 0x80000000
# Perform dummy reads again
REG_READ 0x80000080
# Delay 1us to wait MSPI read transmission done
DELAY_US 1
# Enable cpu get error response
REG_WRITE HP_SYSTEM_CORE_ERR_RESP_DIS_REG, 0
# Reset MSPI AXI and APB interfaces
REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI
REG_SET_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB
REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI
REG_CLR_BIT HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_APB
# Jump to HP ROM first stage boot code
li a5, 0x4fc00000
jr a5
@@ -30,6 +30,7 @@
#include "hal/pmu_hal.h"
#include "hal/psram_ctrlr_ll.h"
#include "hal/lp_sys_ll.h"
#include "hal/lp_clkrst_ll.h"
#include "hal/clk_gate_ll.h"
#include "esp_private/esp_pmu.h"
#include "pmu_param.h"
@@ -419,6 +420,10 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
#endif
rtc_clk_mpll_disable();
}
} else {
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
lp_clkrst_ll_boot_from_lp_ram(true);
#endif
}
@@ -442,12 +447,16 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
;
}
#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM
// Enable PSRAM chip power supply after deepsleep request rejected
if (dslp) {
#if CONFIG_SPIRAM && CONFIG_ESP_LDO_RESERVE_PSRAM
// Enable PSRAM chip power supply after deepsleep request rejected
ldo_ll_enable(LDO_ID2UNIT(CONFIG_ESP_LDO_CHAN_PSRAM_DOMAIN), true);
}
#endif
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
// Set reset vector back to HP ROM after deepsleep request rejected
lp_clkrst_ll_boot_from_lp_ram(false);
#endif
}
return pmu_sleep_finish(dslp);
}
+12 -3
View File
@@ -32,6 +32,12 @@
#define SRAM_HIGH_END SRAM_HIGH_START + SRAM_HIGH_SIZE
#endif
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
#define MSPI_WORKAROUND_SIZE CONFIG_P4_REV3_MSPI_WORKAROUND_SIZE
#else
#define MSPI_WORKAROUND_SIZE 0x0
#endif
#define IDROM_SEG_SIZE (CONFIG_MMU_PAGE_SIZE << 10)
#define LP_ROM_DRAM_START 0x5010fa80 // Value taken from ROM elf, includes LP ROM stack
@@ -90,14 +96,17 @@ MEMORY
/* (See irom_seg for meaning of 0x20 offset in the above.) */
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
/* Used to store the deep sleep workaround code of P4 rev3.0. The reset vector will be set here before the chip enters sleep. */
rev3_mspi_workaround_seg(RWX) : org = 0x50108000, len = MSPI_WORKAROUND_SIZE
/**
* lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667
*/
#if CONFIG_ULP_COPROC_ENABLED
lp_ram_seg(RW) : org = 0x50108000 + RESERVE_RTC_MEM + CONFIG_ULP_COPROC_RESERVE_MEM,
lp_ram_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM + CONFIG_ULP_COPROC_RESERVE_MEM,
len = 0x8000 - CONFIG_ULP_COPROC_RESERVE_MEM - RESERVE_RTC_MEM - LP_ROM_DRAM_SIZE
#else
lp_ram_seg(RW) : org = 0x50108000 + RESERVE_RTC_MEM, len = 0x8000 - RESERVE_RTC_MEM
lp_ram_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE + RESERVE_RTC_MEM, len = 0x8000 - RESERVE_RTC_MEM - MSPI_WORKAROUND_SIZE
#endif // CONFIG_ULP_COPROC_ENABLED
/* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value.
@@ -108,7 +117,7 @@ MEMORY
The aim of this is to keep data that will not be moved around and have a fixed address.
This segment is placed at the beginning of LP RAM, as the end of LP RAM is occupied by LP ROM stack/data
*/
lp_reserved_seg(RW) : org = 0x50108000, len = RESERVE_RTC_MEM
lp_reserved_seg(RW) : org = 0x50108000 + MSPI_WORKAROUND_SIZE, len = RESERVE_RTC_MEM
/* PSRAM seg */
extern_ram_seg(RWX) : org = 0x48000000, len = IDROM_SEG_SIZE
@@ -115,6 +115,15 @@ SECTIONS
ALIGNED_SYMBOL(4, _rtc_force_slow_end)
} > lp_ram_seg
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
.rtc.p4_rev3_mspi_workaround :
{
ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_start)
KEEP (*(.p4_rev3_mspi_workaround.rtc_text .p4_rev3_mspi_workaround.rtc_text.*))
ALIGNED_SYMBOL(4, _rtc_p4_rev3_mspi_workaround_end)
} > rev3_mspi_workaround_seg
#endif
/**
* This section holds RTC data that should have fixed addresses.
* The data are not initialized at power-up and are retained during deep
@@ -0,0 +1,35 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// The LL layer for ESP32-P4 LP_CLKRST register operations
#pragma once
#include <stdbool.h>
#include <stdlib.h>
#include "soc/soc.h"
#include "soc/lp_clkrst_struct.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Select CPU reset vector
* @param boot_from_lp_ram
* true: boot from LP TCM RAM: 0x50108000
* false: boot from HP TCM ROM: 0x4FC00000
*/
__attribute__((always_inline))
static inline void lp_clkrst_ll_boot_from_lp_ram(bool boot_from_lp_ram)
{
LP_AON_CLKRST.hpcpu_reset_ctrl0.hpcore0_stat_vector_sel = !boot_from_lp_ram;
}
#ifdef __cplusplus
}
#endif
@@ -13,6 +13,7 @@
#include "soc/soc.h"
#include "soc/lp_system_struct.h"
#include "hal/misc.h"
#include "hal/config.h"
#include "esp32p4/rom/rtc.h"
+6 -1
View File
@@ -121,6 +121,9 @@ const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_m
extern int _data_start_low, _data_start_high, _heap_start_low, _heap_start_high, _iram_start, _iram_end, _rtc_force_slow_end;
#else
extern int _data_start, _heap_start, _iram_start, _iram_end, _rtc_force_slow_end;
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
extern int _rtc_p4_rev3_mspi_workaround_start, _rtc_p4_rev3_mspi_workaround_end;
#endif
#endif
extern int _tcm_text_start, _tcm_data_end;
extern int _rtc_reserved_start, _rtc_reserved_end;
@@ -154,5 +157,7 @@ SOC_RESERVE_MEMORY_REGION( SOC_EXTRAM_LOW, SOC_EXTRAM_HIGH, extram_region);
SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data);
/* This includes any memory reserved for ULP RAM */
SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_end, (intptr_t)&_rtc_force_slow_end, rtcram_data);
#if CONFIG_P4_REV3_MSPI_CRASH_AFTER_POWER_UP_WORKAROUND
SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_p4_rev3_mspi_workaround_start, (intptr_t)&_rtc_p4_rev3_mspi_workaround_end, p4_rev3_mspi_workaround);
#endif
#endif
@@ -4,5 +4,5 @@ set(srcs "deep_sleep_example_main.c"
set(includes ".")
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES nvs_flash ulp esp_driver_gpio
PRIV_REQUIRES nvs_flash esp_driver_gpio
INCLUDE_DIRS ${includes})
@@ -2,8 +2,6 @@
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
CONFIG_EXAMPLE_EXT1_WAKEUP=n
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=512
CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_RTC_CLK_SRC_INT_RC=y
CONFIG_PARTITION_TABLE_CUSTOM=y
@@ -9,8 +9,6 @@ CONFIG_EXAMPLE_EXT1_WAKEUP=n
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=80
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=512
CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_RTC_CLK_SRC_INT_RC=y
CONFIG_PARTITION_TABLE_CUSTOM=y
@@ -1,5 +1,3 @@
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=512
CONFIG_LIBC_TIME_SYSCALL_USE_RTC_HRT=y
CONFIG_RTC_CLK_SRC_INT_RC=y
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y