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("
%s " D_GPIO "%d %s |