ESP8266で開発していると、しばしばこんな文字列がシリアルに吐き出されてリセットがかかることがあります。なにが起こったか。スタックトレースを調べてみましょう。
0. ESPExceptionDecoder のセットアップ
-
https://github.com/me-no-dev/EspExceptionDecoder/releases から
EspExceptionDecoder-1.0.4.zip
を持ってきて展開する。 -
ArdionoIDEを再起動する。
-
スケッチをビルドする。
例1: Soft WDT Reset
Soft WDT reset
ctx: cont
sp: 3ffef2b0 end: 3ffef490 offset: 01b0
>>>stack>>>
3ffef460: 00000000 3ffe835c 3ffee444 40201c94
3ffef470: 3fffdad0 00000000 3ffee460 402021e8
3ffef480: feefeffe feefeffe 3ffee470 40100114
<<<stack<<<
スタックトレースを貼り付けてみる
この場合は、起こったことは Soft WDT Reset である。WDT、つまり定期的に実行すべき ESP.WdtFeed();
が実行されないまま時間切れになった。
ツールメニューに登場した「ESP Exception Decoder」を選ぶと別画面が開く。
シリアルコンソールに吐き出されたエラーメッセージを上に貼り付けると、下にスタックトレースが表示される。
つまり、WDT Reset が発生した場所は「ASCIITable.ino の 70行目にあるloopメソッド内」であることがわかった。
例2 Exception
Exception (29):
epc1=0x4000e1b2 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
ctx: cont
sp: 3fff3c10 end: 3fff4280 offset: 01a0
>>>stack>>>
3fff3db0: 00000040 00000082 3fffb9cc 4022d44d
3fff3dc0: 3fff9794 02b12719 00000000 00000041
3fff3dd0: 00000040 0000003f 00000000 00000041
3fff3de0: 3fffbc04 3fff9224 3fffb17c 3fff9774
3fff3df0: 3fffbd00 3fffb19c 3fff9224 3fff9224
3fff3e00: 00000040 3fff9224 3fffb9cc 3fff9224
3fff3e10: 00000040 3fff9224 3fffb9cc 4022df82
3fff3e20: 3fff92d4 0000003f 2382a609 00000020
3fff3e30: 3fffb1fc 3fff9224 3fff955c 00000020
3fff3e40: 3fffb1fc 3fff9224 00000010 4022e268
3fff3e50: 3fff6ddc 3fff953c 3fff955c 00000001
3fff3e60: 00000001 3fff955c 3fff70ec 4022d040
3fff3e70: 00000100 3fff929c 3fff7077 00000000
3fff3e80: 00000100 3fff929c 3fff7077 4022f269
3fff3e90: 3fff3ec0 00000000 000000d0 00000030
3fff3ea0: 1df1e22e 181a0000 3fff6c64 00000004
3fff3eb0: 00000004 3fff6fa4 3fff7071 4022b374
3fff3ec0: 2c6c0203 48176945 43e1e0d2 4583a3ad
3fff3ed0: b0d7527d 2e16fe31 366c90ca 91a401ee
3fff3ee0: a5a61010 cc77bb70 46884f03 e22eda52
3fff3ef0: 00000004 3fff7071 3fff6fa4 4022b775
3fff3f00: 00000000 600011f0 3fff6c64 3fff6aec
3fff3f10: 3fff3f30 3fff3f30 00000004 4022992d
3fff3f20: 3ffe85e8 3fff7071 3fff8b64 00000c40
3fff3f30: 3ffe9bd0 3ffebc80 00000000 00000004
3fff3f40: 3fff6fa4 3fff7071 00000004 00000004
3fff3f50: 00000004 3fff7071 3fff6fa4 4022b16c
: <途中省略>
3fff4270: feefeffe feefeffe 3fff3260 40100970
<<<stack<<<
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 1384, room 16
tail 8
chksum 0x2d
csum 0x2d
v40106e40
~ld
Reset by Exception
スタックトレースを貼り付けてみる
ESP Exception Decoder に貼り付けて得られたのがこれ。wpa_cipher_to_suite のなかでException(29)が起こったことがわかる。
このメソッドはデバッグシンボルが手に入っていないため、ファイル名や行番号まではわからない。TODO: シンボルテーブルの入手方法を調べる
Decoding 46 results
0x4022d44d: wpa_cipher_to_suite at ?? line ?
0x4022df82: rijndaelEncrypt at ?? line ?
0x4022e268: rijndaelEncrypt at ?? line ?
0x4022d040: wpa_parse_wpa_ie_rsn at ?? line ?
0x4022f269: lwip_standard_chksum at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/ipv4/inet_chksum.c line 151
0x4022b374: wpa_auth_sm_event at ?? line ?
0x4022b775: wpa_validate_wpa_ie at ?? line ?
0x4022992d: wpa_auth_for_each_sta at ?? line ?
0x4022b16c: wpa_auth_sm_event at ?? line ?
0x4022b514: wpa_write_rsn_ie at ?? line ?
0x401006f0: _umm_malloc at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc/umm_malloc.c line 1441
0x4022b2c4: wpa_auth_sm_event at ?? line ?
0x402096b8: dhcp_reboot at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/dhcp.c line 1213
0x40209df5: dhcp_handle_nak at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/dhcp.c line 196
: (inlined by) dhcp_recv at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/dhcp.c line 1665
0x40208f4a: espconn_tcp_client at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/app/espconn_tcp.c line 946
0x4020a2c1: dhcp_release at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/dhcp.c line 1279 (discriminator 3)
0x40207cd9: wifi_softap_dhcps_client_update at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/app/dhcpserver.c line 1125
0x4020e902: ip_route at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/core/ipv4/ip.c line 147
0x40208609: espconn_client_connect at /Users/igrokhotkov/espressif/arduino/tools/sdk/lwip/src/app/espconn_tcp.c line 853
: <後略>
Exception(29) ってなに
https://github.com/esp8266/Arduino/blob/master/doc/exception_causes.md によれば
29 StoreProhibitedCause: A store referenced a page mapped with an attribute that does not permit stores Region Protection or MMU
あああ。書き込んではいけない領域に書き込もうとしたみたいですね。ソースを見てみましょうか
int wpa_cipher_put_suites(u8 *pos, int ciphers)
{
int num_suites = 0;
if (ciphers & WPA_CIPHER_CCMP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_TKIP) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
if (ciphers & WPA_CIPHER_NONE) {
RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE);
pos += WPA_SELECTOR_LEN;
num_suites++;
}
return num_suites;
}
posにnullでも渡されてるんでしょうかね……スタックトレース中に dhcp_reboot とかやってるので、固定IPを割り振ったら解消するのかもしれません。
例3: Exception
別のが採れました。
Exception (29):
epc1=0x4000e1b2 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000004 depc=0x00000000
ctx: cont
sp: 3fff3be0 end: 3fff4280 offset: 01a0
>>>stack>>>
3fff3d80: 00410000 00000041 3fff8f64 4022cfdb
3fff3d90: 00000001 3fff9104 3fff8f64 4022d174
3fff3da0: 0000020c 3fff9104 3fff3174 3fffb044
3fff3db0: 00000041 00000041 3fffb894 4022d426
3fff3dc0: 3fff9778 ffffffc0 00000041 00000001
3fff3dd0: 00000041 00000000 3fffbacc 00000040
3fff3de0: 3fff6964 00000000 3fffb044 3fff91b4
3fff3df0: 3fffbbd0 3fffb044 3fff9104 00000000
3fff3e00: 00000040 3fff9104 3fffb894 3fffb044
3fff3e10: 00000041 3fff9104 3fffb894 4022dfaa
3fff3e20: 3fff91b4 0000003f b5a3d2ec 00000020
3fff3e30: 3fffb0c4 3fff9104 3fff943c 00000000
3fff3e40: 00000010 3fff9104 00000010 4022e178
3fff3e50: 3fff8f64 3fff941c 0000000f 00000001
3fff3e60: 00000001 3fff943c 3fff6ff1 4022d040
3fff3e70: 00000100 3fff917c 3fff6f2f 00000000
3fff3e80: 00000100 3fff917c 3fff6f2f 4022f269
3fff3e90: 3fff3ec0 00000000 000000d0 00000030
3fff3ea0: 39b9e749 981b0000 3fff6abc 00000004
3fff3eb0: 00000004 3fff6e5c 3fff6f29 4022b374
3fff3ec0: 08180203 fe1ac7d2 8d4d8bcb a76a4af7
3fff3ed0: ae94c76e db27423a a41ccb78 24bdbe5e
3fff3ee0: 829c9f4b b994316d 0bcaf416 e749c51e
3fff3ef0: 00000004 3fff6f29 3fff6e5c 4022b775
3fff3f00: 00000000 600011f0 3fff6abc 3fff6b7c
3fff3f10: 3fff3f30 3fff3f30 00000004 4022992d
3fff3f20: 3ffe85e8 3fff6f29 3fff8a1c 00000c40
3fff3f30: 3ffe9bd0 3ffebc80 00000000 00000004
3fff3f40: 3fff6e5c 3fff6f29 00000004 00000004
3fff3f50: 00000004 3fff6f29 3fff6e5c 4022b16c
3fff3f60: 00000000 3fff6f29 3fff6e5c 4022b514
3fff3f70: 00000019 3fff66f4 00000026 401006f0
3fff3f80: 3fff3fd0 0000000e 00000010 00000000
3fff3f90: 3fff6bd4 3fff66f4 3fff6e5c 01000000
3fff3fa0: 3fff3fd0 3fff685c 3fff6e5c 4022b2c4
3fff3fb0: 402096b8 312e3538 3fff66f4 00001387
3fff3fc0: 0001e677 3fff685c 3fff6bb4 40209df5
3fff3fd0: 000001bb 3fff685c 3fff6abc 40208f4a
3fff3fe0: 5e84559e 3fff681c 00000028 00000000
3fff3ff0: 000001bb 3fff685c 3fff66f4 4020a2c1
3fff4000: 3ffeaa78 5e84559e 3ffeaa78 5e84559e
3fff4010: 3fff3198 3fff681c 3fff40b0 40207cd9
3fff4020: 00000000 3f000a36 3fff4070 4020e902
3fff4030: 00000000 00000000 00000000 3fff4120
3fff4040: 0001382c 3ffe912c 3fff40b0 40208609
3fff4050: 3fff4090 3fff4060 00000008 3ffebaa8
3fff4060: 3fff42a4 00000001 0001382c 3fff6954
3fff4070: 000000b5 0001382c 00000001 00000000
3fff4080: 3ffe9118 00000001 3fff4060 3fff4090
3fff4090: 3ffe90ec 00000001 3fff3198 4020af84
3fff40a0: 0001382c 00000001 3fff3198 40207207
3fff40b0: 3fff681c 3fff685c 3fff66f4 0000001f
3fff40c0: 00000019 3f0001bb 3f001388 3fff6c7c
3fff40d0: 0000003f 0000003d 3fff683c 0000000f
3fff40e0: 00000005 3fff690c 0000001f 00000019
3fff40f0: 3fff68dc 0000001f 00000011 3fff6d7c
3fff4100: 0000004f 00000044 00000000 00000000
3fff4110: 00000000 ffffffff 00000000 00000000
3fff4120: 3ffeaa10 00000000 000003e8 4020d424
3fff4130: 3fff6d1c 3fff693c 00000000 00000000
3fff4140: 00000000 3fff6a0c 0000009f 00000090
3fff4150: 00000001 00000001 3fff644c 4020f212
3fff4160: 00000000 00000001 3fff4180 4020af7a
3fff4170: 3fff644c 3fff27b0 3fff644c 4020afb6
3fff4180: 00000000 00000000 00000000 4020d5d4
3fff4190: 3fff644c 3fff27b0 3fff2770 4020b04d
3fff41a0: 3fff66d4 0000000f 0000000a 3fff3260
3fff41b0: 3fff27b0 00000002 3fff3260 00000001
3fff41c0: 00000001 4020a5ac 0000000f 3fff3260
3fff41d0: 00000000 4020f21c 3fff2770 3ffe900c
3fff41e0: 00000001 3fff2794 3fff2770 4020b257
3fff41f0: 3ffe9f28 00000000 000003e8 4020cfac
3fff4200: 00000000 3fff68a4 3fff3198 4020cff8
3fff4210: 4020f208 4020f21c 3fff2770 40207004
3fff4220: 40206c2c 00000000 4020f21c 4020f208
3fff4230: 3ffeaa78 2100a8c0 00001388 3fff3254
3fff4240: 3fffdad0 00000000 3fff3198 40207083
3fff4250: 00000000 00000000 00000000 feefeffe
3fff4260: feefeffe feefeffe 3fff324c 4020dffb
3fff4270: feefeffe feefeffe 3fff3260 40100970
<<<stack<<<
Decoding 44 results
0x4022cfdb: more_comps at /Users/igrokhotkov/e/axtls/e1/crypto/bigint.c line 1072
0x4022d174: alloc at /Users/igrokhotkov/e/axtls/e1/crypto/bigint.c line 1106
0x4022d426: regular_multiply at /Users/igrokhotkov/e/axtls/e1/crypto/bigint.c line 822
0x4022dfaa: bi_barrett at /Users/igrokhotkov/e/axtls/e1/crypto/bigint.c line 1293
0x4022e178: bi_mod_power at /Users/igrokhotkov/e/axtls/e1/crypto/bigint.c line 1400
0x4022d040: trim at /Users/igrokhotkov/e/axtls/e1/crypto/bigint.c line 1197
0x4022f269: RSA_public at /Users/igrokhotkov/e/axtls/e1/crypto/rsa.c line 242
: (inlined by) RSA_encrypt at /Users/igrokhotkov/e/axtls/e1/crypto/rsa.c line 276
0x4022b374: send_client_key_xchg at /Users/igrokhotkov/e/axtls/e1/ssl/tls1_clnt.c line 352
0x4022b775: do_clnt_handshake at /Users/igrokhotkov/e/axtls/e1/ssl/tls1_clnt.c line 109
0x4022992d: DISPLAY_STATE at /Users/igrokhotkov/e/axtls/e1/ssl/tls1.c line 2047
0x4022b16c: do_handshake at /Users/igrokhotkov/e/axtls/e1/ssl/tls1.c line 1481
: (inlined by) basic_read at /Users/igrokhotkov/e/axtls/e1/ssl/tls1.c line 1357
0x4022b514: do_client_connect at /Users/igrokhotkov/e/axtls/e1/ssl/tls1_clnt.c line 154
0x401006f0: malloc at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc/umm_malloc.c line 1664
0x4022b2c4: ssl_read at /Users/igrokhotkov/e/axtls/e1/ssl/tls1.c line 265
0x402096b8: WiFiClient::_s_connected(void*, void*, signed char) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/WiFiClient.cpp line 327
0x40209df5: SSLContext::connect(ClientContext*, char const*, unsigned int) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/WiFiClientSecure.cpp line 517
: (inlined by) WiFiClientSecure::_connectSSL(char const*) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/WiFiClientSecure.cpp line 279
0x40208f4a: WiFiClient::connect(IPAddress, unsigned short) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/WiFiClient.cpp line 327
0x4020a2c1: WiFiClientSecure::connect(char const*, unsigned short) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src/WiFiClientSecure.cpp line 269
0x40207cd9: HTTPClient::connect() at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.cpp line 130
0x4020e902: SPIFFSImpl::open(char const*, fs::OpenMode, fs::AccessMode) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/spiffs_api.cpp line 53
0x40208609: HTTPClient::sendRequest(char const*, Stream*, unsigned int) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.cpp line 130
0x4020af84: FunctionRequestHandler::handle(ESP8266WebServer&, HTTPMethod, String) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src\detail/RequestHandlersImpl.h line 53
0x40207207: https_connect() at C:\Users\matobaa\Documents\Arduino\SpeechRecognitionByESP8266/SpeechRecognitionByESP8266.ino line 260
0x4020d424: String::changeBuffer(unsigned int) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/WString.cpp line 519
0x4020f212: std::_Function_handler ::_M_invoke(std::_Any_data const&) at c:\users\matobaa\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 2073
0x4020af7a: std::function ::operator()() const at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src\detail/RequestHandlersImpl.h line 53
0x4020afb6: FunctionRequestHandler::handle(ESP8266WebServer&, HTTPMethod, String) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src\detail/RequestHandlersImpl.h line 53
0x4020d5d4: String::String(String const&) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/WString.cpp line 519
0x4020b04d: ESP8266WebServer::_handleRequest() at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src\detail/RequestHandlersImpl.h line 53
0x4020a5ac: FunctionRequestHandler::canHandle(HTTPMethod, String) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src\detail/RequestHandlersImpl.h line 53
0x4020f21c: std::_Function_base::_Base_manager ::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\matobaa\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 1934
0x4020b257: ESP8266WebServer::handleClient() at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src\detail/RequestHandlersImpl.h line 53
0x4020cfac: Print::println() at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/Print.cpp line 76
0x4020cff8: Print::println(char const*) at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/Print.cpp line 76
0x4020f208: std::_Function_handler ::_M_invoke(std::_Any_data const&) at c:\users\matobaa\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 2069
0x4020f21c: std::_Function_base::_Base_manager ::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\matobaa\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 1934
0x40207004: webserver() at C:\Users\matobaa\Documents\Arduino\SpeechRecognitionByESP8266/SpeechRecognitionByESP8266.ino line 260
0x40206c2c: doPost() at C:\Users\matobaa\Documents\Arduino\SpeechRecognitionByESP8266/SpeechRecognitionByESP8266.ino line 260
0x4020f21c: std::_Function_base::_Base_manager ::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) at c:\users\matobaa\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 1934
0x4020f208: std::_Function_handler ::_M_invoke(std::_Any_data const&) at c:\users\matobaa\appdata\local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2/functional line 2069
0x40207083: setup at C:\Users\matobaa\Documents\Arduino\SpeechRecognitionByESP8266/SpeechRecognitionByESP8266.ino line 260
0x4020dffb: loop_wrapper at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/core_esp8266_main.cpp line 56
0x40100970: cont_norm at C:\Users\matobaa\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266/cont.S line 109
https://sourceforge.net/p/axtls/code/HEAD/tree/trunk/crypto/bigint.c#l1072 を見てみます:
static void more_comps(bigint *bi, int n)
{
if (n > bi->max_comps)
{
bi->max_comps = max(bi->max_comps * 2, n);
bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);
}
if (n > bi->size)
{
memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);
}
bi->size = n;
}
あらら。reallocに失敗すると bi->comps に null が入って、そのあとif文内に入るとmemsetでSEGVでちゃいますね。お見事でした。