閉じる

UI言語[UI Language]

記事自体は翻訳されません! 記事によって英語版があったりなかったりします。翻訳がある記事は文頭に記載があるよ!
Each articles themselves will not be translated by this setting. Some of article has translation and some of them doesn't. You will notice if the article has its translation by its preamble!

テーマ[Theme]


アイキャッチ画像

ESP32が落ちた(強制リセット)時にBacktraceから該当コードを調べる


Backtraceは行番号に変換できる

ESP32で開発中、原因不明のまま強制リセットがかかってしまい、シリアルモニタには謎のエラーと16進数の羅列っていうのは良くある事かと思います。
付随するエラーメッセージは色々ある気がするんですが、abort() was called at PC 0x400871bfみたいのとか、Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled.みたいなやつとか。

この時表示される Backtrace はエラーが発生した箇所のアドレスを表していて、どうやらESP32は密かにこれらのアドレスとソースコードの該当位置の対応表を作ってくれているみたいです。
そしてxtensa-esp32-elf-addr2line.exeというコマンドラインツールで、アドレスからソースコードファイル名と行番号に変換できます。

ESP32リセット時のbacktrace
ESP32リセット時のbacktrace

スクリーンショットはPlatformIOのシリアルモニタで、Backtraceのアドレスは枠で囲った部分。


書式

xtensa-esp32-elf-addr2line.exe -pfiaC -e "C:\(プロジェクトフォルダ)\.pio\build\esp32dev\firmware.elf" 0x400dd8da:0x3ffaff60

xtensa-esp32-elf-addr2line.exe

このexeがアドレスと行番号を変換するツールで、自分の環境(Windows)だとPlatformIO用のものがC:\Users\(ユーザー名)\.platformio\packages\toolchain-xtensa32\bin、Arduino IDEのがC:\Users\(ユーザー名)\AppData\Local\Arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-80-g6c4433a-5.2.0\binにありました。ESP32の開発環境がセットアップされていればすぐ見つかると思います。

firmware.elf

拡張子がelfのファイルがアドレスとソースコードの対応表と言うか、マッピングファイルと。普通にバイナリファイルでした。
PlatformIOの場合、プロジェクトフォルダ内に.pio\build\esp32dev\firmware.elfというファイルがあるので、これを指定します。firmware.binと同じとこにあります。

アドレス

最後のパラメーターにBacktraceの後ろにある、0x4で始まる4バイト16進数が2つコロンで繋がった “アドレス”を指定します。Backtraceには大量のアドレスが書かれていますが、それぞれがソースコードの異なる1箇所を示していて、コールスタックみたいな形になっています。
あまりに沢山あるので、自分はわざわざコマンドに渡すアドレスを変えながら逐一実行するPythonスクリプトを作ってしまったんですが、何のことはない、複数のアドレスをそのままパラメータとして指定できます。

xtensa-esp32-elf-addr2line.exe -pfiaC -e "C:\(プロジェクトフォルダ)\.pio\build\esp32dev\firmware.elf" 0x4008b32a:0x3ffafdd0 0x4008d37b:0x3ffafe00 0x4008d9bd:0x3ffafe20 0x400823bd:0x3ffafe40 0x40082469:0x3ffafe60 0x40082539:0x3ffafe80 0x40087115:0x3ffafea0 0x4000bedd:0x3ffafec0 0x400fc503:0x3ffafee0 0x400fc618:0x3ffaff10 0x400fca23:0x3ffaff30 0x400fcb11:0x3ffaff50 0x400dd8ce:0x3ffaff70 0x400d9dee:0x3ffaffa0 0x400da9fa:0x3ffb0950 0x400dad3f:0x3ffb09d0 0x400db025:0x3ffb1260 0x400db0e5:0x3ffb12a0 0x400db41d:0x3ffb12f0 0x400dbb1e:0x3ffb1b60 0x400dc6e6:0x3ffb1c30 0x400d63b8:0x3ffb1f70 0x400e2d88:0x3ffb1f90 0x400ff26d:0x3ffb1fb0 0x4008a30e:0x3ffb1fd0

上記のように、backtraceの後ろのアドレス群をそのままコピペして渡せばOKです。

ちなみにコマンドラインのオプションの意味はさっぱりわかりません(笑)。


出力

コマンドの書式に問題がなければ下記のような形で、対応するソースコードのメソッド名、ファイル名、行番号が出てきます。
はぁ~ESP32って本当によく出来てるんですねぇ……

xtensa-esp32-elf-addr2line.exe 出力例
xtensa-esp32-elf-addr2line.exe 出力例

ぶっちゃけこれを見たところで一発解決とはならんのですが、今回の僕のケースだと 「WString内のconcatメソッドあたりでreallocどうのこうのって出てるからメモリ確保関連?」みたいな感じで推察して、最終的にはヒープが足りなくなっているのかもと自分のコードで使っているバッファの量を少なくしたら落ちなくなりました。

なお出力に'a.out': No such fileみたいなメッセージが出てa.outって何やねんってなる事がありましたが、シンプルにオプションとかの指定ミスでした。


いじょ!
ここまで辿らないと解決できないケースは稀な気がしますが、最悪こういう方法があるって知っておくだけで安心ですよねー。

参考🙇

この記事のタグ[This article is filed under]: ESP32[ESP32] | 開発[Dev] | ハウツー[How to] | C++言語[C++]


この記事はここで終わりです。
読んでいただきありがとうございました。
良かったらシェアしてね!

That's all for this article. Thank you for your reading.
Please share this if you like it!

Twitter | Reddit | Facebook | Pinterest | Pocket

前の記事[Prev Post]

前の記事のアイキャッチ画像

【軸の秤】 version 0.2.0 リリースノート

次の記事[Next Post]

次の記事のアイキャッチ画像

CH9102F, CH9329, MT3608... 最近気になってるICとかメモ【電子工作】