cache_err_int: Add cache error interrupt panic

This commit is contained in:
Li Shuai 2019-07-17 10:05:18 +08:00
parent 35147119f1
commit ce6c86672b
3 changed files with 111 additions and 12 deletions

View file

@ -52,15 +52,18 @@ void esp_cache_err_int_init(void)
// interrupt is connected to PRO CPU and invalid access happens on the APP // interrupt is connected to PRO CPU and invalid access happens on the APP
// CPU. // CPU.
// TODO: implement cache error access interrupt for esp32s2beta - IDF-752
#if 0
DPORT_SET_PERI_REG_MASK(DPORT_PRO_CACHE_IA_INT_EN_REG, DPORT_SET_PERI_REG_MASK(DPORT_PRO_CACHE_IA_INT_EN_REG,
DPORT_CACHE_IA_INT_PRO_DRAM1 | DPORT_MMU_ENTRY_FAULT_INT_ENA |
DPORT_CACHE_IA_INT_PRO_DROM0 | DPORT_DCACHE_REJECT_INT_ENA |
DPORT_CACHE_IA_INT_PRO_IROM0 | DPORT_DCACHE_WRITE_FLASH_INT_ENA |
DPORT_CACHE_IA_INT_PRO_IRAM0 | DPORT_DC_PRELOAD_SIZE_FAULT_INT_ENA |
DPORT_CACHE_IA_INT_PRO_IRAM1); DPORT_DC_SYNC_SIZE_FAULT_INT_ENA |
#endif DPORT_ICACHE_REJECT_INT_ENA |
DPORT_IC_PRELOAD_SIZE_FAULT_INT_ENA |
DPORT_IC_SYNC_SIZE_FAULT_INT_ENA |
DPORT_CACHE_DBG_INT_CLR |
DPORT_CACHE_DBG_EN);
ESP_INTR_ENABLE(ETS_CACHEERR_INUM); ESP_INTR_ENABLE(ETS_CACHEERR_INUM);
} }

View file

@ -315,7 +315,7 @@ void start_cpu0_default(void)
//Initialize the interrupt watch dog for CPU0. //Initialize the interrupt watch dog for CPU0.
//esp_int_wdt_cpu_init(); //esp_int_wdt_cpu_init();
#endif #endif
//esp_cache_err_int_init(); esp_cache_err_int_init();
esp_crosscore_int_init(); esp_crosscore_int_init();
spi_flash_init(); spi_flash_init();
/* init default OS-aware flash access critical section */ /* init default OS-aware flash access critical section */

View file

