-
Notifications
You must be signed in to change notification settings - Fork 13.3k
A new approach for erasing WiFi Settings #8828
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
f5d7d4a
1a03a41
d061a3c
8375000
b1e772c
dd78bc0
9ccd11c
feb8a99
eb7aa17
5f7adcf
c7a3ed8
cd5a852
892e6a2
c952ffc
f8a8251
40fba0a
f3a492e
0e1059d
721e6d3
696b96b
ef0c1e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
Make the reset look like an EXT_RST reset by: | ||
* Set INTLEVEL to 15 blocking NMI Software WDT interference | ||
* set "restart reason" to REASON_EXT_SYS_RST | ||
* Config Hardware WDT for 1.6ms | ||
* Disable Hardware WDT Level-1 interrupt option | ||
* wait, ... | ||
|
||
Inspired by RTOS SDK hardware_restart in panic.c | ||
*/ | ||
|
||
#include "Arduino.h" | ||
#include <user_interface.h> | ||
#include <ets_sys.h> | ||
#include "hardware_reset.h" | ||
|
||
|
||
// Extracted from RTOS_SDK eagle_soc.h | ||
/* | ||
* ESPRSSIF MIT License | ||
* | ||
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD> | ||
* | ||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case, | ||
* it is free of charge, to any person obtaining a copy of this software and associated | ||
* documentation files (the "Software"), to deal in the Software without restriction, including | ||
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished | ||
* to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in all copies or | ||
* substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS | ||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | ||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
* | ||
*/ | ||
#define REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v) | ||
#define REG_READ(_r) (*(volatile uint32_t *)(_r)) | ||
|
||
//Watchdog reg {{ | ||
#define PERIPHS_WDT_BASEADDR 0x60000900 | ||
|
||
#define WDT_CTL_ADDRESS 0 | ||
#define WDT_OP_ADDRESS 0x4 | ||
#define WDT_OP_ND_ADDRESS 0x8 | ||
#define WDT_RST_ADDRESS 0x14 | ||
|
||
#define WDT_CTL_RSTLEN_MASK 0x38 | ||
#define WDT_CTL_RSPMOD_MASK 0x6 | ||
#define WDT_CTL_EN_MASK 0x1 | ||
|
||
#define WDT_CTL_RSTLEN_LSB 0x3 | ||
#define WDT_CTL_RSPMOD_LSB 0x1 | ||
#define WDT_CTL_EN_LSB 0 | ||
|
||
#define WDT_FEED_VALUE 0x73 | ||
|
||
#define WDT_REG_READ(_reg) REG_READ(PERIPHS_WDT_BASEADDR + _reg) | ||
#define WDT_REG_WRITE(_reg, _val) REG_WRITE(PERIPHS_WDT_BASEADDR + _reg, _val) | ||
#define CLEAR_WDT_REG_MASK(_reg, _mask) WDT_REG_WRITE(_reg, WDT_REG_READ(_reg) & (~_mask)) | ||
#define SET_WDT_REG_MASK(_reg, _mask, _val) SET_PERI_REG_BITS((PERIPHS_WDT_BASEADDR + _reg), _mask, _val, 0) | ||
#undef WDT_FEED | ||
#define WDT_FEED() WDT_REG_WRITE(WDT_RST_ADDRESS, WDT_FEED_VALUE) | ||
//}} | ||
|
||
// Inspired by RTOS SDK task_wdt.c and hardware_restart in panic.c | ||
|
||
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
extern "C" { | ||
[[noreturn]] void hardware_reset(void) { | ||
volatile uint32_t* const rtc_mem = (volatile uint32_t *)0x60001100u; | ||
|
||
// Block NMI WDT from disturbing out restart reason | ||
xt_rsil(15); | ||
|
||
// SDK restart reason location | ||
rtc_mem[0] = REASON_EXT_SYS_RST; | ||
|
||
// Disable WDT | ||
CLEAR_WDT_REG_MASK(WDT_CTL_ADDRESS, WDT_CTL_EN_MASK); | ||
|
||
// Set Reset pulse to maximum | ||
// Select Reset only - no level-1 interrupt | ||
SET_WDT_REG_MASK(WDT_CTL_ADDRESS, | ||
WDT_CTL_RSTLEN_MASK | WDT_CTL_RSPMOD_MASK, | ||
(7 << WDT_CTL_RSTLEN_LSB) | (2 << WDT_CTL_RSPMOD_LSB)); | ||
|
||
// Set WDT Reset timer to 1.6 ms. | ||
WDT_REG_WRITE(WDT_OP_ADDRESS, 1); // 2^n * 0.8ms, mask 0xf, n = 1 -> (2^1 = 2) * 0.8 * 0.001 = 0.0016 | ||
|
||
// Enable WDT | ||
SET_WDT_REG_MASK(WDT_CTL_ADDRESS, WDT_CTL_EN_MASK, 1 << WDT_CTL_EN_LSB); | ||
|
||
while (true); | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
#ifndef HARDWARE_RESET_H | ||
#define HARDWARE_RESET_H | ||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
[[noreturn]] extern void hardware_reset(void); | ||
mcspr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
#endif |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -24,10 +24,11 @@ extern "C" { | |||||||||||||||||||||||||||||||||||||||
#include <ESP8266mDNS.h> | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
#ifdef DEBUG_ESP_OTA | ||||||||||||||||||||||||||||||||||||||||
#ifdef DEBUG_ESP_PORT | ||||||||||||||||||||||||||||||||||||||||
#if defined(DEBUG_ESP_OTA) && defined(DEBUG_ESP_PORT) | ||||||||||||||||||||||||||||||||||||||||
#define OTA_DEBUG DEBUG_ESP_PORT | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
#define OTA_DEBUG_PRINTF(fmt, ...) OTA_DEBUG.printf_P(PSTR(fmt), ##__VA_ARGS__) | ||||||||||||||||||||||||||||||||||||||||
#else | ||||||||||||||||||||||||||||||||||||||||
#define OTA_DEBUG_PRINTF(...) | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
ArduinoOTAClass::ArduinoOTAClass() | ||||||||||||||||||||||||||||||||||||||||
|
@@ -89,8 +90,9 @@ void ArduinoOTAClass::setPasswordHash(const char * password) { | |||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
void ArduinoOTAClass::setRebootOnSuccess(bool reboot){ | ||||||||||||||||||||||||||||||||||||||||
void ArduinoOTAClass::setRebootOnSuccess(bool reboot, bool eraseConfig){ | ||||||||||||||||||||||||||||||||||||||||
_rebootOnSuccess = reboot; | ||||||||||||||||||||||||||||||||||||||||
_eraseConfig = eraseConfig; | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
void ArduinoOTAClass::begin(bool useMDNS) { | ||||||||||||||||||||||||||||||||||||||||
|
@@ -119,7 +121,7 @@ void ArduinoOTAClass::begin(bool useMDNS) { | |||||||||||||||||||||||||||||||||||||||
if(!_udp_ota->listen(IP_ADDR_ANY, _port)) | ||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||
_udp_ota->onRx(std::bind(&ArduinoOTAClass::_onRx, this)); | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) | ||||||||||||||||||||||||||||||||||||||||
if(_useMDNS) { | ||||||||||||||||||||||||||||||||||||||||
MDNS.begin(_hostname.c_str()); | ||||||||||||||||||||||||||||||||||||||||
|
@@ -133,9 +135,7 @@ void ArduinoOTAClass::begin(bool useMDNS) { | |||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
_initialized = true; | ||||||||||||||||||||||||||||||||||||||||
_state = OTA_IDLE; | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.printf("OTA server at: %s.local:%u\n", _hostname.c_str(), _port); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("OTA server at: %s.local:%u\n", _hostname.c_str(), _port); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
int ArduinoOTAClass::parseInt(){ | ||||||||||||||||||||||||||||||||||||||||
|
@@ -243,13 +243,11 @@ void ArduinoOTAClass::_runUpdate() { | |||||||||||||||||||||||||||||||||||||||
IPAddress ota_ip = _ota_ip; | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
if (!Update.begin(_size, _cmd)) { | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.println("Update Begin Error"); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("Update Begin Error\n"); | ||||||||||||||||||||||||||||||||||||||||
if (_error_callback) { | ||||||||||||||||||||||||||||||||||||||||
_error_callback(OTA_BEGIN_ERROR); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
StreamString ss; | ||||||||||||||||||||||||||||||||||||||||
Update.printError(ss); | ||||||||||||||||||||||||||||||||||||||||
_udp_ota->append("ERR: ", 5); | ||||||||||||||||||||||||||||||||||||||||
|
@@ -275,9 +273,7 @@ void ArduinoOTAClass::_runUpdate() { | |||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
WiFiClient client; | ||||||||||||||||||||||||||||||||||||||||
if (!client.connect(_ota_ip, _ota_port)) { | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.printf("Connect Failed\n"); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("Connect Failed\n"); | ||||||||||||||||||||||||||||||||||||||||
_udp_ota->listen(IP_ADDR_ANY, _port); | ||||||||||||||||||||||||||||||||||||||||
if (_error_callback) { | ||||||||||||||||||||||||||||||||||||||||
_error_callback(OTA_CONNECT_ERROR); | ||||||||||||||||||||||||||||||||||||||||
|
@@ -293,9 +289,7 @@ void ArduinoOTAClass::_runUpdate() { | |||||||||||||||||||||||||||||||||||||||
while (!client.available() && waited--) | ||||||||||||||||||||||||||||||||||||||||
delay(1); | ||||||||||||||||||||||||||||||||||||||||
if (!waited){ | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.printf("Receive Failed\n"); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("Receive Failed\n"); | ||||||||||||||||||||||||||||||||||||||||
_udp_ota->listen(IP_ADDR_ANY, _port); | ||||||||||||||||||||||||||||||||||||||||
if (_error_callback) { | ||||||||||||||||||||||||||||||||||||||||
_error_callback(OTA_RECEIVE_ERROR); | ||||||||||||||||||||||||||||||||||||||||
|
@@ -320,18 +314,27 @@ void ArduinoOTAClass::_runUpdate() { | |||||||||||||||||||||||||||||||||||||||
client.flush(); | ||||||||||||||||||||||||||||||||||||||||
delay(1000); | ||||||||||||||||||||||||||||||||||||||||
client.stop(); | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.printf("Update Success\n"); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("Update Success\n"); | ||||||||||||||||||||||||||||||||||||||||
if (_end_callback) { | ||||||||||||||||||||||||||||||||||||||||
_end_callback(); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
if(_rebootOnSuccess){ | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.printf("Rebooting...\n"); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("Rebooting...\n"); | ||||||||||||||||||||||||||||||||||||||||
//let serial/network finish tasks that might be given in _end_callback | ||||||||||||||||||||||||||||||||||||||||
delay(100); | ||||||||||||||||||||||||||||||||||||||||
if (_eraseConfig) { | ||||||||||||||||||||||||||||||||||||||||
eraseConfigAndReset(); // returns on failure | ||||||||||||||||||||||||||||||||||||||||
//C What is the best action to take on failure? | ||||||||||||||||||||||||||||||||||||||||
//C 1) On failure, we could invalidate eboot_command buffer - | ||||||||||||||||||||||||||||||||||||||||
//C aborting the flash update. | ||||||||||||||||||||||||||||||||||||||||
//C 2) Just ignore it and restart. | ||||||||||||||||||||||||||||||||||||||||
//C 3) Retry forever | ||||||||||||||||||||||||||||||||||||||||
if (_error_callback) { | ||||||||||||||||||||||||||||||||||||||||
_error_callback(OTA_ERASE_SETTINGS_ERROR); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At failure, there are no good choices. Update: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why a separate condition & callback though? We can retrieve error id There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand your reference. I am using the existing error callback with a new error number to identify the situation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (review UI sent a draft :/) Why even mention it? Since we want this to be done, probably unroll is a better option than leave things in an indeterminate state? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Arduino/libraries/ArduinoOTA/ArduinoOTA.cpp Lines 328 to 346 in 0e1059d
When enabling erase WiFi settings, the user does so by selecting the fail option ignore or abort. Does that satisfy your concerns? |
||||||||||||||||||||||||||||||||||||||||
_state = OTA_ERASEWIFI; | ||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
ESP.restart(); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||
|
@@ -357,17 +360,33 @@ void ArduinoOTAClass::end() { | |||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
_state = OTA_IDLE; | ||||||||||||||||||||||||||||||||||||||||
#ifdef OTA_DEBUG | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG.printf("OTA server stopped.\n"); | ||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("OTA server stopped.\n"); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
void ArduinoOTAClass::eraseConfigAndReset() { | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF("Erase Config and Hard Reset ...\n"); | ||||||||||||||||||||||||||||||||||||||||
if (WiFi.mode(WIFI_OFF)) { | ||||||||||||||||||||||||||||||||||||||||
ESP.eraseConfig(true); // No return testing - Only returns on failure | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF(" ESP.eraseConfig(true) failed!\n"); | ||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||
OTA_DEBUG_PRINTF(" WiFi.mode(WIFI_OFF) Timeout!\n"); | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
delay(2000); // force a gap between retries | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
//this needs to be called in the loop() | ||||||||||||||||||||||||||||||||||||||||
void ArduinoOTAClass::handle() { | ||||||||||||||||||||||||||||||||||||||||
if (_state == OTA_RUNUPDATE) { | ||||||||||||||||||||||||||||||||||||||||
_runUpdate(); | ||||||||||||||||||||||||||||||||||||||||
_state = OTA_IDLE; | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
if (_state == OTA_ERASEWIFI) { | ||||||||||||||||||||||||||||||||||||||||
eraseConfigAndReset(); | ||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_MDNS) | ||||||||||||||||||||||||||||||||||||||||
if(_useMDNS) | ||||||||||||||||||||||||||||||||||||||||
MDNS.update(); //handle MDNS update as well, given that ArduinoOTA relies on it anyways | ||||||||||||||||||||||||||||||||||||||||
|
Uh oh!
There was an error while loading. Please reload this page.