Implement a bootlog to register reboot reason and debug info. Wait for NTP sync event, maximum for 60 seconds.

This commit is contained in:
Robert van den Breemen 2021-12-04 10:58:34 +01:00
parent 42c1792f9d
commit eb1d83449b
2 changed files with 121 additions and 4 deletions

View File

@ -43,14 +43,11 @@ void setup() {
OTGWSerial.println(F("\r\n[OTGW firmware - Nodoshop version]\r\n"));
OTGWSerial.printf("Booting....[%s]\r\n\r\n", String(_FW_VERSION).c_str());
rebootCount = updateRebootCount();
WatchDogEnabled(0); // turn off watchdog
//setup randomseed the right way
randomSeed(RANDOM_REG32); //This is 8266 HWRNG used to seed the Random PRNG: Read more: https://config9.com/arduino/getting-a-truly-random-number-in-arduino/
lastReset = ESP.getResetReason();
OTGWSerial.printf("Last reset reason: [%s]\r\n", CSTR(ESP.getResetReason()));
//setup the status LED
setLed(LED1, ON);
setLed(LED2, ON);
@ -75,6 +72,12 @@ void setup() {
startNTP();
setupFSexplorer();
startWebserver();
lastReset = ESP.getResetReason();
OTGWSerial.printf("Last reset reason: [%s]\r\n", CSTR(ESP.getResetReason()));
rebootCount = updateRebootCount();
updateRebootLog(ESP.getResetReason());
OTGWSerial.println(F("Setup finished!\r\n"));
// After resetting the OTGW PIC never send anything to Serial for debug
// and switch to telnet port 23 for debug purposed.

View File

@ -548,6 +548,120 @@ uint32_t updateRebootCount()
return _reboot;
}
bool updateRebootLog(String text)
{
#define REBOOTLOG_FILE "/reboot_log.txt"
#define TEMPLOG_FILE "/reboot_log.t.txt"
#define LOG_LINES 20
#define LOG_LINE_LENGTH 140
char log_line[LOG_LINE_LENGTH] = {0};
char log_line_regs[LOG_LINE_LENGTH] = {0};
char log_line_excpt[LOG_LINE_LENGTH] = {0};
uint32_t errorCode = -1;
loopNTP(); // make sure time is up to date
struct rst_info *rtc_info = system_get_rst_info();
if (rtc_info == NULL) {
DebugTf("no reset info available: %x\r\n", errorCode);
} else {
DebugTf("reset reason: %x\r\n", rtc_info->reason);
errorCode = rtc_info->reason;
// Rst cause No. Cause GPIO state
//-------------- ------------------- -------------
// 0 Power reboot Changed
// 1 Hardware WDT reset Changed
// 2 Fatal exception Unchanged
// 3 Software watchdog reset Unchanged
// 4 Software reset Unchanged
// 5 Deep-sleep Changed
// 6 Hardware reset Changed
if (rtc_info->reason == REASON_WDT_RST || rtc_info->reason == REASON_EXCEPTION_RST || rtc_info->reason == REASON_SOFT_WDT_RST) {
//The address of the last crash is printed, which is used to debug garbled output
snprintf(log_line_regs, LOG_LINE_LENGTH,"ESP register contents: epc1=0x%08x, epc2=0x%08x, epc3=0x%08x, excvaddr=0x%08x, depc=0x%08x\r\n", rtc_info->epc1, rtc_info->epc2, rtc_info->epc3, rtc_info->excvaddr, rtc_info->depc);
Debugf(log_line_regs);
}
if (rtc_info->reason == REASON_EXCEPTION_RST) {
// Fatal exception No. Description Possible Causes
// ------------------- -------------- -------------------
// 0 Invalid command 1. Damaged BIN binaries
// 2. Wild pointers
//
// 6 Division by zero Division by zero
//
// 9 Unaligned read/write 1. Unaligned read/write Cache addresses
// operation addresses 2. Wild pointers
//
// 28/29 Access to invalid 1. Access to Cache after it is turned off
// address 2. Wild pointers
//
// more reasons can be found in the "corebits.h" file of the Extensa SDK
switch(rtc_info->exccause) {
case 0: snprintf(log_line_excpt, LOG_LINE_LENGTH, "- Invalid command (0)"); break;
case 6: snprintf(log_line_excpt, LOG_LINE_LENGTH, "- Division by zero (6)"); break;
case 9: snprintf(log_line_excpt, LOG_LINE_LENGTH, "- Unaligned read/write operation addresses (9)"); break;
case 28: snprintf(log_line_excpt, LOG_LINE_LENGTH, "- Access to invalid address (28)"); break;
case 29: snprintf(log_line_excpt, LOG_LINE_LENGTH, "- Access to invalid address (29)"); break;
default: snprintf(log_line_excpt, LOG_LINE_LENGTH, "- Other (not specified) (%d)", rtc_info->exccause); break;
}
Debugf("Fatal exception (%d): %s\r\n", rtc_info->exccause, log_line_excpt);
}
}
snprintf(log_line, LOG_LINE_LENGTH, "%d-%02d-%02d %02d:%02d:%02d - reboot cause: %s (%x) %s\r\n", year(), month(), day(), hour(), minute(), second(), CSTR(text), errorCode, log_line_excpt);
if (LittleFS.begin()) {
//start with opening the file
File outfh = LittleFS.open(TEMPLOG_FILE, "w");
if (outfh) {
//write to _reboot to file
outfh.print(log_line);
if (strlen(log_line_regs)>2) {
outfh.print(log_line_regs);
}
File infh = LittleFS.open(REBOOTLOG_FILE, "r");
int i = 1;
if (infh) {
//read from file
while (infh.available() && (i < LOG_LINES)){
//read the first line
String line = infh.readStringUntil('\r\n');
if (line.length() > 3) { //TODO: check is no longer needed?
outfh.print(line);
}
i++;
}
infh.close();
}
outfh.close();
if (LittleFS.exists(REBOOTLOG_FILE)) {
LittleFS.remove(REBOOTLOG_FILE);
}
LittleFS.rename(TEMPLOG_FILE, REBOOTLOG_FILE);
return true; // succesfully logged
}
}
return false; // logging unsuccesfull
}
void doRestart(const char* str) {
DebugTln(str);
delay(2000); // Enough time for messages to be sent.