@ -190,6 +190,96 @@ static void setFirstBreakpoint(uint32_t pc)
::"r"(pc):"a3", "a4"); ::"r"(pc):"a3", "a4");
} }
static inline void printCacheError(void)
{
uint32_t vaddr = 0, size = 0;
uint32_t status[2];
status[0] = REG_READ(DPORT_CACHE_DBG_STATUS0_REG);
status[1] = REG_READ(DPORT_CACHE_DBG_STATUS1_REG);
for (int i = 0; i < 32; i++) {
switch (status[0] & (1 << (i&0x1f)))
{
case DPORT_IC_SYNC_SIZE_FAULT_ST:
vaddr = REG_READ(DPORT_PRO_ICACHE_MEM_SYNC0_REG);
size = REG_READ(DPORT_PRO_ICACHE_MEM_SYNC1_REG);
panicPutStr("Icache sync parameter configuration error, the error address and size is 0x");
panicPutHex(vaddr);
panicPutStr("(0x");
panicPutHex(size);
panicPutStr(")\r\n");
break;
case DPORT_IC_PRELOAD_SIZE_FAULT_ST:
vaddr = REG_READ(DPORT_PRO_ICACHE_PRELOAD_ADDR_REG);
size = REG_READ(DPORT_PRO_ICACHE_PRELOAD_SIZE_REG);
panicPutStr("Icache preload parameter configuration error, the error address and size is 0x");
panicPutHex(vaddr);
panicPutStr("(0x");
panicPutHex(size);
panicPutStr(")\r\n");
break;
case DPORT_ICACHE_REJECT_ST:
vaddr = REG_READ(DPORT_PRO_ICACHE_REJECT_VADDR_REG);
panicPutStr("Icache reject error occurred while accessing the address 0x");
panicPutHex(vaddr);
if (REG_READ(DPORT_PRO_CACHE_MMU_ERROR_CONTENT_REG) & DPORT_MMU_INVALID) {
panicPutStr(" (invalid mmu entry)");
}
panicPutStr("\r\n");
break;
default:
break;
}
switch (status[1] & (1 << (i&0x1f)))
{
case DPORT_DC_SYNC_SIZE_FAULT_ST:
vaddr = REG_READ(DPORT_PRO_DCACHE_MEM_SYNC0_REG);
size = REG_READ(DPORT_PRO_DCACHE_MEM_SYNC1_REG);
panicPutStr("Dcache sync parameter configuration error, the error address and size is 0x");
panicPutHex(vaddr);
panicPutStr("(0x");
panicPutHex(size);
panicPutStr(")\r\n");
break;
case DPORT_DC_PRELOAD_SIZE_FAULT_ST:
vaddr = REG_READ(DPORT_PRO_DCACHE_PRELOAD_ADDR_REG);
size = REG_READ(DPORT_PRO_DCACHE_PRELOAD_SIZE_REG);
panicPutStr("Dcache preload parameter configuration error, the error address and size is 0x");
panicPutHex(vaddr);
panicPutStr("(0x");
panicPutHex(size);
panicPutStr(")\r\n");
break;
case DPORT_DCACHE_WRITE_FLASH_ST:
panicPutStr("Write back error occurred while dcache tries to write back to flash\r\n");
break;
case DPORT_DCACHE_REJECT_ST:
vaddr = REG_READ(DPORT_PRO_DCACHE_REJECT_VADDR_REG);
panicPutStr("Dcache reject error occurred while accessing the address 0x");
panicPutHex(vaddr);
if (REG_READ(DPORT_PRO_CACHE_MMU_ERROR_CONTENT_REG) & DPORT_MMU_INVALID) {
panicPutStr(" (invalid mmu entry)");
}
panicPutStr("\r\n");
break;
case DPORT_MMU_ENTRY_FAULT_ST:
vaddr = REG_READ(DPORT_PRO_CACHE_MMU_ERROR_VADDR_REG);
panicPutStr("MMU entry fault error occurred while accessing the address 0x");
panicPutHex(vaddr);
if (REG_READ(DPORT_PRO_CACHE_MMU_ERROR_CONTENT_REG) & DPORT_MMU_INVALID) {
panicPutStr(" (invalid mmu entry)");
}
panicPutStr("\r\n");
break;
default:
break;
}
}
panicPutStr("\r\n");
}
//When interrupt watchdog happen in one core, both cores will be interrupted. //When interrupt watchdog happen in one core, both cores will be interrupted.
//The core which doesn't trigger the interrupt watchdog will save the frame and return. //The core which doesn't trigger the interrupt watchdog will save the frame and return.
//The core which triggers the interrupt watchdog will use the saved frame, and dump frames for both cores. //The core which triggers the interrupt watchdog will use the saved frame, and dump frames for both cores.
@ -209,7 +299,7 @@ void panicHandler(XtExcFrame *frame)
"Coprocessor exception", "Coprocessor exception",
"Interrupt wdt timeout on CPU0", "Interrupt wdt timeout on CPU0",
"Interrupt wdt timeout on CPU1", "Interrupt wdt timeout on CPU1",
"Cache disabled but cached memory region accessed", "Cache exception",
}; };
const char *reason = reasons[0]; const char *reason = reasons[0];
//The panic reason is stored in the EXCCAUSE register. //The panic reason is stored in the EXCCAUSE register.
@ -242,7 +332,6 @@ void panicHandler(XtExcFrame *frame)
panicPutStr(" panic'ed ("); panicPutStr(" panic'ed (");
panicPutStr(reason); panicPutStr(reason);
panicPutStr(")\r\n"); panicPutStr(")\r\n");
#ifdef PANIC_COMPLETE_IN_ESP32C
if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) { if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
int debugRsn; int debugRsn;
asm("rsr.debugcause %0":"=r"(debugRsn)); asm("rsr.debugcause %0":"=r"(debugRsn));
@ -281,6 +370,10 @@ void panicHandler(XtExcFrame *frame)
} }
panicPutStr("\r\n"); panicPutStr("\r\n");
} }
else if (frame->exccause == PANIC_RSN_CACHEERR) {
panicPutStr(" ^~~~~~~~~~~~~~~\r\n");
printCacheError();
}
if (esp_cpu_in_ocd_debug_mode()) { if (esp_cpu_in_ocd_debug_mode()) {
disableAllWdts(); disableAllWdts();
@ -299,7 +392,6 @@ void panicHandler(XtExcFrame *frame)
setFirstBreakpoint(frame->pc); setFirstBreakpoint(frame->pc);
return; return;
} }
#endif
commonErrorHandler(frame); commonErrorHandler(frame);
} }
@ -405,6 +497,8 @@ void esp_panic_wdt_stop(void)
WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0); WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
} }
#if CONFIG_ESP32S2_PANIC_PRINT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT
static void esp_panic_dig_reset(void) __attribute__((noreturn)); static void esp_panic_dig_reset(void) __attribute__((noreturn));
static void esp_panic_dig_reset(void) static void esp_panic_dig_reset(void)
@ -421,6 +515,8 @@ static void esp_panic_dig_reset(void)
} }
} }
#endif
static void putEntry(uint32_t pc, uint32_t sp) static void putEntry(uint32_t pc, uint32_t sp)
{ {
if (pc & 0x80000000) { if (pc & 0x80000000) {