esp32 Guru Meditation 錯誤解決方案(轉)


Guru Meditation
本節將對打印在 Guru Meditation Error: Core panic'ed后面括號中的致錯原因進行逐一解釋。
IllegalInstruction
此 CPU 異常表示當前執行的指令不是有效指令,引起此錯誤的常見原因包括:

FreeRTOS 中的任務函數已返回。在 FreeRTOS 中,如果想終止任務函數,需要調用 vTaskDelete()函數釋放當前任務的資源,而不是直接返回。
無法從 SPI Flash 中加載下一條指令,這通常發生在:
應用程序將 SPI Flash 的引腳重新配置為其它功能(如 GPIO,UART 等等)。有關 SPI Flash 引腳的詳細信息,請參閱硬件設計指南和芯片/模組的數據手冊。
某些外部設備意外連接到 SPI Flash 的引腳上,干擾了 ESP32 和 SPI Flash 之間的通信。
InstrFetchProhibited
此 CPU 異常表示 CPU 無法加載指令,因為指令的地址不在 IRAM 或者 IROM 中的有效區域中。

通常這意味着代碼中調用了並不指向有效代碼塊的函數指針。這種情況下,可以查看 PC(程序計數器)寄存器的值並做進一步判斷:若為 0 或者其它非法值(即只要不是 0x4xxxxxxx 的情況),則證實確實是該原因。

若PC指針大規模指向無效區域,那么coredump發生的可能原因某個引腳接觸不良等原因導致。

詳情可以對照下面esp32映射圖,確定其 pc 指針位置(並不局限於本節使用)。

 

LoadProhibited, StoreProhibited
當應用程序嘗試讀取或寫入無效的內存位置時,會發生此類 CPU 異常。此類無效內存地址可以在寄存器轉儲的EXCVADDR 中找到。如果該地址為零,通常意味着應用程序正嘗試解引用一個 NULL指針。如果該地址接近於零,則通常意味着應用程序嘗試訪問某個結構體的成員,但是該結構體的指針為 NULL。如果該地址是其它非法值(不在 0x3fxxxxxx - 0x6xxxxxxx 的范圍內),則可能意味着用於訪問數據的指針未初始化或者已經損壞。

IntegerDivideByZero
應用程序嘗試將整數除以零。

LoadStoreAlignment
應用程序嘗試讀取/寫入的內存位置不符合加載/存儲指令對字節對齊大小的要求,例如,32 位加載指令只能訪問 4 字節對齊的內存地址,而 16 位加載指令只能訪問 2 字節對齊的內存地址。

LoadStoreError
應用程序嘗試從僅支持 32 位加載/存儲的內存區域執行 8 位或 16 位加載/存儲操作,例如,解引用一個指向指令內存區域的 char* 指針就會導致這樣的錯誤。

Unhandled debug exception
這后面通常會再跟一條消息:

Debug exception reason: Stack canary watchpoint triggered (task_name)
此錯誤表示應用程序寫入的位置越過了 task_name 任務堆棧的末尾,請注意,並非每次堆棧溢出都會觸發此錯誤。任務有可能會繞過堆棧金絲雀(stack canary)的位置訪問堆棧,在這種情況下,監視點就不會被觸發。

Interrupt wdt timeout on CPU0 / CPU1
這表示發生了中斷看門狗超時.

Cache disabled but cached memory region accessed
@ 此問題很多人遇到過,特別在這總結一下, 該部分內容感謝不方便透露姓名的張同學提供幫助

該問題原因在於:在 cache 被禁用期間(例如在使用 spi_flash API 讀取/寫入/擦除/映射 SPI Flash 的時候),發生了 IRAM-Safe 中斷並且中斷程序訪問了 flash 的資源。通常發生在中斷處理程序調用了在 flash 中的程序,引用了 flash 中的常量。值得注意的是,當在中斷處理程序里使用 double 型變量時,由於 double 型變量操作的實現是軟件實現的,所以該實現部分也被存放在了 flash 中(例如強制類型轉換操作)。
解決辦法就是:

給在中斷中訪問的函數加上IRAM_ATTR修飾符
給在中斷中訪問的常量加 DRAM_ATTR 修飾符
不在中斷處理程序中使用 double 類型操作
需要注意的是:
1.該異常只發生在 IRAM-Safe 中斷,即使用 ESP_INTR_FLAG_IRAM注冊的中斷處理程序。
2.該異常只有在 cache 被禁期間會出現,所以當 cache 未被禁用期間不會出現,換句話說該異常具有隨機性。
3.編譯器可能會將一些不會被改變的變量放入 .rodata 段中,哪怕程序員沒有加 const 修飾符。對於 ESP32 的應用程序來說,.rodata 意味着該部分位於 flash 中。對於字符串變量,這種情況很容易被察覺,但是對於某些常量,就不是那么好察覺了。例如下面的情況

