fix(esp_system): fix mspi write stuck after cpu/digital reset on c5/c61

This commit is contained in:
wuzhenghui
2025-11-25 21:40:51 +08:00
parent cefe58de7d
commit 925a339e32
8 changed files with 59 additions and 1 deletions
@@ -43,6 +43,7 @@
#include "hal/lpwdt_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "hal/brownout_ll.h"
#include "hal/axi_icm_ll.h"
ESP_LOG_ATTR_TAG(TAG, "boot.esp32c5");
@@ -85,6 +86,9 @@ static void bootloader_super_wdt_auto_feed(void)
static inline void bootloader_hardware_init(void)
{
// Clear bit reset_event_bypass to ensure that the system bus is also reset during a core reset (WDT),
// preventing bus freezing caused by an incorrect MSPI core reset in ROM.
axi_icm_ll_reset_with_core_reset(true);
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
regi2c_ctrl_ll_master_configure_clock();
}
@@ -44,6 +44,7 @@
#include "hal/lpwdt_ll.h"
#include "hal/regi2c_ctrl_ll.h"
#include "hal/brownout_ll.h"
#include "hal/axi_icm_ll.h"
ESP_LOG_ATTR_TAG(TAG, "boot.esp32c61");
@@ -86,6 +87,9 @@ static void bootloader_super_wdt_auto_feed(void)
static inline void bootloader_hardware_init(void)
{
// Clear bit reset_event_bypass to ensure that the system bus is also reset during a core reset (WDT),
// preventing bus freezing caused by an incorrect MSPI core reset in ROM.
axi_icm_ll_reset_with_core_reset(true);
_regi2c_ctrl_ll_master_enable_clock(true); // keep ana i2c mst clock always enabled in bootloader
regi2c_ctrl_ll_master_configure_clock();
}
@@ -48,6 +48,7 @@ void esp_system_reset_modules_on_exit(void)
modem_lpcon_ll_reset_all(&MODEM_LPCON);
#endif
// Set Peripheral clk rst
SET_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); // Must reset mspi AXI before reset mspi core.
SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
@@ -62,6 +63,7 @@ void esp_system_reset_modules_on_exit(void)
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); // Must release mspi core reset before mspi AXI.
CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
@@ -49,6 +49,7 @@ void esp_system_reset_modules_on_exit(void)
#endif
// Set Peripheral clk rst
SET_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); // Must reset mspi AXI before reset mspi core.
SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
@@ -61,6 +62,7 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); // Must release mspi core reset before mspi AXI.
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
@@ -37,6 +37,7 @@ void esp_system_reset_modules_on_exit(void)
}
// Set Peripheral clk rst
SET_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); // Must reset mspi AXI before reset mspi core.
SET_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
SET_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
SET_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
@@ -50,6 +51,7 @@ void esp_system_reset_modules_on_exit(void)
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN); // Must release mspi core reset before mspi AXI.
CLEAR_PERI_REG_MASK(PCR_UART0_CONF_REG, PCR_UART0_RST_EN);
CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "hal/assert.h"
#include "soc/hp_system_struct.h"
#include "soc/pcr_struct.h"
#ifdef __cplusplus
extern "C" {
@@ -36,6 +37,15 @@ static inline void axi_icm_ll_set_cache_arbiter_prio(uint8_t priority)
HP_SYSTEM.axi_mst_pri.cache_priority = priority;
}
/**
* @brief Reset system bus with soc core reset.
* @param reset_with_core_reset True to reset system bus with soc core reset.
*/
static inline void axi_icm_ll_reset_with_core_reset(bool reset_with_core_reset)
{
PCR.reset_event_bypass.reset_event_bypass = !reset_with_core_reset;
}
#ifdef __cplusplus
}
#endif
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "hal/assert.h"
#include "soc/hp_system_struct.h"
#include "soc/pcr_struct.h"
#ifdef __cplusplus
extern "C" {
@@ -36,6 +37,15 @@ static inline void axi_icm_ll_set_cache_arbiter_prio(uint8_t priority)
HP_SYSTEM.system_axi_mst_pri.system_cache_priority = priority;
}
/**
* @brief Reset system bus with soc core reset.
* @param reset_with_core_reset True to reset system bus with soc core reset.
*/
static inline void axi_icm_ll_reset_with_core_reset(bool reset_with_core_reset)
{
PCR.reset_event_bypass.reset_event_bypass = !reset_with_core_reset;
}
#ifdef __cplusplus
}
#endif
@@ -1774,6 +1774,30 @@ typedef union {
uint32_t val;
} pcr_timergroup_xtal_conf_reg_t;
/** Type of reset_event_bypass register
* reset event bypass backdoor configuration register
*/
typedef union {
struct {
/** reset_event_bypass_apm : R/W; bitpos: [0]; default: 0;
* This field is used to control reset event relationship for
* tee_reg/apm_reg/hp_system_reg. 1: tee_reg/apm_reg/hp_system_reg will only be reset
* by power-reset. some reset event will be bypass. 0: tee_reg/apm_reg/hp_system_reg
* will not only be reset by power-reset, but also some reset event.
*/
uint32_t reset_event_bypass_apm:1;
/** reset_event_bypass : R/W; bitpos: [1]; default: 1;
* This field is used to control reset event relationship for system-bus. 1: system
* bus (including arbiter/router) will only be reset by power-reset. some reset event
* will be bypass. 0: system bus (including arbiter/router) will not only be reset by
* power-reset, but also some reset event.
*/
uint32_t reset_event_bypass:1;
uint32_t reserved_2:30;
};
uint32_t val;
} pcr_reset_event_bypass_reg_t;
/** Type of regdma_conf register
* REGDMA configuration register
*/
@@ -1966,7 +1990,7 @@ typedef struct {
uint32_t reserved_128;
volatile pcr_timergroup_wdt_conf_reg_t timergroup_wdt_conf;
volatile pcr_timergroup_xtal_conf_reg_t timergroup_xtal_conf;
uint32_t reserved_134;
volatile pcr_reset_event_bypass_reg_t reset_event_bypass;
volatile pcr_regdma_conf_reg_t regdma_conf;
volatile pcr_etm_conf_reg_t etm_conf;
uint32_t reserved_140[6];