Merge branch 'bugfix/customer_baidu_int_wdt_v4.0' into 'release/v4.0'
backport v4.0: add soft solution for esp32 eco3 live lock issue See merge request espressif/esp-idf!9214
This commit is contained in:
commit
f7742dd9cc
6 changed files with 332 additions and 5 deletions
|
@ -355,6 +355,11 @@ esp_err_t esp_efuse_update_secure_version(uint32_t secure_version);
|
||||||
*/
|
*/
|
||||||
void esp_efuse_init(uint32_t offset, uint32_t size);
|
void esp_efuse_init(uint32_t offset, uint32_t size);
|
||||||
|
|
||||||
|
inline static bool soc_has_cache_lock_bug(void)
|
||||||
|
{
|
||||||
|
return (esp_efuse_get_chip_ver() == 3);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
menu "ESP32-specific"
|
menu "ESP32-specific"
|
||||||
|
|
||||||
|
config ESP32_ECO3_CACHE_LOCK_FIX
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
depends on !FREERTOS_UNICORE && ESP32_SPIRAM_SUPPORT
|
||||||
|
|
||||||
choice ESP32_REV_MIN
|
choice ESP32_REV_MIN
|
||||||
prompt "Minimum Supported ESP32 Revision"
|
prompt "Minimum Supported ESP32 Revision"
|
||||||
default ESP32_REV_MIN_0
|
default ESP32_REV_MIN_0
|
||||||
|
@ -15,6 +20,7 @@ menu "ESP32-specific"
|
||||||
bool "Rev 2"
|
bool "Rev 2"
|
||||||
config ESP32_REV_MIN_3
|
config ESP32_REV_MIN_3
|
||||||
bool "Rev 3"
|
bool "Rev 3"
|
||||||
|
select ESP_INT_WDT if ESP32_ECO3_CACHE_LOCK_FIX
|
||||||
endchoice
|
endchoice
|
||||||
|
|
||||||
config ESP32_REV_MIN
|
config ESP32_REV_MIN
|
||||||
|
|
|
@ -386,6 +386,10 @@ void start_cpu0_default(void)
|
||||||
esp_int_wdt_init();
|
esp_int_wdt_init();
|
||||||
//Initialize the interrupt watch dog for CPU0.
|
//Initialize the interrupt watch dog for CPU0.
|
||||||
esp_int_wdt_cpu_init();
|
esp_int_wdt_cpu_init();
|
||||||
|
#else
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||||
|
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
esp_cache_err_int_init();
|
esp_cache_err_int_init();
|
||||||
esp_crosscore_int_init();
|
esp_crosscore_int_init();
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
#include <xtensa/corebits.h>
|
#include <xtensa/corebits.h>
|
||||||
#include <xtensa/config/system.h>
|
#include <xtensa/config/system.h>
|
||||||
#include "freertos/xtensa_context.h"
|
#include "freertos/xtensa_context.h"
|
||||||
|
#include "freertos/xtensa_rtos.h"
|
||||||
#include "esp_private/panic_reason.h"
|
#include "esp_private/panic_reason.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/dport_reg.h"
|
#include "soc/dport_reg.h"
|
||||||
|
#include "soc/timer_group_reg.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
@ -37,7 +39,23 @@ Interrupt , a high-priority interrupt, is used for several things:
|
||||||
#define L4_INTR_A4_OFFSET 8
|
#define L4_INTR_A4_OFFSET 8
|
||||||
.data
|
.data
|
||||||
_l4_intr_stack:
|
_l4_intr_stack:
|
||||||
.space L4_INTR_STACK_SIZE
|
.space L4_INTR_STACK_SIZE*portNUM_PROCESSORS /* This allocates stacks for each individual CPU. */
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_ESP_INT_WDT
|
||||||
|
.global _l4_intr_livelock_counter
|
||||||
|
.global _l4_intr_livelock_max
|
||||||
|
.align 16
|
||||||
|
_l4_intr_livelock_counter:
|
||||||
|
.word 0
|
||||||
|
_l4_intr_livelock_max:
|
||||||
|
.word 0
|
||||||
|
_l4_intr_livelock_sync:
|
||||||
|
.word 0, 0
|
||||||
|
_l4_intr_livelock_app:
|
||||||
|
.word 0
|
||||||
|
_l4_intr_livelock_pro:
|
||||||
|
.word 0
|
||||||
|
#endif
|
||||||
|
|
||||||
.section .iram1,"ax"
|
.section .iram1,"ax"
|
||||||
.global xt_highint4
|
.global xt_highint4
|
||||||
|
@ -52,8 +70,24 @@ xt_highint4:
|
||||||
bnez a0, .handle_dport_access_int
|
bnez a0, .handle_dport_access_int
|
||||||
#endif // CONFIG_FREERTOS_UNICORE
|
#endif // CONFIG_FREERTOS_UNICORE
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_ESP_INT_WDT
|
||||||
|
/* See if we're here for the tg1 watchdog interrupt */
|
||||||
|
rsr a0, INTERRUPT
|
||||||
|
extui a0, a0, ETS_T1_WDT_INUM, 1
|
||||||
|
beqz a0, 1f
|
||||||
|
|
||||||
|
wsr a5, depc /* use DEPC as temp storage */
|
||||||
|
movi a0, _l4_intr_livelock_counter
|
||||||
|
l32i a0, a0, 0
|
||||||
|
movi a5, _l4_intr_livelock_max
|
||||||
|
l32i a5, a5, 0
|
||||||
|
bltu a0, a5, .handle_livelock_int /* _l4_intr_livelock_counter < _l4_intr_livelock_max */
|
||||||
|
|
||||||
|
rsr a5, depc /* restore a5 */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Allocate exception frame and save minimal context. */
|
/* Allocate exception frame and save minimal context. */
|
||||||
mov a0, sp
|
1: mov a0, sp
|
||||||
addi sp, sp, -XT_STK_FRMSZ
|
addi sp, sp, -XT_STK_FRMSZ
|
||||||
s32i a0, sp, XT_STK_A1
|
s32i a0, sp, XT_STK_A1
|
||||||
#if XCHAL_HAVE_WINDOWED
|
#if XCHAL_HAVE_WINDOWED
|
||||||
|
@ -129,6 +163,257 @@ xt_highint4:
|
||||||
rfi 4
|
rfi 4
|
||||||
|
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX && CONFIG_ESP_INT_WDT
|
||||||
|
|
||||||
|
/*
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Macro intr_matrix_map - Attach an CPU interrupt to a hardware source.
|
||||||
|
|
||||||
|
Input : "addr" - Interrupt map configuration base address
|
||||||
|
Input : "src" - Interrupt source.
|
||||||
|
Input : "inum" - Interrupt number.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
.macro intr_matrix_map addr src inum
|
||||||
|
movi a2, \src
|
||||||
|
slli a2, a2, 2
|
||||||
|
movi a3, \addr
|
||||||
|
add a3, a3, a2
|
||||||
|
movi a2, \inum
|
||||||
|
s32i a2, a3, 0
|
||||||
|
memw
|
||||||
|
.endm
|
||||||
|
|
||||||
|
/*
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
Macro wdt_clr_intr_status - Clear the WDT interrupt status.
|
||||||
|
Macro wdt_feed - Feed the WDT.
|
||||||
|
|
||||||
|
Input : "dev" - Beginning address of the peripheral registers
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TIMG1_REG_OFFSET(reg) ((reg) - REG_TIMG_BASE(1))
|
||||||
|
#define TIMG1_WDTWPROTECT_OFFSET TIMG1_REG_OFFSET(TIMG_WDTWPROTECT_REG(1))
|
||||||
|
#define TIMG1_INT_CLR_OFFSET TIMG1_REG_OFFSET(TIMG_INT_CLR_TIMERS_REG(1))
|
||||||
|
#define TIMG1_WDT_STG0_HOLD_OFFSET TIMG1_REG_OFFSET(TIMG_WDTCONFIG2_REG(1))
|
||||||
|
#define TIMG1_WDT_STG1_HOLD_OFFSET TIMG1_REG_OFFSET(TIMG_WDTCONFIG3_REG(1))
|
||||||
|
#define TIMG1_WDT_FEED_OFFSET TIMG1_REG_OFFSET(TIMG_WDTFEED_REG(1))
|
||||||
|
|
||||||
|
.macro wdt_clr_intr_status dev
|
||||||
|
movi a2, \dev
|
||||||
|
movi a3, TIMG_WDT_WKEY_VALUE
|
||||||
|
s32i a3, a2, TIMG1_WDTWPROTECT_OFFSET /* disable write protect */
|
||||||
|
memw
|
||||||
|
l32i a4, a2, TIMG1_INT_CLR_OFFSET
|
||||||
|
memw
|
||||||
|
movi a3, 4
|
||||||
|
or a3, a4, a3
|
||||||
|
s32i a3, a2, TIMG1_INT_CLR_OFFSET /* clear 1st stage timeout interrupt */
|
||||||
|
memw
|
||||||
|
movi a3, 0
|
||||||
|
s32i a3, a2, TIMG1_WDTWPROTECT_OFFSET /* enable write protect */
|
||||||
|
memw
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro wdt_feed dev
|
||||||
|
movi a2, \dev
|
||||||
|
movi a3, TIMG_WDT_WKEY_VALUE
|
||||||
|
s32i a3, a2, TIMG1_WDTWPROTECT_OFFSET /* disable write protect */
|
||||||
|
memw
|
||||||
|
movi a4, _l4_intr_livelock_max
|
||||||
|
l32i a4, a4, 0
|
||||||
|
memw
|
||||||
|
addi a4, a4, 1
|
||||||
|
movi a3, (CONFIG_ESP_INT_WDT_TIMEOUT_MS<<1)
|
||||||
|
quou a3, a3, a4
|
||||||
|
s32i a3, a2, TIMG1_WDT_STG0_HOLD_OFFSET /* set timeout before interrupt */
|
||||||
|
memw
|
||||||
|
movi a3, (CONFIG_ESP_INT_WDT_TIMEOUT_MS<<2)
|
||||||
|
s32i a3, a2, TIMG1_WDT_STG1_HOLD_OFFSET /* set timeout before system reset */
|
||||||
|
memw
|
||||||
|
movi a3, 1
|
||||||
|
s32i a3, a2, TIMG1_WDT_FEED_OFFSET /* feed wdt */
|
||||||
|
memw
|
||||||
|
movi a3, 0
|
||||||
|
s32i a3, a2, TIMG1_WDTWPROTECT_OFFSET /* enable write protect */
|
||||||
|
memw
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.handle_livelock_int:
|
||||||
|
|
||||||
|
getcoreid a5
|
||||||
|
|
||||||
|
/* Save A2, A3, A4 so we can use those registers */
|
||||||
|
movi a0, L4_INTR_STACK_SIZE
|
||||||
|
mull a5, a5, a0
|
||||||
|
movi a0, _l4_intr_stack
|
||||||
|
add a0, a0, a5
|
||||||
|
s32i a2, a0, L4_INTR_A2_OFFSET
|
||||||
|
s32i a3, a0, L4_INTR_A3_OFFSET
|
||||||
|
s32i a4, a0, L4_INTR_A4_OFFSET
|
||||||
|
|
||||||
|
/* Here, we can use a0, a2, a3, a4, a5 registers */
|
||||||
|
getcoreid a5
|
||||||
|
|
||||||
|
rsil a0, CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL /* disable nested interrupt */
|
||||||
|
|
||||||
|
beqz a5, 1f
|
||||||
|
movi a2, _l4_intr_livelock_app
|
||||||
|
l32i a3, a2, 0
|
||||||
|
addi a3, a3, 1
|
||||||
|
s32i a3, a2, 0
|
||||||
|
|
||||||
|
/* Dual core synchronization, ensuring that both cores enter interrupts */
|
||||||
|
1: movi a4, 0x1
|
||||||
|
movi a2, _l4_intr_livelock_sync
|
||||||
|
addx4 a3, a5, a2
|
||||||
|
s32i a4, a3, 0
|
||||||
|
|
||||||
|
1: movi a2, _l4_intr_livelock_sync
|
||||||
|
movi a3, 1
|
||||||
|
addx4 a3, a3, a2
|
||||||
|
l32i a2, a2, 0
|
||||||
|
l32i a3, a3, 0
|
||||||
|
and a2, a2, a3
|
||||||
|
beqz a2, 1b
|
||||||
|
|
||||||
|
beqz a5, 1f /* Pro cpu (Core 0) jump bypass */
|
||||||
|
|
||||||
|
movi a2, _l4_intr_livelock_app
|
||||||
|
l32i a2, a2, 0
|
||||||
|
bnei a2, 2, 1f
|
||||||
|
movi a2, _l4_intr_livelock_counter /* _l4_intr_livelock_counter++ */
|
||||||
|
l32i a3, a2, 0
|
||||||
|
addi a3, a3, 1
|
||||||
|
s32i a3, a2, 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
The delay time can be calculated by the following formula:
|
||||||
|
T = ceil(0.25 + max(t1, t2)) us
|
||||||
|
|
||||||
|
t1 = 80 / f1, t2 = (1 + 14/N) * 20 / f2
|
||||||
|
|
||||||
|
f1: PSRAM access frequency, unit: MHz.
|
||||||
|
f2: Flash access frequency, unit: MHz.
|
||||||
|
|
||||||
|
When flash is slow/fast read, N = 1.
|
||||||
|
When flash is DOUT/DIO read, N = 2.
|
||||||
|
When flash is QOUT/QIO read, N = 4.
|
||||||
|
*/
|
||||||
|
1: rsr.ccount a2
|
||||||
|
#if defined(CONFIG_ESPTOOLPY_FLASHMODE_QIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_QOUT)
|
||||||
|
# if defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_80M)
|
||||||
|
movi a3, 480
|
||||||
|
# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_40M)
|
||||||
|
movi a3, 720
|
||||||
|
# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_40M) && defined(CONFIG_SPIRAM_SPEED_40M)
|
||||||
|
movi a3, 720
|
||||||
|
# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_26M) && defined(CONFIG_SPIRAM_SPEED_40M)
|
||||||
|
movi a3, 960
|
||||||
|
# else
|
||||||
|
movi a3, 1200
|
||||||
|
# endif
|
||||||
|
#elif defined(CONFIG_ESPTOOLPY_FLASHMODE_DIO) || defined(CONFIG_ESPTOOLPY_FLASHMODE_DOUT)
|
||||||
|
# if defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_80M)
|
||||||
|
movi a3, 720
|
||||||
|
# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_80M) && defined(CONFIG_SPIRAM_SPEED_40M)
|
||||||
|
movi a3, 720
|
||||||
|
# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_40M) && defined(CONFIG_SPIRAM_SPEED_40M)
|
||||||
|
movi a3, 1200
|
||||||
|
# elif defined(CONFIG_ESPTOOLPY_FLASHFREQ_26M) && defined(CONFIG_SPIRAM_SPEED_40M)
|
||||||
|
movi a3, 1680
|
||||||
|
# else
|
||||||
|
movi a3, 2160
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
2: rsr.ccount a4 /* delay_us(N) */
|
||||||
|
sub a4, a4, a2
|
||||||
|
bltu a4, a3, 2b
|
||||||
|
|
||||||
|
beqz a5, 2f
|
||||||
|
movi a2, _l4_intr_livelock_app
|
||||||
|
l32i a2, a2, 0
|
||||||
|
beqi a2, 2, 8f
|
||||||
|
j 3f
|
||||||
|
|
||||||
|
2: movi a2, _l4_intr_livelock_pro
|
||||||
|
l32i a4, a2, 0
|
||||||
|
addi a4, a4, 1
|
||||||
|
s32i a4, a2, 0
|
||||||
|
|
||||||
|
movi a2, _l4_intr_livelock_sync
|
||||||
|
movi a3, 1
|
||||||
|
addx4 a3, a3, a2
|
||||||
|
l32i a2, a2, 0
|
||||||
|
l32i a3, a3, 0
|
||||||
|
and a2, a2, a3
|
||||||
|
beqz a2, 5f
|
||||||
|
j 1b
|
||||||
|
5: bgei a4, 2, 4f
|
||||||
|
j 1b
|
||||||
|
|
||||||
|
/*
|
||||||
|
Pro cpu (Core 0) jump bypass, continue waiting, App cpu (Core 1)
|
||||||
|
can execute to here, unmap itself tg1 1st stage timeout interrupt
|
||||||
|
then restore registers and exit highint4.
|
||||||
|
*/
|
||||||
|
3: intr_matrix_map DPORT_APP_MAC_INTR_MAP_REG, ETS_TG1_WDT_LEVEL_INTR_SOURCE, 16
|
||||||
|
j 9f
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here, App cpu (Core 1) has exited isr, Pro cpu (Core 0) help the
|
||||||
|
App cpu map tg1 1st stage timeout interrupt clear tg1 interrupt.
|
||||||
|
*/
|
||||||
|
4: intr_matrix_map DPORT_APP_MAC_INTR_MAP_REG, ETS_TG1_WDT_LEVEL_INTR_SOURCE, ETS_T1_WDT_INUM
|
||||||
|
|
||||||
|
1: movi a2, _l4_intr_livelock_sync
|
||||||
|
movi a4, 1
|
||||||
|
addx4 a3, a4, a2
|
||||||
|
l32i a2, a2, 0
|
||||||
|
l32i a3, a3, 0
|
||||||
|
and a2, a2, a3
|
||||||
|
beqz a2, 1b /* Wait for App cpu to enter highint4 again */
|
||||||
|
|
||||||
|
wdt_clr_intr_status TIMERG1
|
||||||
|
j 9f
|
||||||
|
|
||||||
|
/* Feed watchdog */
|
||||||
|
8: wdt_feed TIMERG1
|
||||||
|
|
||||||
|
9: wsr a0, PS /* restore iterrupt level */
|
||||||
|
|
||||||
|
movi a0, 0
|
||||||
|
beqz a5, 1f
|
||||||
|
movi a2, _l4_intr_livelock_app
|
||||||
|
l32i a3, a2, 0
|
||||||
|
bnei a3, 2, 1f
|
||||||
|
s32i a0, a2, 0
|
||||||
|
|
||||||
|
1: bnez a5, 2f
|
||||||
|
movi a2, _l4_intr_livelock_pro
|
||||||
|
s32i a0, a2, 0
|
||||||
|
2: movi a2, _l4_intr_livelock_sync
|
||||||
|
addx4 a2, a5, a2
|
||||||
|
s32i a0, a2, 0
|
||||||
|
|
||||||
|
/* Done. Restore registers and return. */
|
||||||
|
movi a0, L4_INTR_STACK_SIZE
|
||||||
|
mull a5, a5, a0
|
||||||
|
movi a0, _l4_intr_stack
|
||||||
|
add a0, a0, a5
|
||||||
|
l32i a2, a0, L4_INTR_A2_OFFSET
|
||||||
|
l32i a3, a0, L4_INTR_A3_OFFSET
|
||||||
|
l32i a4, a0, L4_INTR_A4_OFFSET
|
||||||
|
rsync /* ensure register restored */
|
||||||
|
|
||||||
|
rsr a5, depc
|
||||||
|
|
||||||
|
rsr a0, EXCSAVE_4 /* restore a0 */
|
||||||
|
rfi 4
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef CONFIG_FREERTOS_UNICORE
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
|
|
@ -30,12 +30,22 @@
|
||||||
#include "driver/timer.h"
|
#include "driver/timer.h"
|
||||||
#include "driver/periph_ctrl.h"
|
#include "driver/periph_ctrl.h"
|
||||||
#include "esp_int_wdt.h"
|
#include "esp_int_wdt.h"
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
|
||||||
#if CONFIG_ESP_INT_WDT
|
#if CONFIG_ESP_INT_WDT
|
||||||
|
|
||||||
|
|
||||||
#define WDT_INT_NUM 24
|
#define WDT_INT_NUM ETS_T1_WDT_INUM
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||||
|
/*
|
||||||
|
* This parameter is indicates the response time of tg1 watchdog to
|
||||||
|
* identify the live lock,
|
||||||
|
*/
|
||||||
|
#define TG1_WDT_LIVELOCK_TIMEOUT_MS (20)
|
||||||
|
|
||||||
|
extern uint32_t _l4_intr_livelock_counter, _l4_intr_livelock_max;
|
||||||
|
#endif
|
||||||
|
|
||||||
//Take care: the tick hook can also be called before esp_int_wdt_init() is called.
|
//Take care: the tick hook can also be called before esp_int_wdt_init() is called.
|
||||||
#if CONFIG_ESP_INT_WDT_CHECK_CPU1
|
#if CONFIG_ESP_INT_WDT_CHECK_CPU1
|
||||||
|
@ -49,7 +59,12 @@ static void IRAM_ATTR tick_hook(void) {
|
||||||
//Only feed wdt if app cpu also ticked.
|
//Only feed wdt if app cpu also ticked.
|
||||||
if (int_wdt_app_cpu_ticked) {
|
if (int_wdt_app_cpu_ticked) {
|
||||||
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||||
|
_l4_intr_livelock_counter = 0;
|
||||||
|
TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2/(_l4_intr_livelock_max+1); //Set timeout before interrupt
|
||||||
|
#else
|
||||||
TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt
|
TIMERG1.wdt_config2=CONFIG_ESP_INT_WDT_TIMEOUT_MS*2; //Set timeout before interrupt
|
||||||
|
#endif
|
||||||
TIMERG1.wdt_config3=CONFIG_ESP_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset
|
TIMERG1.wdt_config3=CONFIG_ESP_INT_WDT_TIMEOUT_MS*4; //Set timeout before reset
|
||||||
TIMERG1.wdt_feed=1;
|
TIMERG1.wdt_feed=1;
|
||||||
TIMERG1.wdt_wprotect=0;
|
TIMERG1.wdt_wprotect=0;
|
||||||
|
@ -91,9 +106,21 @@ void esp_int_wdt_init() {
|
||||||
|
|
||||||
void esp_int_wdt_cpu_init()
|
void esp_int_wdt_cpu_init()
|
||||||
{
|
{
|
||||||
|
assert((CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (portTICK_PERIOD_MS<<1)) && "Interrupt watchdog timeout needs to meet double SysTick period!");
|
||||||
esp_register_freertos_tick_hook_for_cpu(tick_hook, xPortGetCoreID());
|
esp_register_freertos_tick_hook_for_cpu(tick_hook, xPortGetCoreID());
|
||||||
ESP_INTR_DISABLE(WDT_INT_NUM);
|
ESP_INTR_DISABLE(WDT_INT_NUM);
|
||||||
intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM);
|
intr_matrix_set(xPortGetCoreID(), ETS_TG1_WDT_LEVEL_INTR_SOURCE, WDT_INT_NUM);
|
||||||
|
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||||
|
/*
|
||||||
|
* This is a workaround for issue 3.15 in "ESP32 ECO and Workarounds for Bugs" document.
|
||||||
|
*/
|
||||||
|
_l4_intr_livelock_max = 0;
|
||||||
|
if (soc_has_cache_lock_bug()) {
|
||||||
|
assert((portTICK_PERIOD_MS<<1) <= TG1_WDT_LIVELOCK_TIMEOUT_MS);
|
||||||
|
assert(CONFIG_ESP_INT_WDT_TIMEOUT_MS >= (TG1_WDT_LIVELOCK_TIMEOUT_MS*3));
|
||||||
|
_l4_intr_livelock_max = CONFIG_ESP_INT_WDT_TIMEOUT_MS/TG1_WDT_LIVELOCK_TIMEOUT_MS - 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
//We do not register a handler for the interrupt because it is interrupt level 4 which
|
//We do not register a handler for the interrupt because it is interrupt level 4 which
|
||||||
//is not servicable from C. Instead, xtensa_vectors.S has a call to the panic handler for
|
//is not servicable from C. Instead, xtensa_vectors.S has a call to the panic handler for
|
||||||
//this interrupt.
|
//this interrupt.
|
||||||
|
|
|
@ -245,9 +245,9 @@ void panicHandler(XtExcFrame *frame)
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//The core which triggers the interrupt watchdog will delay 1 us, so the other core can save its frame.
|
//The core which triggers the interrupt watchdog will delay 500 us, so the other core can save its frame.
|
||||||
if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || frame->exccause == PANIC_RSN_INTWDT_CPU1) {
|
if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || frame->exccause == PANIC_RSN_INTWDT_CPU1) {
|
||||||
ets_delay_us(1);
|
ets_delay_us(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame->exccause == PANIC_RSN_CACHEERR && esp_cache_err_get_cpuid() != core_id) {
|
if (frame->exccause == PANIC_RSN_CACHEERR && esp_cache_err_get_cpuid() != core_id) {
|
||||||
|
|
Loading…
Reference in a new issue