static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};

這里定義了指針數組 TG,該數組元素是兩個硬件定時器0,1的寄存器首地址,該指針數組的元素不會被改變,所以會被編譯器放入 .rodata 中。此時在定時器中斷里操作了 TG,又恰好這個中斷發生在 cache 被禁期間,那么 CPU 就會拋出該異常。

出現該問題的調試技巧
CPU 拋出該類型異常時,通常異常位置就是出錯位置,需要細看

Guru Meditation Error: Core  1 panic'ed (Cache disabled but cached memory region accessed)
Core 1 register dump:
PC      : 0x4011b808  PS      : 0x00060034  A0      : 0x8008c664  A1      : 0x3ffbeca0 
0x4011b808: __fixunsdfdi at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libgcc/config/xtensa/ieee754-df.S:2041
A2      : 0x0099fd28  A3      : 0x00000000  A4      : 0x3ffbf6a0  A5      : 0x3f7909f1 
A6      : 0x00000000  A7      : 0x00013ffc  A8      : 0x80086136  A9      : 0x3ffbec80 
A10     : 0xfffffffc  A11     : 0x40ddd57f  A12     : 0x000007fe  A13     : 0x00000000 
A14     : 0x65580000  A15     : 0x00000000  SAR     : 0x00000014  EXCCAUSE: 0x00000007 
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000 
Core 1 was running in ISR context:
EPC1    : 0x40086914  EPC2    : 0x00000000  EPC3    : 0x00000000  EPC4    : 0x4011b808
0x40086914: spi_flash_enable_interrupts_caches_and_other_cpu at /home/chenzhengwei/esp/esp-idf/components/spi_flash/cache_utils.c:147
0x4011b808: __fixunsdfdi at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libgcc/config/xtensa/ieee754-df.S:2041
Backtrace: 0x4011b808:0x3ffbeca0 0x4008c661:0x3ffbecd0 0x4008c69d:0x3ffbecf0 0x400857e5:0x3ffbed10 0x40086911:0x3ffd0970 0x40086cc9:0x3ffd0990 0x40117789:0x3ffd09e0 0x4011785e:0x3ffd0a10 0x401179ea:0x3ffd0a30 0x40116c51:0x3ffd0aa0 0x40117109:0x3ffd0b20 0x40116729:0x3ffd0b90 0x40105c36:0x3ffd0bd0 0x401057d7:0x3ffd0c10 0x401058ce:0x3ffd0c40 0x4008dfb5:0x3ffd0c90
0x4011b808: __fixunsdfdi at /builds/idf/crosstool-NG/.build/src/gcc-5.2.0/libgcc/config/xtensa/ieee754-df.S:2041
0x4008c661: gpio_isr_loop at /home/chenzhengwei/esp/esp-idf/components/driver/gpio.c:433
0x4008c69d: gpio_intr_service at /home/chenzhengwei/esp/esp-idf/components/driver/gpio.c:433
0x400857e5: _xt_lowint1 at /home/chenzhengwei/esp/esp-idf/components/freertos/xtensa_vectors.S:1154
0x40086911: spi_flash_enable_interrupts_caches_and_other_cpu at /home/chenzhengwei/esp/esp-idf/components/spi_flash/cache_utils.c:147
...

在這個例子中,發生異常的位置在 0x4011b808, 這里是__fixunssfdi 函數的存放位置,且該位置位於片外存儲器(見 esp32_technical_reference_manual 的 1.3.3 節),這個函數是用來對浮點數轉 64 位無符號整數的操作,意味着中斷處理程序里使用了 double 型數據的強制類型轉換操作。這在 cache 被關閉時操作是不被允許的。

如果不知道變量是在 .data/.bss 段還是 .rodata 段,那么可以使用 readelf 命令查看 .elf 中的符號詳細信息

# 將 build/empty-project.elf 中的符號表覆蓋寫到 empty-project.out 文件中
readelf -a build/empty-project.elf > empty-project.out

使用 readelf 命令提取 elf 文件中的符號表,如何查看符號表可參考 C語言變量的存儲布局,通過符號表,可以准確的看到每一個變量、函數的存儲位置,大小等信息。有了這些信息,就可以檢查 IRAM-Safe 中斷處理程序里使用變量和函數是否在 flash 中。

 


原文鏈接:https://blog.csdn.net/weixin_42942530/article/details/103975237


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM