If the power supply fails before the flag is cleared, will it go into reset mode?
rtek1000 opened this issue · 1 comments
rtek1000 commented
Hi,
I have noticed that if the power supply fails before the flag is cleared, it will go into reset mode.
To avoid this, we can use a button on a GPIO like the GPIO0
If anyone is interested, see this code:
APConfig.ino:
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#define USESERIAL
#define USELED
#define USE_BTN_FACTORY
#include "Config.h"
#include "FirmwareReset.h"
#include "AdminPage.h"
ESP8266WebServer webServer(80);
void setup() {
// put your setup code here, to run once:
Serial.begin(115200); Serial.printf("\nAP Config Demo\n");
InitConfig();
//Start the wifi with the required username and password
WiFi.mode(WIFI_AP);
LoadConfig();
PrintConfig();
//Check to see if the flag is still set from the previous boot
if (checkResetFlag()) {
//Do the firmware reset here
Serial.printf("Reset Firmware\n");
//Set the ssid to default value and turn off the password
WiFi.softAP("APConfig", "", 1, false, 1);
}
else {
WiFi.softAP(config.ssid, config.pass, 1, false, 1);
}
// Serve a very basic page on the root url
webServer.on("/", []() {
webServer.send(200, "text/plain", "Hello World");
});
// Set up the admin page
webServer.on("/admin", std::bind(serveAdmin, &webServer));
webServer.begin();
}
void loop() {
// put your main code here, to run repeatedly:
webServer.handleClient();
}
FirmwareReset.h:
// The Firmware reset library creates a small window of time, in which the reset button can be pressed to initiate a firmware reset.
// The state of the window is displayed to the user by flashing the built in LED or by Serial updates.
#ifndef FirmwareReset_H
#define FirmwareReset_H
#include <Ticker.h>
#define FLAGSET 0x55555555
#define FLAGCLEAR 0xAAAAAAAA
#define FLAGADDRESS 00
#define SETTIMEOUT 3
#define CLEARTIMEOUT 1
#define btnFactory 0 // Note: GPIO0 must be in the HIGH state to run the program,
// otherwise it will enter the Flash mode for reprogramming,
// so do not hold down at startup!
Ticker ticker;
bool booted = false;
// Allows shared usage of the built in led for as long as the firmware reset needs it
void BuiltInLED(bool on) {
#ifdef USELED
if (booted)
digitalWrite(LED_BUILTIN, on);
#endif
}
// End the firmware reset process, at this point the software can run normally without checking for user resets
void finishBoot() {
booted = true;
#ifdef USESERIAL
Serial.printf("Booted\n");
#endif
ticker.detach();
}
// Clear the reset flag in memory, this ends the window for a possible reset
void clearFlag() {
uint32_t value = FLAGCLEAR;
ESP.rtcUserMemoryWrite(FLAGADDRESS, &value, sizeof(value));
#ifdef USELED
digitalWrite(LED_BUILTIN, HIGH);
#endif
#ifdef USESERIAL
Serial.printf("Clear Flag\n");
#endif
ticker.attach(CLEARTIMEOUT, finishBoot);
}
void setFlag() {
uint32_t value = FLAGSET;
// Set the reset flag in memory, this will indicate if the user has pressed reset while the LED was on
ESP.rtcUserMemoryWrite(FLAGADDRESS, &value, sizeof(value));
#ifdef USELED
digitalWrite(LED_BUILTIN, LOW);
#endif
#ifdef USESERIAL
Serial.printf("Set Flag\n");
#endif
ticker.attach(CLEARTIMEOUT, clearFlag);
}
// Checks to see if the user has rebooted the processor within the reset time frame
bool checkResetFlag() {
uint32_t value = FLAGCLEAR;
bool result;
#ifdef USELED
// Set up the LED as a status indicator
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
#endif
#ifdef USE_BTN_FACTORY
int i = SETTIMEOUT * 10;
#ifdef USESERIAL
Serial.printf("Press the Factory button within %d seconds", SETTIMEOUT);
#endif
while (i--) {
#ifdef USESERIAL
Serial.printf(".");
#endif
delay(100);
if (!digitalRead(btnFactory)) {
#ifdef USESERIAL
Serial.printf("\n");
#endif
return true;
}
} // start window (GPIO0 must be in HIGH state to run program)
#ifdef USESERIAL
Serial.printf("\n");
#endif
return false;
#else // #ifdef USE_BTN_FACTORY
// Check to see the state of the flag in memory
ESP.rtcUserMemoryRead(FLAGADDRESS, &value, sizeof(value));
result = (value == FLAGSET);
// If the user previously performed a reset then begin the reset process
if (result)
clearFlag();
// If the flag was not previously set, then set up a new reset window
else
ticker.attach(SETTIMEOUT, setFlag);
return result;
#endif // #ifdef USE_BTN_FACTORY
}
#endif // #ifndef FirmwareReset_H
proddy commented
nice addition, thanks for sharing.