Skip to content

Commit dd78bc0

Browse files
committed
Merge branch 'pr-eraseconfig-reset' of github.com:mhightower83/Arduino into pr-eraseconfig-reset
2 parents 8375000 + b1e772c commit dd78bc0

File tree

21 files changed

+189
-77
lines changed

21 files changed

+189
-77
lines changed

cores/esp8266/WString.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,15 @@ bool String::reserve(unsigned int size) {
197197
return false;
198198
}
199199

200+
#ifdef DEBUG_ESP_PORT
201+
static void identifyString (const String& badOne)
202+
{
203+
DEBUG_ESP_PORT.printf("[String] '%." STR(OOM_STRING_BORDER_DISPLAY) "s ... %." STR(OOM_STRING_BORDER_DISPLAY) "s': ",
204+
badOne.c_str(),
205+
badOne.length() > OOM_STRING_BORDER_DISPLAY? badOne.c_str() + std::max((int)badOne.length() - OOM_STRING_BORDER_DISPLAY, OOM_STRING_BORDER_DISPLAY): "");
206+
}
207+
#endif
208+
200209
bool String::changeBuffer(unsigned int maxStrLen) {
201210
// Can we use SSO here to avoid allocation?
202211
if (maxStrLen < sizeof(sso.buff) - 1) {
@@ -218,16 +227,19 @@ bool String::changeBuffer(unsigned int maxStrLen) {
218227
}
219228
// Fallthrough to normal allocator
220229
size_t newSize = (maxStrLen + 16) & (~0xf);
221-
#ifdef DEBUG_ESP_OOM
230+
#ifdef DEBUG_ESP_PORT
222231
if (!isSSO() && capacity() >= OOM_STRING_THRESHOLD_REALLOC_WARN && maxStrLen > capacity()) {
223232
// warn when badly re-allocating
224-
DEBUGV("[String] Reallocating large String(%d -> %d bytes) '%." STR(OOM_STRING_BORDER_DISPLAY) "s ... %." STR(OOM_STRING_BORDER_DISPLAY) "s'\n",
225-
len(), maxStrLen, c_str(),
226-
len() > OOM_STRING_BORDER_DISPLAY? c_str() + std::max((int)len() - OOM_STRING_BORDER_DISPLAY, OOM_STRING_BORDER_DISPLAY): "");
233+
identifyString(*this);
234+
DEBUG_ESP_PORT.printf("Reallocating large String(%d -> %d bytes)\n", len(), maxStrLen);
227235
}
228236
#endif
229237
// Make sure we can fit newsize in the buffer
230238
if (newSize > CAPACITY_MAX) {
239+
#ifdef DEBUG_ESP_PORT
240+
identifyString(*this);
241+
DEBUG_ESP_PORT.printf("Maximum capacity reached (" STR(CAPACITY_MAX) ")\n");
242+
#endif
231243
return false;
232244
}
233245
uint16_t oldLen = len();
@@ -247,6 +259,10 @@ bool String::changeBuffer(unsigned int maxStrLen) {
247259
setBuffer(newbuffer);
248260
return true;
249261
}
262+
#ifdef DEBUG_ESP_PORT
263+
identifyString(*this);
264+
DEBUG_ESP_PORT.printf("OOM: %d -> %zu bytes\n", isSSO() ? 0: capacity(), newSize);
265+
#endif
250266
return false;
251267
}
252268

@@ -804,7 +820,7 @@ void String::replace(const String &find, const String &replace) {
804820
if (size == len())
805821
return;
806822
if (size > capacity() && !changeBuffer(size))
807-
return; // XXX: tell user!
823+
return;
808824
int index = len() - 1;
809825
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
810826
readFrom = wbuffer() + index + find.len();

cores/esp8266/core_esp8266_postmortem.cpp

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,26 @@ static void cut_here() {
110110
ets_putc('\n');
111111
}
112112

113-
void __wrap_system_restart_local() {
114-
register uint32_t sp asm("a1");
115-
uint32_t sp_dump = sp;
116-
113+
/*
114+
Add some assembly to grab the stack pointer and pass it as an argument before
115+
it grows for the target function. Should stabilize the stack offsets, used to
116+
find the relevant stack content for dumping.
117+
*/
118+
extern "C" void __wrap_system_restart_local(void);
119+
asm(
120+
".section .text.__wrap_system_restart_local,\"ax\",@progbits\n\t"
121+
".literal_position\n\t"
122+
".align 4\n\t"
123+
".global __wrap_system_restart_local\n\t"
124+
".type __wrap_system_restart_local, @function\n\t"
125+
"\n"
126+
"__wrap_system_restart_local:\n\t"
127+
"mov a2, a1\n\t"
128+
"j postmortem_report\n\t"
129+
".size __wrap_system_restart_local, .-__wrap_system_restart_local\n\t"
130+
);
131+
132+
static void postmortem_report(uint32_t sp_dump) {
117133
struct rst_info rst_info;
118134
memset(&rst_info, 0, sizeof(rst_info));
119135
if (s_user_reset_reason == REASON_DEFAULT_RST)
@@ -152,9 +168,17 @@ void __wrap_system_restart_local() {
152168
else if (rst_info.reason == REASON_EXCEPTION_RST) {
153169
// The GCC divide routine in ROM jumps to the address below and executes ILL (00 00 00) on div-by-zero
154170
// In that case, print the exception as (6) which is IntegerDivZero
155-
bool div_zero = (rst_info.exccause == 0) && (rst_info.epc1 == 0x4000dce5);
171+
uint32_t epc1 = rst_info.epc1;
172+
uint32_t exccause = rst_info.exccause;
173+
bool div_zero = (exccause == 0) && (epc1 == 0x4000dce5u);
174+
if (div_zero) {
175+
exccause = 6;
176+
// In place of the detached 'ILL' instruction., redirect attention
177+
// back to the code that called the ROM divide function.
178+
__asm__ __volatile__("rsr.excsave1 %0\n\t" : "=r"(epc1) :: "memory");
179+
}
156180
ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
157-
div_zero ? 6 : rst_info.exccause, rst_info.epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
181+
exccause, epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
158182
}
159183
else if (rst_info.reason == REASON_SOFT_WDT_RST) {
160184
ets_printf_P(PSTR("\nSoft WDT reset\n"));
@@ -174,16 +198,31 @@ void __wrap_system_restart_local() {
174198

175199
// amount of stack taken by interrupt or exception handler
176200
// and everything up to __wrap_system_restart_local
177-
// (determined empirically, might break)
201+
// ~(determined empirically, might break)~
178202
uint32_t offset = 0;
179203
if (rst_info.reason == REASON_SOFT_WDT_RST) {
180-
offset = 0x1a0;
204+
// Stack Tally
205+
// 256 User Exception vector handler reserves stack space
206+
// directed to _xtos_l1int_handler function in Boot ROM
207+
// 48 wDev_ProcessFiq - its address appears in a vector table at 0x3FFFC27C
208+
// 16 ?unnamed? - index into a table, pull out pointer, and call if non-zero
209+
// appears near near wDev_ProcessFiq
210+
// 32 pp_soft_wdt_feed_local - gather the specifics and call __wrap_system_restart_local
211+
offset = 32 + 16 + 48 + 256;
181212
}
182213
else if (rst_info.reason == REASON_EXCEPTION_RST) {
183-
offset = 0x190;
214+
// Stack Tally
215+
// 256 Exception vector reserves stack space
216+
// filled in by "C" wrapper handler
217+
// 16 Handler level 1 - enable icache
218+
// 64 Handler level 2 - exception report
219+
offset = 64 + 16 + 256;
184220
}
185221
else if (rst_info.reason == REASON_WDT_RST) {
186-
offset = 0x10;
222+
offset = 16;
223+
}
224+
else if (rst_info.reason == REASON_USER_SWEXCEPTION_RST) {
225+
offset = 16;
187226
}
188227

189228
ets_printf_P(PSTR("\n>>>stack>>>\n"));
@@ -280,8 +319,9 @@ static void raise_exception() {
280319

281320
s_user_reset_reason = REASON_USER_SWEXCEPTION_RST;
282321
ets_printf_P(PSTR("\nUser exception (panic/abort/assert)"));
283-
__wrap_system_restart_local();
284-
322+
uint32_t sp;
323+
__asm__ __volatile__ ("mov %0, a1\n\t" : "=r"(sp) :: "memory");
324+
postmortem_report(sp);
285325
while (1); // never reached, needed to satisfy "noreturn" attribute
286326
}
287327

@@ -321,7 +361,9 @@ void __stack_chk_fail(void) {
321361
if (gdb_present())
322362
__asm__ __volatile__ ("syscall"); // triggers GDB when enabled
323363

324-
__wrap_system_restart_local();
364+
uint32_t sp;
365+
__asm__ __volatile__ ("mov %0, a1\n\t" : "=r"(sp) :: "memory");
366+
postmortem_report(sp);
325367

326368
__builtin_unreachable(); // never reached, needed to satisfy "noreturn" attribute
327369
}

libraries/ESP8266WebServer/src/ESP8266WebServer-impl.h

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,35 @@ void ESP8266WebServerTemplate<ServerType>::handleClient() {
296296
bool keepCurrentClient = false;
297297
bool callYield = false;
298298

299-
DBGWS("http-server loop: conn=%d avail=%d status=%s\n",
300-
_currentClient.connected(), _currentClient.available(),
301-
_currentStatus==HC_NONE?"none":
302-
_currentStatus==HC_WAIT_READ?"wait-read":
303-
_currentStatus==HC_WAIT_CLOSE?"wait-close":
304-
"??");
299+
#ifdef DEBUG_ESP_HTTP_SERVER
300+
301+
struct compare_s
302+
{
303+
uint8_t connected;
304+
int available;
305+
HTTPClientStatus status;
306+
bool operator != (const compare_s& o)
307+
{
308+
return o.connected != connected
309+
|| o.available != available
310+
|| o.status != status;
311+
}
312+
};
313+
static compare_s last { false, 0, HC_NONE };
314+
compare_s now { _currentClient.connected(), _currentClient.available(), _currentStatus };
315+
316+
if (last != now)
317+
{
318+
DBGWS("http-server loop: conn=%d avail=%d status=%s\n",
319+
_currentClient.connected(), _currentClient.available(),
320+
_currentStatus==HC_NONE?"none":
321+
_currentStatus==HC_WAIT_READ?"wait-read":
322+
_currentStatus==HC_WAIT_CLOSE?"wait-close":
323+
"??");
324+
last = now;
325+
}
326+
327+
#endif // DEBUG_ESP_HTTP_SERVER
305328

306329
if (_currentClient.connected() || _currentClient.available()) {
307330
if (_currentClient.available() && _keepAlive) {

libraries/SD/src/SD.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
#include "SD.h"
22

3+
static_assert(__builtin_strcmp(SDClassFileMode(FILE_READ), "r") == 0, "");
4+
static_assert(__builtin_strcmp(SDClassFileMode(FILE_WRITE), "a+") == 0, "");
5+
6+
static_assert(__builtin_strcmp(SDClassFileMode(O_RDONLY), "r") == 0, "");
7+
static_assert(__builtin_strcmp(SDClassFileMode(O_WRONLY), "w+") == 0, "");
8+
static_assert(__builtin_strcmp(SDClassFileMode(O_RDWR), "w+") == 0, "");
9+
static_assert(__builtin_strcmp(SDClassFileMode(O_WRONLY | O_APPEND), "a") == 0, "");
10+
static_assert(__builtin_strcmp(SDClassFileMode(O_RDWR | O_APPEND), "a+") == 0, "");
11+
312
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SD)
413
SDClass SD;
514
#endif

libraries/SD/src/SD.h

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,44 @@
2424
#include <FS.h>
2525
#include <SDFS.h>
2626

27+
// Avoid type ambiguity, force u8 instead of untyped literal
28+
// ref. #6106 as to why we add APPEND to WRITE
29+
30+
inline constexpr uint8_t SDClassFileRead { FILE_READ };
2731
#undef FILE_READ
28-
#define FILE_READ ((uint8_t)O_READ)
29-
#undef FILE_WRITE
30-
#define FILE_WRITE ((uint8_t)(O_READ | O_WRITE | O_CREAT | O_APPEND))
32+
#define FILE_READ SDClassFileRead
3133

34+
inline constexpr uint8_t SDClassFileWrite { FILE_WRITE | O_APPEND };
35+
#undef FILE_WRITE
36+
#define FILE_WRITE SDClassFileWrite
37+
38+
static inline constexpr const char* SDClassFileMode(uint8_t mode) {
39+
bool read = false;
40+
bool write = false;
41+
42+
switch (mode & O_ACCMODE) {
43+
case O_RDONLY:
44+
read = true;
45+
break;
46+
case O_WRONLY:
47+
write = true;
48+
break;
49+
case O_RDWR:
50+
read = true;
51+
write = true;
52+
break;
53+
}
54+
55+
const bool append = (mode & O_APPEND) > 0;
56+
57+
if ( read && !write ) { return "r"; }
58+
else if ( !read && write && !append ) { return "w+"; }
59+
else if ( !read && write && append ) { return "a"; }
60+
else if ( read && write && !append ) { return "w+"; } // may be a bug in FS::mode interpretation, "r+" seems proper
61+
else if ( read && write && append ) { return "a+"; }
62+
63+
return "r";
64+
}
3265

3366
class SDClass {
3467
public:
@@ -45,7 +78,7 @@ class SDClass {
4578
}
4679

4780
fs::File open(const char *filename, uint8_t mode = FILE_READ) {
48-
return SDFS.open(filename, getMode(mode));
81+
return SDFS.open(filename, SDClassFileMode(mode));
4982
}
5083

5184
fs::File open(const char *filename, const char *mode) {
@@ -158,18 +191,6 @@ class SDClass {
158191
}
159192

160193
private:
161-
const char *getMode(uint8_t mode) {
162-
bool read = (mode & O_READ) ? true : false;
163-
bool write = (mode & O_WRITE) ? true : false;
164-
bool append = (mode & O_APPEND) ? true : false;
165-
if ( read & !write ) { return "r"; }
166-
else if ( !read & write & !append ) { return "w+"; }
167-
else if ( !read & write & append ) { return "a"; }
168-
else if ( read & write & !append ) { return "w+"; } // may be a bug in FS::mode interpretation, "r+" seems proper
169-
else if ( read & write & append ) { return "a+"; }
170-
else { return "r"; }
171-
}
172-
173194
static time_t wrapperTimeCB(void) {
174195
extern void (*__SD__userDateTimeCB)(uint16_t*, uint16_t*);
175196
if (__SD__userDateTimeCB) {

libraries/Ticker/src/Ticker.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,28 @@ void Ticker::_static_callback()
115115
}
116116
}
117117

118+
// it is technically allowed to call either schedule or detach
119+
// *during* callback execution. allow both to happen
120+
decltype(_callback) tmp;
121+
std::swap(tmp, _callback);
122+
118123
std::visit([](auto&& callback) {
119124
using T = std::decay_t<decltype(callback)>;
120125
if constexpr (std::is_same_v<T, callback_ptr_t>) {
121126
callback.func(callback.arg);
122127
} else if constexpr (std::is_same_v<T, callback_function_t>) {
123128
callback();
124129
}
125-
}, _callback);
130+
}, tmp);
131+
132+
// ...and move ourselves back only when object is in a valid state
133+
// * ticker was not detached, zeroing timer pointer
134+
// * nothing else replaced callback variant
135+
if ((_timer == nullptr) || !std::holds_alternative<std::monostate>(_callback)) {
136+
return;
137+
}
138+
139+
std::swap(tmp, _callback);
126140

127141
if (_repeat) {
128142
if (_tick) {

libraries/esp8266/examples/LowPowerDemo/LowPowerDemo.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ void setup() {
128128

129129
// Read previous resets (Deep Sleeps) from RTC memory, if any
130130
uint32_t crcOfData = crc32((uint8_t*)&nv->rtcData.rstCount, sizeof(nv->rtcData.rstCount));
131-
if ((crcOfData = nv->rtcData.crc32) && (resetCause == "Deep-Sleep Wake")) {
131+
if ((crcOfData == nv->rtcData.crc32) && (resetCause == "Deep-Sleep Wake")) {
132132
resetCount = nv->rtcData.rstCount; // read the previous reset count
133133
resetCount++;
134134
}

platform.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,18 @@ compiler.cpreprocessor.flags=-D__ets__ -DICACHE_FLASH -U__STRICT_ANSI__ -D_GNU_S
7676
compiler.libraries.ldflags=
7777

7878
compiler.c.cmd=xtensa-lx106-elf-gcc
79-
compiler.c.flags=-c "{compiler.warning_flags}-gcc" -std=gnu17 {build.stacksmash_flags} -Os -g -free -fipa-pta -Werror=return-type -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.mmuflags} {build.non32xferflags}
79+
compiler.c.flags=-c "{compiler.warning_flags}-cflags" -std=gnu17 {build.stacksmash_flags} -Os -g -free -fipa-pta -Werror=return-type -Wpointer-arith -Wno-implicit-function-declaration -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -falign-functions=4 -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.mmuflags} {build.non32xferflags}
8080

8181
compiler.S.cmd=xtensa-lx106-elf-gcc
8282
compiler.S.flags=-c -g -x assembler-with-cpp -MMD -mlongcalls "-I{runtime.tools.xtensa-lx106-elf-gcc.path}/include/"
8383

84-
compiler.c.elf.flags=-g "{compiler.warning_flags}-gcc" -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{build.path}" "-L{compiler.libc.path}/lib" "-Tlocal.eagle.flash.ld" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
84+
compiler.c.elf.flags=-g "{compiler.warning_flags}-cflags" -Os -nostdlib -Wl,--no-check-sections -u app_entry {build.float} -Wl,-static "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/lib/{build.sdk}" "-L{build.path}" "-L{compiler.libc.path}/lib" "-Tlocal.eagle.flash.ld" -Wl,--gc-sections -Wl,-wrap,system_restart_local -Wl,-wrap,spi_flash_read
8585

8686
compiler.c.elf.cmd=xtensa-lx106-elf-gcc
8787
compiler.c.elf.libs=-lhal -lphy -lpp -lnet80211 {build.lwip_lib} -lwpa -lcrypto -lmain -lwps -lbearssl -lespnow -lsmartconfig -lairkiss -lwpa2 {build.stdcpp_lib} -lm -lc -lgcc
8888

8989
compiler.cpp.cmd=xtensa-lx106-elf-g++
90-
compiler.cpp.flags=-c "{compiler.warning_flags}-g++" {build.stacksmash_flags} -Os -g -free -fipa-pta -Werror=return-type -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.mmuflags} {build.non32xferflags}
90+
compiler.cpp.flags=-c "{compiler.warning_flags}-cppflags" {build.stacksmash_flags} -Os -g -free -fipa-pta -Werror=return-type -mlongcalls -mtext-section-literals -fno-rtti -falign-functions=4 {build.stdcpp_level} -MMD -ffunction-sections -fdata-sections {build.exception_flags} {build.sslflags} {build.mmuflags} {build.non32xferflags}
9191

9292
compiler.as.cmd=xtensa-lx106-elf-as
9393

0 commit comments

Comments
 (0)