diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index 473c43325..03ea68236 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -185,3 +185,12 @@ void esp_dport_access_int_deinit(void) #endif portEXIT_CRITICAL_ISR(&g_dport_mux); } + + +void esp_dport_access_int_abort(void) +{ + dport_core_state[0] = DPORT_CORE_STATE_IDLE; +#ifndef CONFIG_FREERTOS_UNICORE + dport_core_state[1] = DPORT_CORE_STATE_IDLE; +#endif +} diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 8b081c5ae..220516309 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/components/esp32/include/esp_dport_access.h @@ -23,6 +23,7 @@ void esp_dport_access_stall_other_cpu_start(void); void esp_dport_access_stall_other_cpu_end(void); void esp_dport_access_int_init(void); void esp_dport_access_int_deinit(void); +void esp_dport_access_int_abort(void); #if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index b3c54b12b..4d7beb55e 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -256,22 +256,31 @@ void IRAM_ATTR esp_restart(void) */ void IRAM_ATTR esp_restart_noos() { - const uint32_t core_id = xPortGetCoreID(); - const uint32_t other_core_id = core_id == 0 ? 1 : 0; - esp_cpu_stall(other_core_id); + // Disable interrupts + xt_ints_off(0xFFFFFFFF); - // other core is now stalled, can access DPORT registers directly - esp_dport_access_int_deinit(); - - // We need to disable TG0/TG1 watchdogs - // First enable RTC watchdog to be on the safe side + // Enable RTC watchdog for 1 second REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); REG_WRITE(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M | + (RTC_WDT_STG_SEL_RESET_SYSTEM << RTC_CNTL_WDT_STG0_S) | + (RTC_WDT_STG_SEL_RESET_RTC << RTC_CNTL_WDT_STG1_S) | (1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) | (1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) ); REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, 128000); + // Reset and stall the other CPU. + // CPU must be reset before stalling, in case it was running a s32c1i + // instruction. This would cause memory pool to be locked by arbiter + // to the stalled CPU, preventing current CPU from accessing this pool. + const uint32_t core_id = xPortGetCoreID(); + const uint32_t other_core_id = (core_id == 0) ? 1 : 0; + esp_cpu_reset(other_core_id); + esp_cpu_stall(other_core_id); + + // Other core is now stalled, can access DPORT registers directly + esp_dport_access_int_abort(); + // Disable TG0/TG1 watchdogs TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; TIMERG0.wdt_config0.en = 0; @@ -280,8 +289,6 @@ void IRAM_ATTR esp_restart_noos() TIMERG1.wdt_config0.en = 0; TIMERG1.wdt_wprotect=0; - // Disable all interrupts - xt_ints_off(0xFFFFFFFF); // Disable cache Cache_Read_Disable(0); @@ -322,14 +329,14 @@ void IRAM_ATTR esp_restart_noos() // Reset CPUs if (core_id == 0) { // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs. - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, - RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M); + esp_cpu_reset(1); + esp_cpu_reset(0); } else { // Running on APP CPU: need to reset PRO CPU and unstall it, // then reset APP CPU - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M); + esp_cpu_reset(0); esp_cpu_unstall(0); - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_APPCPU_RST_M); + esp_cpu_reset(1); } while(true) { ; diff --git a/components/soc/esp32/cpu_util.c b/components/soc/esp32/cpu_util.c index ecfcab4ba..bc052af98 100644 --- a/components/soc/esp32/cpu_util.c +++ b/components/soc/esp32/cpu_util.c @@ -44,6 +44,12 @@ void IRAM_ATTR esp_cpu_unstall(int cpu_id) } } +void IRAM_ATTR esp_cpu_reset(int cpu_id) +{ + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, + cpu_id == 0 ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M); +} + bool IRAM_ATTR esp_cpu_in_ocd_debug_mode() { #if CONFIG_ESP32_DEBUG_OCDAWARE diff --git a/components/soc/esp32/include/soc/cpu.h b/components/soc/esp32/include/soc/cpu.h index b56fb3dc8..05ec91776 100644 --- a/components/soc/esp32/include/soc/cpu.h +++ b/components/soc/esp32/include/soc/cpu.h @@ -85,6 +85,13 @@ void esp_cpu_stall(int cpu_id); */ void esp_cpu_unstall(int cpu_id); +/** + * @brief Reset CPU using RTC controller + * @param cpu_id ID of the CPU to reset (0 = PRO, 1 = APP) + */ +void esp_cpu_reset(int cpu_id); + + /** * @brief Returns true if a JTAG debugger is attached to CPU * OCD (on chip debug) port. diff --git a/components/soc/esp32/include/soc/rtc_cntl_reg.h b/components/soc/esp32/include/soc/rtc_cntl_reg.h index 02f8dff2c..ffcbb3c03 100644 --- a/components/soc/esp32/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32/include/soc/rtc_cntl_reg.h @@ -1718,6 +1718,7 @@ #define RTC_WDT_STG_SEL_INT 1 #define RTC_WDT_STG_SEL_RESET_CPU 2 #define RTC_WDT_STG_SEL_RESET_SYSTEM 3 +#define RTC_WDT_STG_SEL_RESET_RTC 4 #define RTC_CNTL_WDTCONFIG1_REG (DR_REG_RTCCNTL_BASE + 0x90) /* RTC_CNTL_WDT_STG0_HOLD : R/W ;bitpos:[31:0] ;default: 32'd128000 ; */