From f7c38f24f3b7f1ad0c2ac0951b9629b4b3d6c616 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 30 Aug 2018 14:27:33 +0200 Subject: [PATCH] 6.1.1.14 Add boot loop detection Add boot loop detection and try to fix --- sonoff/_changelog.ino | 5 ++++- sonoff/i18n.h | 1 + sonoff/settings.h | 7 +++++-- sonoff/settings.ino | 8 ++++++++ sonoff/sonoff.h | 1 + sonoff/sonoff.ino | 35 ++++++++++++++++++++++++++++++----- sonoff/sonoff_template.h | 28 ++++++++++++++++++++++++++-- sonoff/sonoff_version.h | 2 +- sonoff/support.ino | 9 +++++++++ sonoff/xdrv_02_webserver.ino | 6 +++--- sonoff/xdrv_09_timers.ino | 2 +- 11 files changed, 89 insertions(+), 15 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 0629de523..dcc60cc55 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.1.1.13 20180828 +/* 6.1.1.14 20180830 + * Add boot loop detection and try to fix + * + * 6.1.1.13 20180828 * Fix 6.1.1.12 regression of Mem and Var default handling (#3618) * Optimizations * Change define USE_ALL_SENSORS to USE_SENSORS as it doesn't contain all sensors due to duplicate I2C addresses diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 3d63f73f5..107710678 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -236,6 +236,7 @@ #define D_CMND_SERIALSEND "SerialSend" #define D_CMND_SERIALDELIMITER "SerialDelimiter" #define D_CMND_BAUDRATE "Baudrate" +#define D_LOG_SOME_SETTINGS_RESET "Some settings have been reset" // Commands xdrv_01_mqtt.ino #define D_CMND_MQTTHOST "MqttHost" diff --git a/sonoff/settings.h b/sonoff/settings.h index 618ef0b54..ded2c140b 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -94,7 +94,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu uint32_t spare28 : 1; uint32_t spare29 : 1; uint32_t spare30 : 1; - uint32_t spare31 : 1; + uint32_t user_esp8285_enable : 1; // bit 31 (v6.1.1.14) }; } SysBitfield3; @@ -341,7 +341,10 @@ struct RTCMEM { unsigned long energy_kWhtotal; // 008 unsigned long pulse_counter[MAX_COUNTERS]; // 00C power_t power; // 01C - // 020 next free location + uint16_t extended_valid; // 020 Extended valid flag (v6.1.1.14) + uint8_t fast_reboot_count; // 022 + uint8_t free_023[57]; // 023 + // 05C next free location (64 (=core) + 100 (=tasmota offset) + 92 (=0x5C RTCMEM struct) = 256 bytes (max = 512)) } RtcSettings; struct TIME_T { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index e0a40a17c..cba043696 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -84,6 +84,7 @@ void RtcSettingsSave() { if (GetRtcSettingsCrc() != rtc_settings_crc) { RtcSettings.valid = RTC_MEM_VALID; + RtcSettings.extended_valid = RTC_MEM_VALID; ESP.rtcUserMemoryWrite(100, (uint32_t*)&RtcSettings, sizeof(RTCMEM)); rtc_settings_crc = GetRtcSettingsCrc(); #ifdef DEBUG_THEO @@ -103,12 +104,14 @@ void RtcSettingsLoad() if (RtcSettings.valid != RTC_MEM_VALID) { memset(&RtcSettings, 0, sizeof(RTCMEM)); RtcSettings.valid = RTC_MEM_VALID; + RtcSettings.extended_valid = RTC_MEM_VALID; RtcSettings.energy_kWhtoday = Settings.energy_kWhtoday; RtcSettings.energy_kWhtotal = Settings.energy_kWhtotal; for (byte i = 0; i < MAX_COUNTERS; i++) { RtcSettings.pulse_counter[i] = Settings.pulse_counter[i]; } RtcSettings.power = Settings.power; +// RtcSettings.fast_reboot_count = 0; // Explicit by memset RtcSettingsSave(); } rtc_settings_crc = GetRtcSettingsCrc(); @@ -119,6 +122,11 @@ boolean RtcSettingsValid() return (RTC_MEM_VALID == RtcSettings.valid); } +boolean RtcSettingsExtendedValid() +{ + return (RTC_MEM_VALID == RtcSettings.extended_valid); +} + /*********************************************************************************************\ * Config - Flash \*********************************************************************************************/ diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index f93df0059..3a1dc14c6 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -85,6 +85,7 @@ typedef unsigned long power_t; // Power (Relay) type #define STATES 20 // Number of states per second using 50 mSec interval #define IMMINENT_RESET_FACTOR 10 // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 +#define BOOT_LOOP_TIME 10 // Number of seconds to stop detecting boot loops #define SYSLOG_TIMER 600 // Seconds to restore syslog_level #define SERIALLOG_TIMER 600 // Seconds to disable SerialLog #define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 8cd69e4cc..2e080aa18 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1567,6 +1567,11 @@ void PerformEverySecond() { uptime++; + if (BOOT_LOOP_TIME == uptime) { + RtcSettings.fast_reboot_count = 0; + RtcSettingsSave(); + } + if ((4 == uptime) && (SONOFF_IFAN02 == Settings.module)) { // Microcontroller needs 3 seconds before accepting commands SetDevicePower(1, SRC_RETRY); // Sync with default power on state microcontroller being Light ON and Fan OFF SetDevicePower(power, SRC_RETRY); // Set required power on state @@ -2313,7 +2318,7 @@ void GpioInit() pin[i] = 99; } for (byte i = 0; i < MAX_GPIO_PIN; i++) { - mpin = my_module.gp.io[i]; + mpin = ValidGPIO(i, my_module.gp.io[i]); // snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin); // AddLog(LOG_LEVEL_DEBUG); @@ -2323,7 +2328,7 @@ void GpioInit() bitSet(switch_no_pullup, mpin - GPIO_SWT1_NP); mpin -= (GPIO_SWT1_NP - GPIO_SWT1); } - if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { + else if ((mpin >= GPIO_KEY1_NP) && (mpin < (GPIO_KEY1_NP + MAX_KEYS))) { bitSet(key_no_pullup, mpin - GPIO_KEY1_NP); mpin -= (GPIO_KEY1_NP - GPIO_KEY1); } @@ -2486,6 +2491,11 @@ void setup() { byte idx; + RtcSettingsLoad(); + if (!RtcSettingsExtendedValid()) { RtcSettings.fast_reboot_count = 0; } + RtcSettings.fast_reboot_count++; + RtcSettingsSave(); + Serial.begin(baudrate); delay(10); Serial.println(); @@ -2517,10 +2527,25 @@ void setup() save_data_counter = Settings.save_data; sleep = Settings.sleep; - if ((resetInfo.reason == REASON_WDT_RST) || (resetInfo.reason == REASON_EXCEPTION_RST) || (resetInfo.reason == REASON_SOFT_WDT_RST) || OsWatchBlockedLoop()) { - for (byte i = 0; i < MAX_RULE_SETS; i++) { - if (bitRead(Settings.rule_stop, i)) { bitWrite(Settings.rule_enabled, i, 0); } + // Disable functionality as possible cause of fast reboot within BOOT_LOOP_TIME seconds (Exception or WDT) + if (RtcSettings.fast_reboot_count > 1) { // Restart twice + Settings.flag3.user_esp8285_enable = 0; // Disable ESP8285 Generic GPIOs interfering with flash SPI + if (RtcSettings.fast_reboot_count > 2) { // Restart 3 times + for (byte i = 0; i < MAX_RULE_SETS; i++) { + if (bitRead(Settings.rule_stop, i)) { + bitWrite(Settings.rule_enabled, i, 0); // Disable rules causing boot loop + } + } } + if (RtcSettings.fast_reboot_count > 3) { // Restarted 4 times + Settings.rule_enabled = 0; // Disable all rules + } + if (RtcSettings.fast_reboot_count > 4) { // Restarted 5 times + Settings.module = SONOFF_BASIC; // Use default module + Settings.last_module = SONOFF_BASIC; // Use default module + } + snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcSettings.fast_reboot_count); + AddLog(LOG_LEVEL_DEBUG); } Settings.bootcount++; diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 180c24aec..84a0749dc 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -226,7 +226,7 @@ enum SupportedModules { #define MAX_GPIO_PIN 18 // Number of supported GPIO -const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcontrolD6D7D5D8D0A0"; +const char PINS_WEMOS[] PROGMEM = "D3TXD4RXD2D1flashcFLFLolD6D7D5D8D0A0"; typedef struct MYIO { uint8_t io[MAX_GPIO_PIN]; @@ -514,7 +514,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor GPIO_USER, // GPIO04 D2 Wemos I2C SDA GPIO_USER, // GPIO05 D1 Wemos I2C SCL / Wemos Relay Shield (0 = Off, 1 = On) / Wemos WS2812B RGB led Shield - 0, 0, 0, 0, 0, 0, // Flash connection + 0, 0, 0, // Flash connection + GPIO_USER, // Flash connection or GPIO09 on ESP8285 only! + GPIO_USER, // Flash connection or GPIO10 on ESP8285 only! + 0, // Flash connection GPIO_USER, // GPIO12 D6 GPIO_USER, // GPIO13 D7 GPIO_USER, // GPIO14 D5 @@ -987,6 +990,27 @@ const mytmplt kModules[MAXMODULE] PROGMEM = { 0 // ADC0 Analog input (A0) }, + { "Shelly 1", // Shelly1 Open Source (ESP8266 - 2MB) - https://shelly.cloud/shelly1-open-source/ + GPIO_KEY1, // GPIO00 Button + GPIO_USER, // GPIO01 Serial RXD and Optional sensor + 0, + GPIO_USER, // GPIO03 Serial TXD and Optional sensor + GPIO_REL1, // GPIO04 Relay (0 = Off, 1 = On) + GPIO_SWT1_NP, // GPIO05 Switch + 0, 0, 0, 0, 0, 0, // Flash connection + 0, 0, 0, 0, 0, 0 + }, + { "Shelly 2", // Shelly2 (ESP8266 - 2MB) - https://shelly.cloud/shelly2/ + // As Gnd is connected to AC no user GPIO allowed + 0, 0, 0, 0, + GPIO_REL1, // GPIO04 Relay 1 (0 = Off, 1 = On) + GPIO_REL2, // GPIO05 Relay 2 (0 = Off, 1 = On) + 0, 0, 0, 0, 0, 0, // Flash connection + GPIO_SWT1_NP, // GPIO12 Switch 1 + 0, + GPIO_SWT2_NP, // GPIO14 Switch 2 + 0, 0, 0 + }, */ #endif // _SONOFF_TEMPLATE_H_ \ No newline at end of file diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index f351b547d..72634caa1 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x0601010D +#define VERSION 0x0601010E #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/support.ino b/sonoff/support.ino index 87cd49edb..8cc064fe5 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -717,6 +717,15 @@ void ShowSource(int source) } } +uint8_t ValidGPIO(uint8_t pin, uint8_t gpio) +{ + uint8_t result = gpio; + if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) { + if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } // Disable possible flash GPIO9 and GPIO10 + } + return result; +} + /*********************************************************************************************\ * Sleep aware time scheduler functions borrowed from ESPEasy \*********************************************************************************************/ diff --git a/sonoff/xdrv_02_webserver.ino b/sonoff/xdrv_02_webserver.ino index 64c138a56..c919c8f43 100644 --- a/sonoff/xdrv_02_webserver.ino +++ b/sonoff/xdrv_02_webserver.ino @@ -789,7 +789,7 @@ void HandleModuleConfiguration() page += FPSTR(HTTP_SCRIPT_MODULE3); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_USER == cmodule.gp.io[i]) { + if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("sk(%d,%d);"), my_module.gp.io[i], i); // g0 - g16 page += mqtt_data; } @@ -803,10 +803,10 @@ void HandleModuleConfiguration() page.replace(F("{mt"), stemp); page += F("
"); for (byte i = 0; i < MAX_GPIO_PIN; i++) { - if (GPIO_USER == cmodule.gp.io[i]) { + if (GPIO_USER == ValidGPIO(i, cmodule.gp.io[i])) { snprintf_P(stemp, 3, PINS_WEMOS +i*2); snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(""), - (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); + (WEMOS==Settings.module)?stemp:"", i, (0==i)? D_SENSOR_BUTTON "1":(1==i)? D_SERIAL_OUT :(3==i)? D_SERIAL_IN :(9==i)? "ESP8285" :(10==i)? "ESP8285" :(12==i)? D_SENSOR_RELAY "1":(13==i)? D_SENSOR_LED "1i":(14==i)? D_SENSOR :"", i, i); page += mqtt_data; } } diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 229b55d69..0652f3b53 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -457,7 +457,7 @@ boolean TimerCommand() } if (XdrvMailbox.payload == 2) { Settings.flag3.timers_enable = !Settings.flag3.timers_enable; - } + } } snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable));
%s " D_GPIO "%d %s