Make Quick Power Cycle Detection Actually work

This commit is contained in:
Theo Arends 2020-08-13 16:25:48 +02:00
parent 731ca297b0
commit ef128fdafb

View File

@ -334,46 +334,62 @@ void SettingsSaveAll(void)
* Quick power cycle monitoring
\*********************************************************************************************/
void UpdateQuickPowerCycle(bool update)
{
void UpdateQuickPowerCycle(bool update) {
#ifndef FIRMWARE_MINIMAL
if (Settings.flag3.fast_power_cycle_disable) { return; } // SetOption65 - Disable fast power cycle detection for device reset
uint32_t pc_register;
uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES;
const uint32_t QPC_COUNT = 7; // Number of Power Cycles before Settings erase
const uint32_t QPC_SIGNATURE = 0xFFA55AFF;
#ifdef ESP8266
ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
#else // ESP32
QPCRead(&pc_register, sizeof(pc_register));
#endif // ESP8266 - ESP32
if (update && ((pc_register & 0xFFFFFF80) == 0xFFA55A80)) {
uint32_t counter = ((pc_register & 0x7F) << 1) & 0x7F;
if (0 == counter) { // 7 power cycles in a row
SettingsErase(3); // Quickly reset all settings including QuickPowerCycle flag
EspRestart(); // And restart
const uint32_t qpc_sector = SETTINGS_LOCATION - CFG_ROTATES;
const uint32_t qpc_location = qpc_sector * SPI_FLASH_SEC_SIZE;
uint32_t qpc_buffer[QPC_COUNT +1];
ESP.flashRead(qpc_location, (uint32*)&qpc_buffer, sizeof(qpc_buffer));
if (update && (QPC_SIGNATURE == qpc_buffer[0])) {
uint32_t counter = 1;
while ((0 == qpc_buffer[counter]) && (counter <= QPC_COUNT)) { counter++; }
if (QPC_COUNT == counter) { // 7 power cycles in a row
SettingsErase(3); // Quickly reset all settings including QuickPowerCycle flag
EspRestart(); // And restart
} else {
pc_register = 0xFFA55AB0 | counter;
#ifdef ESP8266
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
#else // ESP32
QPCWrite(&pc_register, sizeof(pc_register));
#endif // ESP8266 - ESP32
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter);
qpc_buffer[0] = 0;
ESP.flashWrite(qpc_location + (counter * 4), (uint32*)&qpc_buffer, 4);
AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Count %d"), counter);
}
}
else if (pc_register != 0xFFA55AFF) {
pc_register = 0xFFA55AFF;
#ifdef ESP8266
else if ((qpc_buffer[0] != QPC_SIGNATURE) || (0 == qpc_buffer[1])) {
qpc_buffer[0] = QPC_SIGNATURE;
// Assume flash is default all ones and setting a bit to zero does not need an erase
if (ESP.flashEraseSector(pc_location)) {
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
if (ESP.flashEraseSector(qpc_sector)) {
ESP.flashWrite(qpc_location, (uint32*)&qpc_buffer, 4);
AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Reset"));
}
#else // ESP32
QPCWrite(&pc_register, sizeof(pc_register));
#endif // ESP8266 - ESP32
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset"));
}
#else // ESP32
uint32_t pc_register;
QPCRead(&pc_register, sizeof(pc_register));
if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AF0)) {
uint32_t counter = pc_register & 0xF; // Allow up to 15 cycles
if (0xF == counter) { counter = 0; }
counter++;
if (QPC_COUNT == counter) { // 7 power cycles in a row
SettingsErase(3); // Quickly reset all settings including QuickPowerCycle flag
EspRestart(); // And restart
} else {
pc_register = 0xFFA55AF0 | counter;
QPCWrite(&pc_register, sizeof(pc_register));
AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Count %d"), counter);
}
}
else if (pc_register != QPC_SIGNATURE) {
pc_register = QPC_SIGNATURE;
QPCWrite(&pc_register, sizeof(pc_register));
AddLog_P2(LOG_LEVEL_INFO, PSTR("QPC: Reset"));
}
#endif // ESP8266 or ESP32
#endif // FIRMWARE_MINIMAL
}
@ -556,6 +572,7 @@ void SettingsLoad(void) {
#ifdef ESP8266
// Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate
#ifdef CFG_LEGACY_LOAD
// Active until version 8.4.0.2
struct {
uint16_t cfg_holder; // 000
uint16_t cfg_size; // 002
@ -598,11 +615,11 @@ void SettingsLoad(void) {
AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag);
}
#else // CFG_RESILIENT
// Activated with version 8.4.0.2
settings_location = 0;
uint32_t save_flag = 0;
uint32_t flash_location = SETTINGS_LOCATION +1;
uint32_t flash_location = SETTINGS_LOCATION;
for (uint32_t i = 0; i < CFG_ROTATES; i++) { // Read all config pages in search of valid and latest
flash_location--;
ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings));
if ((Settings.cfg_crc32 != 0xFFFFFFFF) && (Settings.cfg_crc32 != 0x00000000) && (Settings.cfg_crc32 == GetSettingsCrc32())) {
if (Settings.save_flag > save_flag) { // Find latest page based on incrementing save_flag
@ -613,6 +630,7 @@ void SettingsLoad(void) {
}
}
}
flash_location--;
delay(1);
}
if (settings_location > 0) {