Add ESP32 QuickPowerCycle control

This commit is contained in:
Theo Arends 2020-04-19 15:36:04 +02:00
parent eab612871c
commit c37dde93c2
7 changed files with 100 additions and 91 deletions

View File

@ -99,12 +99,3 @@ uint32_t ESP_getSketchSize(void)
} }
return sketchsize; 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
}

View File

@ -31,8 +31,6 @@
// //
// ESP32 // 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); String ESP_getResetReason(void);
uint32_t ESP_ResetInfoReason(void); uint32_t ESP_ResetInfoReason(void);
uint32_t ESP_getBootVersion(void); uint32_t ESP_getBootVersion(void);
@ -41,7 +39,6 @@ uint32_t ESP_getFlashChipId();
uint32_t ESP_getChipId(); uint32_t ESP_getChipId();
String String_ESP_getChipId(); String String_ESP_getChipId();
uint32_t ESP_getSketchSize(); uint32_t ESP_getSketchSize();
void DisableBrownout(void);
// Analog // Analog
inline void analogWrite(uint8_t pin, int val) inline void analogWrite(uint8_t pin, int val)

View File

@ -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 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; const uint8_t MAX_TUYA_FUNCTIONS = 16;
struct SYSCFG { struct {
uint16_t cfg_holder; // 000 v6 header uint16_t cfg_holder; // 000 v6 header
uint16_t cfg_size; // 002 uint16_t cfg_size; // 002
unsigned long save_flag; // 004 unsigned long save_flag; // 004

View File

@ -305,7 +305,7 @@ uint16_t GetCfgCrc16(uint8_t *bytes, uint32_t size)
uint16_t GetSettingsCrc(void) uint16_t GetSettingsCrc(void)
{ {
// Fix miscalculation if previous Settings was 3584 and current Settings is 4096 between 0x06060007 and 0x0606000A // 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); return GetCfgCrc16((uint8_t*)&Settings, size);
} }
@ -325,7 +325,7 @@ uint32_t GetCfgCrc32(uint8_t *bytes, uint32_t size)
uint32_t GetSettingsCrc32(void) 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) void SettingsSaveAll(void)
@ -351,7 +351,11 @@ void UpdateQuickPowerCycle(bool update)
uint32_t pc_register; uint32_t pc_register;
uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES; uint32_t pc_location = SETTINGS_LOCATION - CFG_ROTATES;
#ifdef ESP8266
ESP.flashRead(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); 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)) { if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) {
uint32_t counter = ((pc_register & 0xF) << 1) & 0xF; uint32_t counter = ((pc_register & 0xF) << 1) & 0xF;
if (0 == counter) { // 4 power cycles in a row if (0 == counter) { // 4 power cycles in a row
@ -359,16 +363,24 @@ void UpdateQuickPowerCycle(bool update)
EspRestart(); // And restart EspRestart(); // And restart
} else { } else {
pc_register = 0xFFA55AB0 | counter; pc_register = 0xFFA55AB0 | counter;
#ifdef ESP8266
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); 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); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Flag %02X"), counter);
} }
} }
else if (pc_register != 0xFFA55ABF) { else if (pc_register != 0xFFA55ABF) {
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 // Assume flash is default all ones and setting a bit to zero does not need an erase
if (ESP.flashEraseSector(pc_location)) { if (ESP.flashEraseSector(pc_location)) {
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register)); 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")); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset"));
} }
} }
@ -501,13 +513,13 @@ void SettingsSave(uint8_t rotate)
} else { } else {
Settings.cfg_timestamp++; 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_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade
Settings.cfg_crc32 = GetSettingsCrc32(); Settings.cfg_crc32 = GetSettingsCrc32();
#ifdef ESP8266 #ifdef ESP8266
if (ESP.flashEraseSector(settings_location)) { 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) { if (!stop_flash_rotate && rotate) {
@ -516,12 +528,12 @@ void SettingsSave(uint8_t rotate)
delay(1); 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 #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 #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; settings_crc32 = Settings.cfg_crc32;
} }
#endif // FIRMWARE_MINIMAL #endif // FIRMWARE_MINIMAL
@ -530,8 +542,9 @@ void SettingsSave(uint8_t rotate)
void SettingsLoad(void) void SettingsLoad(void)
{ {
#ifdef ESP8266
// Load configuration from eeprom or one of 7 slots below if first valid load does not stop_flash_rotate // 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_holder; // 000
uint16_t cfg_size; // 002 uint16_t cfg_size; // 002
unsigned long save_flag; // 004 unsigned long save_flag; // 004
@ -543,7 +556,7 @@ void SettingsLoad(void)
uint16_t cfg_holder = 0; uint16_t cfg_holder = 0;
for (uint32_t i = 0; i < CFG_ROTATES; i++) { for (uint32_t i = 0; i < CFG_ROTATES; i++) {
flash_location--; 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; bool valid = false;
if (Settings.version > 0x06000000) { if (Settings.version > 0x06000000) {
bool almost_valid = (Settings.cfg_crc32 == GetSettingsCrc32()); 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 if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder
valid = (cfg_holder == Settings.cfg_holder); valid = (cfg_holder == Settings.cfg_holder);
} else { } 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); valid = (Settings.cfg_holder == _SettingsH.cfg_holder);
} }
if (valid) { if (valid) {
@ -566,13 +579,16 @@ void SettingsLoad(void)
} }
} }
} }
delay(1); delay(1);
} }
if (settings_location > 0) { 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); 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 #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 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) void SettingsDefaultSet1(void)
{ {
memset(&Settings, 0x00, sizeof(SYSCFG)); memset(&Settings, 0x00, sizeof(Settings));
Settings.cfg_holder = (uint16_t)CFG_HOLDER; Settings.cfg_holder = (uint16_t)CFG_HOLDER;
Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_size = sizeof(Settings);
// Settings.save_flag = 0; // Settings.save_flag = 0;
Settings.version = VERSION; Settings.version = VERSION;
// Settings.bootcount = 0; // Settings.bootcount = 0;
@ -695,7 +711,7 @@ void SettingsDefaultSet1(void)
void SettingsDefaultSet2(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.stop_flash_rotate = APP_FLASH_CYCLE;
Settings.flag.global_state = APP_ENABLE_LEDLINK; Settings.flag.global_state = APP_ENABLE_LEDLINK;
@ -1064,7 +1080,7 @@ void SettingsDelta(void)
#ifdef ESP8266 #ifdef ESP8266
if (Settings.version < 0x06000000) { if (Settings.version < 0x06000000) {
Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_size = sizeof(Settings);
Settings.cfg_crc = GetSettingsCrc(); Settings.cfg_crc = GetSettingsCrc();
} }
if (Settings.version < 0x06000002) { if (Settings.version < 0x06000002) {
@ -1148,7 +1164,7 @@ void SettingsDelta(void)
Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP; Settings.param[P_OVER_TEMP] = ENERGY_OVERTEMP;
} }
if (Settings.version < 0x06060007) { if (Settings.version < 0x06060007) {
memset((char*)&Settings +0xE00, 0x00, sizeof(SYSCFG) -0xE00); memset((char*)&Settings +0xE00, 0x00, sizeof(Settings) -0xE00);
} }
if (Settings.version < 0x06060008) { if (Settings.version < 0x06060008) {
// Move current tuya dimmer range to the new param. // Move current tuya dimmer range to the new param.

View File

@ -22,6 +22,39 @@
#include <nvs.h> #include <nvs.h>
#include <rom/rtc.h> #include <rom/rtc.h>
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) void SettingsErase(uint8_t type)
{ {
if (1 == type) // SDK parameter area if (1 == type) // SDK parameter area
@ -34,75 +67,39 @@ void SettingsErase(uint8_t type)
{ {
} }
noInterrupts(); NvmErase("main");
nvs_handle handle;
nvs_open("main", NVS_READWRITE, &handle);
nvs_erase_all(handle);
nvs_commit(handle);
nvs_close(handle);
interrupts();
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " t=%d"), type); 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(); NvmLoad("main", "Settings", data, size);
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();
} }
void SettingsSave(const char *sNvsName, const char *sName, const void *pSettings, unsigned nSettingsLen) void SettingsWrite(const void *pSettings, unsigned nSettingsLen)
{ {
nvs_handle handle; NvmSave("main", "Settings", pSettings, nSettingsLen);
noInterrupts();
nvs_open(sNvsName, NVS_READWRITE, &handle);
nvs_set_blob(handle, sName, pSettings, nSettingsLen);
nvs_commit(handle);
nvs_close(handle);
interrupts();
} }
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) void SettingsLoadUpg(void *pSettings, unsigned nSettingsLen)
{ {
SettingsLoad("upg", "Settings", pSettings, nSettingsLen); NvmLoad("upg", "Settings", pSettings, nSettingsLen);
} }
void SettingsLoadUpgH(void *pSettings, unsigned 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 #endif // ESP32

View File

@ -18,11 +18,6 @@
#define ESP_getSketchSize() ESP.getSketchSize() #define ESP_getSketchSize() ESP.getSketchSize()
#define ESP_getChipId() ESP.getChipId() #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 // UDP
#define PortUdp_write(p,n) PortUdp.write(p, n) #define PortUdp_write(p,n) PortUdp.write(p, n)
// //

View File

@ -312,7 +312,7 @@ void DebugCfgDump(char* parms)
char *p; char *p;
uint8_t *buffer = (uint8_t *) &Settings; 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 srow = strtol(parms, &p, 16) / CFG_COLS;
uint16_t mrow = strtol(p, &p, 10); uint16_t mrow = strtol(p, &p, 10);
@ -356,7 +356,7 @@ void DebugCfgPeek(char* parms)
char *p; char *p;
uint16_t address = strtol(parms, &p, 16); 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; address = (address >> 2) << 2;
uint8_t *buffer = (uint8_t *) &Settings; uint8_t *buffer = (uint8_t *) &Settings;
@ -381,7 +381,7 @@ void DebugCfgPoke(char* parms)
char *p; char *p;
uint16_t address = strtol(parms, &p, 16); 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; address = (address >> 2) << 2;
uint32_t data = strtol(p, &p, 16); uint32_t data = strtol(p, &p, 16);