Files
esp-idf/components/esp_system/port/soc/esp32h2/system_internal.c
T
Xiao Xufeng 40dd5e3957 dma: fixed issue that DMA are not reset when CPU reset
When DMA keep writing the memory, some data may be corrupted after reset. For example, the stack of bootloader may be overwritten and failed to boot until a higher scope of reset (Core).

Also removed the DPORT_PERIP_RST_EN_REG alias on ESP32S2. Now it's the same as some following chips (EN0).
2025-10-20 01:34:32 +08:00

146 lines
5.7 KiB
C

/*
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "sdkconfig.h"
#include "esp_macros.h"
#include "esp_system.h"
#include "esp_private/system_internal.h"
#include "esp_attr.h"
#include "esp_log.h"
#include "esp_rom_sys.h"
#include "riscv/rv_utils.h"
#include "riscv/interrupt.h"
#include "esp_rom_serial_output.h"
#include "soc/gpio_reg.h"
#include "esp_cpu.h"
#include "soc/rtc.h"
#include "esp_private/rtc_clk.h"
#include "soc/rtc_periph.h"
#include "soc/uart_reg.h"
#include "hal/wdt_hal.h"
#include "hal/uart_ll.h"
#include "hal/spimem_flash_ll.h"
#include "hal/uart_ll.h"
#include "esp_private/cache_err_int.h"
#include "esp_private/mspi_timing_tuning.h"
#include "esp32h2/rom/cache.h"
#include "esp32h2/rom/rtc.h"
#include "soc/pcr_reg.h"
void esp_system_reset_modules_on_exit(void)
{
// Flush any data left in UART FIFOs before reset the UART peripheral
for (int i = 0; i < SOC_UART_HP_NUM; ++i) {
if (uart_ll_is_enabled(i)) {
esp_rom_output_tx_wait_idle(i);
}
}
// Set Peripheral clk rst
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);
SET_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
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);
CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.
SET_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
SET_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
SET_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
SET_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
SET_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
SET_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
SET_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_AES_CONF_REG, PCR_AES_RST_EN);
CLEAR_PERI_REG_MASK(PCR_DS_CONF_REG, PCR_DS_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECC_CONF_REG, PCR_ECC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ECDSA_CONF_REG, PCR_ECDSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_HMAC_CONF_REG, PCR_HMAC_RST_EN);
CLEAR_PERI_REG_MASK(PCR_RSA_CONF_REG, PCR_RSA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SHA_CONF_REG, PCR_SHA_RST_EN);
// UART's sclk is controlled in the PCR register and does not reset with the UART module. The ROM missed enabling
// it when initializing the ROM UART. If it is not turned on, it will trigger LP_WDT in the ROM.
uart_ll_sclk_enable(&UART0);
}
/* "inner" restart function for after RTOS, interrupts & anything else on this
* core are already stopped. Stalls other core, resets hardware,
* triggers restart.
*/
void esp_restart_noos(void)
{
// Disable interrupts
rv_utils_intr_global_disable();
// Enable RTC watchdog for 1 second
wdt_hal_context_t rtc_wdt_ctx;
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_SYSTEM);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE1, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
//Enable flash boot mode so that flash booting after restart is protected by the RTC WDT.
wdt_hal_set_flashboot_en(&rtc_wdt_ctx, true);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
// Disable TG0/TG1 watchdogs
wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
wdt_hal_write_protect_disable(&wdt0_context);
wdt_hal_disable(&wdt0_context);
wdt_hal_write_protect_enable(&wdt0_context);
wdt_hal_context_t wdt1_context = {.inst = WDT_MWDT1, .mwdt_dev = &TIMERG1};
wdt_hal_write_protect_disable(&wdt1_context);
wdt_hal_disable(&wdt1_context);
wdt_hal_write_protect_enable(&wdt1_context);
// Disable cache
Cache_Disable_ICache();
// 2nd stage bootloader reconfigures SPI flash signals.
// Reset them to the defaults expected by ROM.
WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
esp_system_reset_modules_on_exit();
#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
/**
* Turn down MSPI speed
*
* We set MSPI clock to a high speed one before, ROM doesn't have such high speed clock source option.
* This function will change clock source to a ROM supported one when system restarts.
*/
mspi_timing_change_speed_mode_cache_safe(true);
#endif //#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP
// Set CPU back to XTAL source, same as hard reset, but keep BBPLL on so that USB Serial JTAG can log at 1st stage bootloader.
#if !CONFIG_IDF_ENV_FPGA
rtc_clk_cpu_set_to_default_config();
#endif
// Reset CPU
esp_rom_software_reset_cpu(0);
ESP_INFINITE_LOOP();
}