在某些情況下,程序的執(zhí)行,沒有按照定義的方式持續(xù)執(zhí)行.在 ESP-IDF 中,這些情況包括:
CONFIG_TASK_WDT_PANIC
,則僅 fatal)assert
,configASSERT
和類似的宏.本指南介紹了 ESP-IDF 中用于處理這些錯誤的過程,并提供了有關(guān)錯誤故障排除的建議.
概述中列出的每個錯誤原因都將由 Panic 處理程序處理.
Panic 處理程序?qū)⑹紫葘㈠e誤原因打印到控制臺. 對于 CPU 異常,消息類似于:
Guru Meditation Error: Core 0 panic'ed (IllegalInstruction). Exception was unhandled.
對于某些系統(tǒng)級別檢查(中斷監(jiān)視程序,緩存訪問錯誤),該消息將類似于:
Guru Meditation Error: Core 0 panic'ed (Cache disabled but cached memory region accessed)
在所有情況下,錯誤原因?qū)⒋蛴≡诶ㄌ栔? 有關(guān)可能的錯誤原因列表,請參閱 Guru Meditation Errors.
可以使用 CONFIG_ESP32_PANIC
配置選項設(shè)置 Panic 處理程序的后續(xù)行為. 可用選項包括:
打印寄存器并重新啟動(CONFIG_ESP32_PANIC_PRINT_REBOOT
) - 默認選項.
這將在異常點打印寄存器值,打印回溯,然后重新啟動芯片.
打印寄存器并暫停(CONFIG_ESP32_PANIC_PRINT_HALT
)
與上述選項類似,但暫停而不是重新啟動. 重啟程序需要外部重置.
無提示重啟(CONFIG_ESP32_PANIC_SILENT_REBOOT
)
不要打印寄存器或回溯,立即重啟芯片.
調(diào)用 GDB 存根(CONFIG_ESP32_PANIC_GDBSTUB
)
啟動 GDB 服務(wù)器,它可以通過控制臺 UART 端口與 GDB 通信. 有關(guān)詳細信息,請參閱 GDB 存根.
Panic 處理程序的行為受另外兩個配置選項的影響.
CONFIG_ESP32_DEBUG_OCDAWARE
(這是默認設(shè)置),則 Panic 處理程序?qū)z測 JTAG 調(diào)試器是否已連接. 如果是,則執(zhí)行將暫停,控制權(quán)將傳遞給調(diào)試器. 在這種情況下,寄存器和回溯不會轉(zhuǎn)儲到控制臺,并且不使用 GDBStub/Core Dump 功能.CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
或 CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
選項),則系統(tǒng)狀態(tài)(任務(wù)堆棧和寄存器)將被轉(zhuǎn)儲到 Flash 或 UART,以供以后分析.下圖說明了 Panic 處理程序的行為:
除非啟用了 CONFIG_ESP32_PANIC_SILENT_REBOOT
選項,否則 Panic 處理程序會將一些 CPU 寄存器和回溯打印到控制臺:
Core 0 register dump:PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb5030A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dcA6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff8A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001dEXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffffBacktrace: 0x400e14ed:0x3ffb5030 0x400d0802:0x3ffb5050
打印的寄存器值是異常幀中的寄存器值,即 CPU 異常或其他嚴重錯誤發(fā)生時的值.
如果由于 abort()
調(diào)用而執(zhí)行了 Panic 處理程序,則不會打印寄存器轉(zhuǎn)儲.
在某些情況下,例如中斷看門狗超時, Panic 處理程序可能會打印額外的 CPU 寄存器 (EPC1-EPC4) 以及在另一個 CPU 上運行的代碼的寄存器/回溯.
Backtrace 行包含 PC:SP 對,其中 PC 是程序計數(shù)器,SP 是堆棧指針,用于當前任務(wù)的每個堆棧幀. 如果在 ISR 內(nèi)發(fā)生嚴重錯誤,則回溯可能包括來自被中斷的任務(wù)和來自 ISR 的 PC:SP 對.
如果使用 IDF Monitor,程序計數(shù)器值將轉(zhuǎn)換為代碼位置(函數(shù)名稱,文件名和行號),輸出將與其他行進行注釋:
Core 0 register dump:PC : 0x400e14ed PS : 0x00060030 A0 : 0x800d0805 A1 : 0x3ffb50300x400e14ed: app_main at /Users/user/esp/example/main/main.cpp:36A2 : 0x00000000 A3 : 0x00000001 A4 : 0x00000001 A5 : 0x3ffb50dcA6 : 0x00000000 A7 : 0x00000001 A8 : 0x00000000 A9 : 0x3ffb5000A10 : 0x00000000 A11 : 0x3ffb2bac A12 : 0x40082d1c A13 : 0x06ff1ff80x40082d1c: _calloc_r at /Users/user/esp/esp-idf/components/newlib/syscalls.c:51A14 : 0x3ffb7078 A15 : 0x00000000 SAR : 0x00000014 EXCCAUSE: 0x0000001dEXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0xffffffffBacktrace: 0x400e14ed:0x3ffb5030 0x400d0802:0x3ffb50500x400e14ed: app_main at /Users/user/esp/example/main/main.cpp:360x400d0802: main_task at /Users/user/esp/esp-idf/components/esp32/cpu_start.c:470
要查找發(fā)生嚴重錯誤的位置,請查看“Backtrace”的下一行. 嚴重錯誤位置是頂行,后續(xù)行顯示調(diào)用堆棧.
如果啟用了 CONFIG_ESP32_PANIC_GDBSTUB
選項,則發(fā)生嚴重錯誤時, Panic 處理程序不會重置芯片. 相反,它將啟動 GDB 遠程協(xié)議服務(wù)器,通常稱為 GDB Stub. 發(fā)生這種情況時,可以指示主機上運行的 GDB 實例連接到 ESP32 UART 端口.
如果使用 IDF Monitor,則在 UART 上檢測到 GDB Stub 提示時會自動啟動 GDB. 輸出看起來像這樣:
Entering gdb stub now.$T0b#e6GNU gdb (crosstool-NG crosstool-ng-1.22.0-80-gff1f415) 7.10Copyright (C) 2015 Free Software Foundation, Inc.License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>This is free software: you are free to change and redistribute it.There is NO WARRANTY, to the extent permitted by law. Type "show copying"and "show warranty" for details.This GDB was configured as "--host=x86_64-build_apple-darwin16.3.0 --target=xtensa-esp32-elf".Type "show configuration" for configuration details.For bug reporting instructions, please see:<http://www.gnu.org/software/gdb/bugs/>.Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from /Users/user/esp/example/build/example.elf...done.Remote debugging using /dev/cu.usbserial-313010x400e1b41 in app_main () at /Users/user/esp/example/main/main.cpp:3636 *((int*) 0) = 0;(gdb)
GDB 提示可用于檢查 CPU 寄存器,本地和靜態(tài)變量以及內(nèi)存中的任意位置. 無法設(shè)置斷點,更改 PC 或繼續(xù)執(zhí)行. 要重置程序,請退出 GDB 并執(zhí)行外部重置:IDF Monitor 中的 Ctrl-T Ctrl-R
,或使用開發(fā)板上的外部重置按鈕.
本節(jié)解釋了不同錯誤原因的含義,打印在 Guru Meditation Error:Core panic'ed message
之后的括號中.
有關(guān)“Guru Meditation”的歷史淵源,請參閱 Wikipedia 文章.
該 CPU 異常表示執(zhí)行的指令不是有效指令. 此錯誤的最常見原因有:
此 CPU 異常表示 CPU 無法加載指令,因為指令的地址不屬于指令 RAM 或 ROM 中的有效區(qū)域.
通常這意味著嘗試調(diào)用函數(shù)指針,該指針不指向有效代碼. PC (程序計數(shù)器)寄存器可用作指示器:它將為零或?qū)?不是 0x4xxxxxxx).
當應(yīng)用程序嘗試讀取或?qū)懭霟o效的內(nèi)存位置時,會發(fā)生此 CPU 異常. 寫入/讀取的地址可在寄存器轉(zhuǎn)儲中的 EXCVADDR
寄存器中找到. 如果此地址為零,則通常表示應(yīng)用程序嘗試取消引用 NULL 指針. 如果此地址接近于零,則通常意味著應(yīng)用程序嘗試訪問結(jié)構(gòu)的成員,但指向該結(jié)構(gòu)的指針為 NULL. 如果該地址是別的(垃圾值,不在 0x3fxxxxxx
- 0x6xxxxxxx
范圍內(nèi)),則可能意味著用于訪問數(shù)據(jù)的指針未初始化或已損壞.
應(yīng)用程序嘗試將整數(shù)除以零.
應(yīng)用程序嘗試讀取或?qū)懭雰?nèi)存位置,并且地址對齊與加載/存儲大小不匹配. 例如,32 位加載只能從 4 字節(jié)對齊的地址完成,而 16 位加載只能從 2 字節(jié)的對齊地址完成.
應(yīng)用程序嘗試從僅支持 32 位加載/存儲的內(nèi)存區(qū)域進行 8 位或 16 位加載/存儲. 例如,取消引用指向內(nèi)存存儲器的 char *
指針將導致這樣的錯誤.
通常會出現(xiàn)以下消息:
Debug exception reason: Stack canary watchpoint triggered (task_name)
此錯誤表示應(yīng)用程序已寫入 task_name
任務(wù)堆棧的末尾. 請注意,并非每個堆棧溢出都可以保證觸發(fā)此錯誤. 任務(wù)可能會在堆棧 canary
位置之外寫入堆棧,在這種情況下,不會觸發(fā)觀察點.
表示發(fā)生了中斷看門狗超時. 有關(guān)詳細信息,請參閱看門狗.
在某些情況下,ESP-IDF 將暫時禁止通過高速緩存訪問外部 SPI Flash 和 SPI RAM. 例如,spi_flash API 用于讀取/寫入/擦除/mmap SPI Flash 區(qū)域. 在這些情況下,任務(wù)被掛起,并且未注冊 ESP_INTR_FLAG_IRAM
的中斷處理程序被禁用. 確保使用此標志注冊的任何中斷處理程序都具有 IRAM/DRAM 中的所有代碼和數(shù)據(jù). 有關(guān)更多詳細信息,請參閱 SPI Flash API 文檔.
ESP32 有一個內(nèi)置的掉電檢測器,默認啟用. 如果電源電壓低于安全水平,掉電檢測器可以觸發(fā)系統(tǒng)復位. 可以使用 CONFIG_BROWNOUT_DET
和 CONFIG_BROWNOUT_DET_LVL_SEL
選項配置掉電檢測器. 當?shù)綦姍z測器觸發(fā)時,將打印以下消息:
Brownout detector was triggered
打印消息后,芯片將復位.
請注意,如果電源電壓快速下降,則控制臺上只能看到部分消息.
ESP-IDF 堆實現(xiàn)包含許多堆結(jié)構(gòu)的運行時檢查. 可以在 menuconfig 中啟用其他檢查(“Heap Stisoning”). 如果其中一項檢查失敗,將打印類似于以下內(nèi)容的消息:
CORRUPT HEAP: Bad tail at 0x3ffe270a. Expected 0xbaad5678 got 0xbaac5678assertion "head != NULL" failed: file "/Users/user/esp/esp-idf/components/heap/multi_heap_poisoning.c", line 201, function: multi_heap_freeabort() was called at PC 0x400dca43 on core 0
有關(guān)詳細信息,請參閱堆內(nèi)存調(diào)試文檔.
可以使用 CONFIG_STACK_CHECK_MODE
選項在 ESP-IDF 中啟用 Stack Smashing 保護(基于 GCC -fstack-protector *
標志). 如果檢測到 Stack Smashing,將打印類似于以下內(nèi)容的消息:
Stack smashing protect failure!abort() was called at PC 0x400d2138 on core 0Backtrace: 0x4008e6c0:0x3ffc1780 0x4008e8b7:0x3ffc17a0 0x400d2138:0x3ffc17c0 0x400e79d5:0x3ffc17e0 0x400e79a7:0x3ffc1840 0x400e79df:0x3ffc18a0 0x400e2235:0x3ffc18c0 0x400e1916:0x3ffc18f0 0x400e19cd:0x3ffc1910 0x400e1a11:0x3ffc1930 0x400e1bb2:0x3ffc1950 0x400d2c44:0x3ffc1a800
回溯應(yīng)該指向 Stack Smashing 發(fā)生的函數(shù). 檢查功能代碼以獲得對本地陣列的無限制訪問.
聯(lián)系客服