diff --git a/tasmota/support.ino b/tasmota/support.ino index f44d14eb7..14f21db01 100644 --- a/tasmota/support.ino +++ b/tasmota/support.ino @@ -107,12 +107,6 @@ String GetResetReason(void) } } -String GetResetReasonInfo(void) -{ - // "Fatal exception:0 flag:2 (EXCEPTION) epc1:0x704022a7 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000000 depc:0x00000000" - return (ResetReason() == REASON_EXCEPTION_RST) ? ESP.getResetInfo() : GetResetReason(); -} - /*********************************************************************************************\ * Miscellaneous \*********************************************************************************************/ diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino index f6baeef4e..09495f55a 100644 --- a/tasmota/support_command.ino +++ b/tasmota/support_command.ino @@ -334,6 +334,9 @@ void CmndStatus(void) if ((!Settings.flag.mqtt_enabled) && (6 == payload)) { payload = 99; } // SetOption3 - Enable MQTT if (!energy_flg && (9 == payload)) { payload = 99; } + bool exception_flg = (ResetReason() == REASON_EXCEPTION_RST); + if (!exception_flg && (12 == payload)) { payload = 99; } + if ((0 == payload) || (99 == payload)) { uint32_t maxfn = (devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!devices_present) ? 1 : devices_present; #ifdef USE_SONOFF_IFAN @@ -369,7 +372,7 @@ void CmndStatus(void) D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), baudrate, Settings.mqtt_grptopic, Settings.ota_url, - GetResetReasonInfo().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, + GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } @@ -483,11 +486,13 @@ void CmndStatus(void) MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } - if ((0 == payload) || (12 == payload)) { - Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); - CrashDump(); - ResponseJsonEnd(); - MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + if (exception_flg) { + if ((0 == payload) || (12 == payload)) { + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS12_STATUS "\":")); + CrashDump(); + ResponseJsonEnd(); + MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "12")); + } } #ifdef USE_SCRIPT_STATUS diff --git a/tasmota/support_crash_recorder.ino b/tasmota/support_crash_recorder.ino index c89fa681b..87009bbc5 100644 --- a/tasmota/support_crash_recorder.ino +++ b/tasmota/support_crash_recorder.ino @@ -1,5 +1,5 @@ /* - support_crash_recorder.ino - record the call stack in RTC in cas of crash + support_crash_recorder.ino - record the call stack in RTC in case of crash Copyright (C) 2019 Stephan Hadinger, Theo Arends, @@ -17,30 +17,30 @@ along with this program. If not, see . */ -const uint32_t dump_max_len = 63; // dump only 64 call addresses +const uint32_t crash_magic = 0x53415400; // Stack trace magic number (TASx) +const uint32_t crash_rtc_offset = 32; // Offset in RTC memory skipping OTA used block +const uint32_t crash_dump_max_len = 31; // Dump only 31 call addresses to satisfy max JSON length of about 600 characters /** * Save crash information in RTC memory * This function is called automatically if ESP8266 suffers an exception * It should be kept quick / consise to be able to execute before hardware wdt may kick in */ -extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) { +extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end ) +{ uint32_t addr_written = 0; // how many addresses have we already written in RTC uint32_t value; // 4 bytes buffer to write to RTC for (uint32_t i = stack; i < stack_end; i += 4) { value = *((uint32_t*) i); // load value from stack if ((value >= 0x40000000) && (value < 0x40300000)) { // keep only addresses in code area - ESP.rtcUserMemoryWrite(addr_written, (uint32_t*)&value, sizeof(value)); + ESP.rtcUserMemoryWrite(crash_rtc_offset + addr_written, (uint32_t*)&value, sizeof(value)); addr_written++; - if (addr_written >= dump_max_len) { break; } // we store only 63 addresses + if (addr_written >= crash_dump_max_len) { break; } // we store only 31 addresses } } - // fill the rest of RTC with the amount of addresses - value = addr_written; - while (addr_written < dump_max_len +1) { - ESP.rtcUserMemoryWrite(addr_written++, (uint32_t*)&value, sizeof(value)); - } + value = crash_magic + addr_written; + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); } // Generate a crash to test the crash recorder @@ -51,26 +51,39 @@ void CmndCrash(void) } // Clear the RTC dump counter when we do a normal reboot, this avoids garbage data to stay in RTC -void CrashDumpClear(void) { +void CrashDumpClear(void) +{ uint32_t value = 0; - ESP.rtcUserMemoryWrite(dump_max_len, (uint32_t*)&value, sizeof(value)); + ESP.rtcUserMemoryWrite(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); } /*********************************************************************************************\ * CmndCrashDump - dump the crash history - called by `Status 12` \*********************************************************************************************/ + void CrashDump(void) { - ResponseAppend_P(PSTR("{\"call_chain\":[")); + ResponseAppend_P(PSTR("{\"Exception\":%d,\"Reason\":\"%s\",\"EPC\":[\"%08x\",\"%08x\",\"%08x\"],\"EXCVADDR\":\"%08x\",\"DEPC\":\"%08x\""), + resetInfo.exccause, // Exception Cause + GetResetReason().c_str(), // Reset Reason + resetInfo.epc1, // Exception Progam Counter + resetInfo.epc2, // Exception Progam Counter - High-Priority Interrupt 1 + resetInfo.epc3, // Exception Progam Counter - High-Priority Interrupt 2 + resetInfo.excvaddr, // Exception Virtual Address Register - Virtual address that caused last fetch, load, or store exception + resetInfo.depc); // Double Exception Program Counter uint32_t value; - ESP.rtcUserMemoryRead(dump_max_len, (uint32_t*)&value, sizeof(value)); - uint32_t count = value & 0x3F; - - for (uint32_t i = 0; i < count; i++) { - ESP.rtcUserMemoryRead(i, (uint32_t*)&value, sizeof(value)); - if (i > 0) { ResponseAppend_P(PSTR(",")); } - ResponseAppend_P(PSTR("\"%08x\""), value); + ESP.rtcUserMemoryRead(crash_rtc_offset + crash_dump_max_len, (uint32_t*)&value, sizeof(value)); + if (crash_magic == (value & 0xFFFFFF00)) { + ResponseAppend_P(PSTR(",\"CallChain\":[")); + uint32_t count = value & 0x3F; + for (uint32_t i = 0; i < count; i++) { + ESP.rtcUserMemoryRead(crash_rtc_offset +i, (uint32_t*)&value, sizeof(value)); + if (i > 0) { ResponseAppend_P(PSTR(",")); } + ResponseAppend_P(PSTR("\"%08x\""), value); + } + ResponseAppend_P(PSTR("]")); } - ResponseAppend_P(PSTR("]}")); + + ResponseJsonEnd(); } diff --git a/tasmota/xdrv_02_mqtt.ino b/tasmota/xdrv_02_mqtt.ino index a6994ebfb..d31d0a860 100644 --- a/tasmota/xdrv_02_mqtt.ino +++ b/tasmota/xdrv_02_mqtt.ino @@ -555,7 +555,7 @@ void MqttConnected(void) MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER - Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReasonInfo().c_str()); + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReason().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); MqttPublishAllPowerState(); if (Settings.tele_period) {