Explorar o código

Merge branch 'bugfix/esp32s2beta_cache_interrupt_panic' into 'feature/esp32s2beta'

cache_err_int: Add cache error interrupt panic

See merge request espressif/esp-idf!5559
Jiang Jiang Jian %!s(int64=6) %!d(string=hai) anos
pai
achega
32f216441f

+ 11 - 8
components/esp32s2beta/cache_err_int.c

@@ -52,15 +52,18 @@ void esp_cache_err_int_init(void)
     // interrupt is connected to PRO CPU and invalid access happens on the APP
     // 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_CACHE_IA_INT_PRO_DRAM1 |
-        DPORT_CACHE_IA_INT_PRO_DROM0 |
-        DPORT_CACHE_IA_INT_PRO_IROM0 |
-        DPORT_CACHE_IA_INT_PRO_IRAM0 |
-        DPORT_CACHE_IA_INT_PRO_IRAM1);
-#endif
+        DPORT_MMU_ENTRY_FAULT_INT_ENA |
+        DPORT_DCACHE_REJECT_INT_ENA |
+        DPORT_DCACHE_WRITE_FLASH_INT_ENA |
+        DPORT_DC_PRELOAD_SIZE_FAULT_INT_ENA |
+        DPORT_DC_SYNC_SIZE_FAULT_INT_ENA |
+        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);
 }
 

+ 1 - 1
components/esp32s2beta/cpu_start.c

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

+ 98 - 3
components/esp32s2beta/panic.c

@@ -190,6 +190,96 @@ static void setFirstBreakpoint(uint32_t pc)
         ::"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] & BIT(i))
+        {
+        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] & BIT(i))
+        {
+        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.
 //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.
@@ -209,7 +299,7 @@ void panicHandler(XtExcFrame *frame)
         "Coprocessor exception",
         "Interrupt wdt timeout on CPU0",
         "Interrupt wdt timeout on CPU1",
-        "Cache disabled but cached memory region accessed",
+        "Cache exception",
     };
     const char *reason = reasons[0];
     //The panic reason is stored in the EXCCAUSE register.
@@ -242,7 +332,6 @@ void panicHandler(XtExcFrame *frame)
     panicPutStr(" panic'ed (");
     panicPutStr(reason);
     panicPutStr(")\r\n");
-#ifdef PANIC_COMPLETE_IN_ESP32C
     if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
         int debugRsn;
         asm("rsr.debugcause %0":"=r"(debugRsn));
@@ -280,6 +369,9 @@ void panicHandler(XtExcFrame *frame)
             panicPutStr("DebugIntr ");
         }
         panicPutStr("\r\n");
+    } else if (frame->exccause == PANIC_RSN_CACHEERR) {
+        panicPutStr("                                         ^~~~~~~~~~~~~~~\r\n");
+        printCacheError();
     }
 
     if (esp_cpu_in_ocd_debug_mode()) {
@@ -299,7 +391,6 @@ void panicHandler(XtExcFrame *frame)
         setFirstBreakpoint(frame->pc);
         return;
     }
-#endif
     commonErrorHandler(frame);
 }
 
@@ -405,6 +496,8 @@ void esp_panic_wdt_stop(void)
     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)
@@ -421,6 +514,8 @@ static void esp_panic_dig_reset(void)
     }
 }
 
+#endif
+
 static void putEntry(uint32_t pc, uint32_t sp)
 {
     if (pc & 0x80000000) {