From c37dde93c244d7e4e86189fde13d4c56f34863b1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 19 Apr 2020 15:36:04 +0200 Subject: [PATCH] Add ESP32 QuickPowerCycle control --- .../src/esp8266toEsp32.cpp | 9 -- .../src/esp8266toEsp32.h | 3 - tasmota/settings.h | 2 +- tasmota/settings.ino | 50 +++++--- tasmota/support_esp32.ino | 116 ++++++++++-------- tasmota/tasmota_compat.h | 5 - tasmota/xdrv_99_debug.ino | 6 +- 7 files changed, 100 insertions(+), 91 deletions(-) diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp index bfbf26419..c25845922 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.cpp @@ -99,12 +99,3 @@ uint32_t ESP_getSketchSize(void) } return sketchsize; } - -#include "soc/soc.h" -#include "soc/rtc_cntl_reg.h" - -void DisableBrownout(void) -{ - // https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737 - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector -} diff --git a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h index 3af2c12c5..92184d4a7 100644 --- a/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h +++ b/libesp32/ESP32-to-ESP8266-compat/src/esp8266toEsp32.h @@ -31,8 +31,6 @@ // // ESP32 // -#define ESP_flashReadHeader(offset, data, size) ESP32_flashRead(offset, data, size) -#define ESP_flashRead(offset, data, size) ESP32_flashRead(offset, data, size) String ESP_getResetReason(void); uint32_t ESP_ResetInfoReason(void); uint32_t ESP_getBootVersion(void); @@ -41,7 +39,6 @@ uint32_t ESP_getFlashChipId(); uint32_t ESP_getChipId(); String String_ESP_getChipId(); uint32_t ESP_getSketchSize(); -void DisableBrownout(void); // Analog inline void analogWrite(uint8_t pin, int val) diff --git a/tasmota/settings.h b/tasmota/settings.h index 5b862280e..7ea3b5e3e 100644 --- a/tasmota/settings.h +++ b/tasmota/settings.h @@ -253,7 +253,7 @@ typedef struct { const uint32_t settings_text_size = 699; // Settings.text_pool[size] = Settings.display_model (2D2) - Settings.text_pool (017) const uint8_t MAX_TUYA_FUNCTIONS = 16; -struct SYSCFG { +struct { uint16_t cfg_holder; // 000 v6 header uint16_t cfg_size; // 002 unsigned long save_flag; // 004 diff --git a/tasmota/settings.ino b/tasmota/settings.ino index cff437d67..c6cc355b4 100644 --- a/tasmota/settings.ino +++ b/tasmota/settings.ino @@ -305,7 +305,7 @@ uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size) uint16_t GetSettingsCrc(void) { // Fix miscalculation if previous Settings was 3584 and current Settings is 4096 between 0x06060007 and 0x0606000A - uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(SYSCFG); + uint32_t size = ((Settings.version < 0x06060007) || (Settings.version > 0x0606000A)) ? 3584 : sizeof(Settings); return GetCfgCrc16((uint8_t*)&Settings, size); } @@ -325,7 +325,7 @@ uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size) uint32_t GetSettingsCrc32(void) { - return GetCfgCrc32((uint8_t*)&Settings, sizeof(SYSCFG) -4); // Skip crc32 + return GetCfgCrc32((uint8_t*)&Settings, sizeof(Settings) -4); // Skip crc32 } void SettingsSaveAll(void) @@ -351,7 +351,11 @@ void UpdateQuickPowerCycle(bool update) uint32_t pc_register; uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; +#ifdef ESP8266 ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); +#else + QPCRead(&pc_register, sizeof(pc_register)); +#endif if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) { uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; if (0 == counter) { // 4 power cycles in a row @@ -359,16 +363,24 @@ void UpdateQuickPowerCycle(bool update) 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 + QPCWrite(&pc_register, sizeof(pc_register)); +#endif AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter); } } else if (pc_register != 0xFFA55ABF) { pc_register = 0xFFA55ABF; +#ifdef ESP8266 // 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)); } +#else + QPCWrite(&pc_register, sizeof(pc_register)); +#endif AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset")); } } @@ -501,13 +513,13 @@ void SettingsSave(uint8_t rotate) } else { Settings.cfg_timestamp++; } - Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_size = sizeof(Settings); Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade Settings.cfg_crc32 = GetSettingsCrc32(); #ifdef ESP8266 if (ESP.flashEraseSector(settings_location)) { - ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); } if (!stop_flash_rotate && rotate) { @@ -516,12 +528,12 @@ void SettingsSave(uint8_t rotate) delay(1); } } + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(Settings)); #else // ESP32 - SettingsSaveMain(&Settings, sizeof(SYSCFG)); + SettingsWrite(&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG "Saved, " D_COUNT " %d, " D_BYTES " %d"), Settings.save_flag, sizeof(Settings)); #endif // ESP8266 - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_SAVED_TO_FLASH_AT " %X, " D_COUNT " %d, " D_BYTES " %d"), settings_location, Settings.save_flag, sizeof(SYSCFG)); - settings_crc32 = Settings.cfg_crc32; } #endif // FIRMWARE_MINIMAL @@ -530,8 +542,9 @@ void SettingsSave(uint8_t rotate) void SettingsLoad(void) { +#ifdef ESP8266 // Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate - struct SYSCFGH { + struct { uint16_t cfg_holder; // 000 uint16_t cfg_size; // 002 unsigned long save_flag; // 004 @@ -543,7 +556,7 @@ void SettingsLoad(void) uint16_t cfg_holder = 0; for (uint32_t i = 0; i < CFG_ROTATES; i++) { flash_location--; - ESP_flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); bool valid = false; if (Settings.version > 0x06000000) { bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); @@ -554,7 +567,7 @@ void SettingsLoad(void) if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder valid = (cfg_holder == Settings.cfg_holder); } else { - ESP_flashReadHeader((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); + ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(_SettingsH)); valid = (Settings.cfg_holder == _SettingsH.cfg_holder); } if (valid) { @@ -566,13 +579,16 @@ void SettingsLoad(void) } } } - delay(1); } if (settings_location > 0) { - ESP_flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); + ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(Settings)); AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); } +#else // ESP32 + SettingsRead(&Settings, sizeof(Settings)); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG "Loaded, " D_COUNT " %lu"), Settings.save_flag); +#endif // ESP8266 - ESP32 #ifndef FIRMWARE_MINIMAL if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h @@ -683,10 +699,10 @@ void SettingsDefault(void) void SettingsDefaultSet1(void) { - memset(&Settings, 0x00, sizeof(SYSCFG)); + memset(&Settings, 0x00, sizeof(Settings)); Settings.cfg_holder = (uint16_t)CFG_HOLDER; - Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_size = sizeof(Settings); // Settings.save_flag = 0; Settings.version = VERSION; // Settings.bootcount = 0; @@ -695,7 +711,7 @@ void SettingsDefaultSet1(void) void SettingsDefaultSet2(void) { - memset((char*)&Settings +16, 0x00, sizeof(SYSCFG) -16); + memset((char*)&Settings +16, 0x00, sizeof(Settings) -16); Settings.flag.stop_flash_rotate = APP_FLASH_CYCLE; Settings.flag.global_state = APP_ENABLE_LEDLINK; @@ -1064,7 +1080,7 @@ void SettingsDelta(void) #ifdef ESP8266 if (Settings.version < 0x06000000) { - Settings.cfg_size = sizeof(SYSCFG); + Settings.cfg_size = sizeof(Settings); Settings.cfg_crc = GetSettingsCrc(); } if (Settings.version < 0x06000002) { @@ -1148,7 +1164,7 @@ void SettingsDelta(void) Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; } if (Settings.version < 0x06060007) { - memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); + memset((char*)&Settings +0xE00, 0x00, sizeof(Settings) -0xE00); } if (Settings.version < 0x06060008) { // Move current tuya dimmer range to the new param. diff --git a/tasmota/support_esp32.ino b/tasmota/support_esp32.ino index 1e2a4e0ca..d9f6ab390 100644 --- a/tasmota/support_esp32.ino +++ b/tasmota/support_esp32.ino @@ -22,6 +22,39 @@ #include #include +void NvmLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen) +{ + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READONLY, &handle); + size_t size = nSettingsLen; + nvs_get_blob(handle, sName, pSettings, &size); + nvs_close(handle); + interrupts(); +} + +void NvmSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) +{ + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READWRITE, &handle); + nvs_set_blob(handle, sName, pSettings, nSettingsLen); + nvs_commit(handle); + nvs_close(handle); + interrupts(); +} + +void NvmErase(const char *sNvsName) +{ + nvs_handle handle; + noInterrupts(); + nvs_open(sNvsName, NVS_READWRITE, &handle); + nvs_erase_all(handle); + nvs_commit(handle); + nvs_close(handle); + interrupts(); +} + void SettingsErase(uint8_t type) { if (1 == type) // SDK parameter area @@ -34,75 +67,39 @@ void SettingsErase(uint8_t type) { } - noInterrupts(); - nvs_handle handle; - nvs_open("main", NVS_READWRITE, &handle); - nvs_erase_all(handle); - nvs_commit(handle); - nvs_close(handle); - interrupts(); + NvmErase("main"); AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " t=%d"), type); } -void SettingsLoad(const char *sNvsName, const char *sName, void *pSettings, unsigned nSettingsLen) +void SettingsRead(void *data, size_t size) { - noInterrupts(); - nvs_handle handle; - size_t size; - nvs_open(sNvsName, NVS_READONLY, &handle); - size = nSettingsLen; - nvs_get_blob(handle, sName, pSettings, &size); - nvs_close(handle); - interrupts(); + NvmLoad("main", "Settings", data, size); } -void SettingsSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) +void SettingsWrite(const void *pSettings, unsigned nSettingsLen) { - nvs_handle handle; - noInterrupts(); - nvs_open(sNvsName, NVS_READWRITE, &handle); - nvs_set_blob(handle, sName, pSettings, nSettingsLen); - nvs_commit(handle); - nvs_close(handle); - interrupts(); + NvmSave("main", "Settings", pSettings, nSettingsLen); } -void ESP32_flashRead(uint32_t offset, uint32_t *data, size_t size) -{ - SettingsLoad("main", "Settings", data, size); -} - -void ESP32_flashReadHeader(uint32_t offset, uint32_t *data, size_t size) -{ - SettingsLoad("main", "SettingsH", data, size); -} - -void SettingsSaveMain(const void *pSettings, unsigned nSettingsLen) -{ - SettingsSave("main", "Settings", pSettings, nSettingsLen); -} - -/* -void SettingsLoadMain(void *pSettings, unsigned nSettingsLen) -{ - SettingsLoad("main", "Settings", pSettings, nSettingsLen); -} - -void SettingsLoadMainH(void *pSettingsH, unsigned nSettingsLenH) -{ - SettingsLoad("main", "SettingsH", pSettingsH, nSettingsLenH); -} -*/ - void SettingsLoadUpg(void *pSettings, unsigned nSettingsLen) { - SettingsLoad("upg", "Settings", pSettings, nSettingsLen); + NvmLoad("upg", "Settings", pSettings, nSettingsLen); } void SettingsLoadUpgH(void *pSettings, unsigned nSettingsLen) { - SettingsLoad("upg", "SettingsH", pSettings, nSettingsLen); + NvmLoad("upg", "SettingsH", pSettings, nSettingsLen); +} + +void QPCRead(void *pSettings, unsigned nSettingsLen) +{ + NvmLoad("qpc", "pcreg", pSettings, nSettingsLen); +} + +void QPCWrite(const void *pSettings, unsigned nSettingsLen) +{ + NvmSave("qpc", "pcreg", pSettings, nSettingsLen); } // @@ -174,4 +171,17 @@ void CmndBlockedLoop(void) */ } +// +// ESP32 specific +// + +#include "soc/soc.h" +#include "soc/rtc_cntl_reg.h" + +void DisableBrownout(void) +{ + // https://github.com/espressif/arduino-esp32/issues/863#issuecomment-347179737 + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // Disable brownout detector +} + #endif // ESP32 diff --git a/tasmota/tasmota_compat.h b/tasmota/tasmota_compat.h index 7ca5615b1..5119c9021 100644 --- a/tasmota/tasmota_compat.h +++ b/tasmota/tasmota_compat.h @@ -18,11 +18,6 @@ #define ESP_getSketchSize() ESP.getSketchSize() #define ESP_getChipId() ESP.getChipId() // -// we need different ESP_flashRead for ESP32 -// -#define ESP_flashReadHeader(offset, data, size) ESP.flashRead(offset, data, size) -#define ESP_flashRead(offset, data, size) ESP.flashRead(offset, data, size) -// // UDP #define PortUdp_write(p,n) PortUdp.write(p, n) // diff --git a/tasmota/xdrv_99_debug.ino b/tasmota/xdrv_99_debug.ino index feb04cabd..eeb4e7ca1 100644 --- a/tasmota/xdrv_99_debug.ino +++ b/tasmota/xdrv_99_debug.ino @@ -312,7 +312,7 @@ void DebugCfgDump(char* parms) char *p; uint8_t *buffer = (uint8_t *) &Settings; - maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); + maxrow = ((sizeof(Settings)+CFG_COLS)/CFG_COLS); uint16_t srow = strtol(parms, &p, 16) / CFG_COLS; uint16_t mrow = strtol(p, &p, 10); @@ -356,7 +356,7 @@ void DebugCfgPeek(char* parms) char *p; uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + if (address > sizeof(Settings)) address = sizeof(Settings) -4; address = (address >> 2) << 2; uint8_t *buffer = (uint8_t *) &Settings; @@ -381,7 +381,7 @@ void DebugCfgPoke(char* parms) char *p; uint16_t address = strtol(parms, &p, 16); - if (address > sizeof(SYSCFG)) address = sizeof(SYSCFG) -4; + if (address > sizeof(Settings)) address = sizeof(Settings) -4; address = (address >> 2) << 2; uint32_t data = strtol(p, &p, 16);