Skip to content

Commit e1618eb

Browse files
authored
Merge branch 'master' into troubleshooting
2 parents 2894ee2 + f2da54d commit e1618eb

18 files changed

+195
-64
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ ESP8266 Arduino core comes with libraries to communicate over WiFi using TCP and
2828

2929
Starting with 1.6.4, Arduino allows installation of third-party platform packages using Boards Manager. We have packages available for Windows, Mac OS, and Linux (32 and 64 bit).
3030

31-
- Install the current upstream Arduino IDE at the 1.8.9 level or later. The current version is on the [Arduino website](https://www.arduino.cc/en/software).
32-
- Start Arduino and open the Preferences window.
33-
- Enter ```https://arduino.esp8266.com/stable/package_esp8266com_index.json``` into the *File>Preferences>Additional Boards Manager URLs* field of the Arduino IDE. You can add multiple URLs, separating them with commas.
31+
- [Download and install Arduino IDE 1.x or 2.x](https://www.arduino.cc/en/software)
32+
- Start Arduino and open the Preferences window
33+
- Enter `https://arduino.esp8266.com/stable/package_esp8266com_index.json` into the *File>Preferences>Additional Boards Manager URLs* field of the Arduino IDE. You can add multiple URLs, separating them with commas.
3434
- Open Boards Manager from Tools > Board menu and install *esp8266* platform (and don't forget to select your ESP8266 board from Tools > Board menu after installation).
3535

3636
#### Latest release [![Latest release](https://img.shields.io/github/release/esp8266/Arduino.svg)](https://github.com/esp8266/Arduino/releases/latest/)

cores/esp8266/core_esp8266_features.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ void precache(void *f, uint32_t bytes) {
3838
// page (ie 1 word in 8) for this to work.
3939
#define CACHE_PAGE_SIZE 32
4040

41-
uint32_t a0;
42-
__asm__("mov.n %0, a0" : "=r"(a0));
43-
uint32_t lines = (bytes/CACHE_PAGE_SIZE)+2;
44-
volatile uint32_t *p = (uint32_t*)((f ? (uint32_t)f : a0) & ~0x03);
45-
uint32_t x;
46-
for (uint32_t i=0; i<lines; i++, p+=CACHE_PAGE_SIZE/sizeof(uint32_t)) x=*p;
47-
(void)x;
41+
uint32_t lines = (bytes / CACHE_PAGE_SIZE) + 2;
42+
uint32_t *p = (uint32_t*)((uint32_t)(f ? f : __builtin_return_address(0)) & ~0x03);
43+
do {
44+
__asm__ volatile ("" : : "r"(*p)); // guarantee that the value of *p will be in some register (forced load)
45+
p += CACHE_PAGE_SIZE / sizeof(uint32_t);
46+
} while (--lines);
47+
__sync_synchronize(); // full memory barrier, mapped to MEMW in Xtensa
4848
}
4949

5050
/** based on efuse data, we could determine what type of chip this is

cores/esp8266/core_esp8266_main.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ extern "C" void __esp_delay(unsigned long ms) {
166166
extern "C" void esp_delay(unsigned long ms) __attribute__((weak, alias("__esp_delay")));
167167

168168
bool esp_try_delay(const uint32_t start_ms, const uint32_t timeout_ms, const uint32_t intvl_ms) {
169+
if (!timeout_ms) {
170+
esp_yield();
171+
return true;
172+
}
173+
169174
uint32_t expired = millis() - start_ms;
170175
if (expired >= timeout_ms) {
171176
return true; // expired

cores/esp8266/core_esp8266_postmortem.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ static void cut_here() {
110110
ets_putc('\n');
111111
}
112112

113+
static inline bool is_pc_valid(uint32_t pc) {
114+
return pc >= XCHAL_INSTRAM0_VADDR && pc < (XCHAL_INSTROM0_VADDR + XCHAL_INSTROM0_SIZE);
115+
}
116+
113117
/*
114118
Add some assembly to grab the stack pointer and pass it as an argument before
115119
it grows for the target function. Should stabilize the stack offsets, used to
@@ -125,7 +129,7 @@ asm(
125129
"\n"
126130
"__wrap_system_restart_local:\n\t"
127131
"mov a2, a1\n\t"
128-
"j postmortem_report\n\t"
132+
"j.l postmortem_report, a3\n\t"
129133
".size __wrap_system_restart_local, .-__wrap_system_restart_local\n\t"
130134
);
131135

@@ -181,7 +185,13 @@ static void postmortem_report(uint32_t sp_dump) {
181185
exccause, epc1, rst_info.epc2, rst_info.epc3, rst_info.excvaddr, rst_info.depc);
182186
}
183187
else if (rst_info.reason == REASON_SOFT_WDT_RST) {
184-
ets_printf_P(PSTR("\nSoft WDT reset\n"));
188+
ets_printf_P(PSTR("\nSoft WDT reset"));
189+
const char infinite_loop[] = { 0x06, 0xff, 0xff }; // loop: j loop
190+
if (is_pc_valid(rst_info.epc1) && 0 == memcmp_P(infinite_loop, (PGM_VOID_P)rst_info.epc1, 3u)) {
191+
// The SDK is riddled with these. They are usually preceded by an ets_printf.
192+
ets_printf_P(PSTR(" - deliberate infinite loop detected"));
193+
}
194+
ets_putc('\n');
185195
ets_printf_P(PSTR("\nException (%d):\nepc1=0x%08x epc2=0x%08x epc3=0x%08x excvaddr=0x%08x depc=0x%08x\n"),
186196
rst_info.exccause, /* Address executing at time of Soft WDT level-1 interrupt */ rst_info.epc1, 0, 0, 0, 0);
187197
}

cores/esp8266/umm_malloc/Notes.h

+11
Original file line numberDiff line numberDiff line change
@@ -341,5 +341,16 @@ Enhancement ideas:
341341
* For multiple Heaps builds, add a dedicated function that always reports
342342
DRAM results.
343343

344+
345+
April 22, 2023
346+
347+
The umm_poison logic runs outside the UMM_CRITICAL_* umbrella. When interrupt
348+
routines do alloc calls, it is possible to interrupt an in-progress allocation
349+
just before the poison is set, with a new alloc request resulting in a false
350+
"poison check fail" against the in-progress allocation. The SDK does mallocs
351+
from ISRs. SmartConfig can illustrate this issue.
352+
353+
Move get_poisoned() within UMM_CRITICAL_* in umm_malloc() and umm_realloc().
354+
344355
*/
345356
#endif

cores/esp8266/umm_malloc/umm_local.c

+5-2
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,11 @@ void *umm_poison_realloc_fl(void *ptr, size_t size, const char *file, int line)
142142

143143
add_poison_size(&size);
144144
ret = umm_realloc(ptr, size);
145-
146-
ret = get_poisoned(ret, size);
145+
/*
146+
"get_poisoned" is now called from umm_realloc while still in a critical
147+
section. Before umm_realloc returned, the pointer offset was adjusted to
148+
the start of the requested buffer.
149+
*/
147150

148151
return ret;
149152
}

cores/esp8266/umm_malloc/umm_malloc.cpp

+22-8
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,8 @@ void *umm_malloc(size_t size) {
909909

910910
ptr = umm_malloc_core(_context, size);
911911

912+
ptr = POISON_CHECK_SET_POISON(ptr, size);
913+
912914
UMM_CRITICAL_EXIT(id_malloc);
913915

914916
return ptr;
@@ -926,7 +928,7 @@ void *umm_realloc(void *ptr, size_t size) {
926928

927929
uint16_t c;
928930

929-
size_t curSize;
931+
[[maybe_unused]] size_t curSize;
930932

931933
UMM_CHECK_INITIALIZED();
932934

@@ -1068,7 +1070,7 @@ void *umm_realloc(void *ptr, size_t size) {
10681070
// Case 2 - block + next block fits EXACTLY
10691071
} else if ((blockSize + nextBlockSize) == blocks) {
10701072
DBGLOG_DEBUG("exact realloc using next block - %i\n", blocks);
1071-
umm_assimilate_up(c);
1073+
umm_assimilate_up(_context, c);
10721074
STATS__FREE_BLOCKS_UPDATE(-nextBlockSize);
10731075
blockSize += nextBlockSize;
10741076

@@ -1087,8 +1089,10 @@ void *umm_realloc(void *ptr, size_t size) {
10871089
STATS__FREE_BLOCKS_UPDATE(-prevBlockSize);
10881090
STATS__FREE_BLOCKS_ISR_MIN();
10891091
blockSize += prevBlockSize;
1092+
// Fix new allocation such that poison checks from an ISR pass.
1093+
POISON_CHECK_SET_POISON_BLOCKS((void *)&UMM_DATA(c), blockSize);
10901094
UMM_CRITICAL_SUSPEND(id_realloc);
1091-
memmove((void *)&UMM_DATA(c), ptr, curSize);
1095+
UMM_POISON_MEMMOVE((void *)&UMM_DATA(c), ptr, curSize);
10921096
ptr = (void *)&UMM_DATA(c);
10931097
UMM_CRITICAL_RESUME(id_realloc);
10941098
// Case 5 - prev block + block + next block fits
@@ -1108,8 +1112,9 @@ void *umm_realloc(void *ptr, size_t size) {
11081112
#else
11091113
blockSize += (prevBlockSize + nextBlockSize);
11101114
#endif
1115+
POISON_CHECK_SET_POISON_BLOCKS((void *)&UMM_DATA(c), blockSize);
11111116
UMM_CRITICAL_SUSPEND(id_realloc);
1112-
memmove((void *)&UMM_DATA(c), ptr, curSize);
1117+
UMM_POISON_MEMMOVE((void *)&UMM_DATA(c), ptr, curSize);
11131118
ptr = (void *)&UMM_DATA(c);
11141119
UMM_CRITICAL_RESUME(id_realloc);
11151120

@@ -1119,8 +1124,9 @@ void *umm_realloc(void *ptr, size_t size) {
11191124
void *oldptr = ptr;
11201125
if ((ptr = umm_malloc_core(_context, size))) {
11211126
DBGLOG_DEBUG("realloc %i to a bigger block %i, copy, and free the old\n", blockSize, blocks);
1127+
(void)POISON_CHECK_SET_POISON(ptr, size);
11221128
UMM_CRITICAL_SUSPEND(id_realloc);
1123-
memcpy(ptr, oldptr, curSize);
1129+
UMM_POISON_MEMCPY(ptr, oldptr, curSize);
11241130
UMM_CRITICAL_RESUME(id_realloc);
11251131
umm_free_core(_context, oldptr);
11261132
} else {
@@ -1181,8 +1187,10 @@ void *umm_realloc(void *ptr, size_t size) {
11811187
blockSize = blocks;
11821188
#endif
11831189
}
1190+
// Fix new allocation such that poison checks from an ISR pass.
1191+
POISON_CHECK_SET_POISON_BLOCKS((void *)&UMM_DATA(c), blockSize);
11841192
UMM_CRITICAL_SUSPEND(id_realloc);
1185-
memmove((void *)&UMM_DATA(c), ptr, curSize);
1193+
UMM_POISON_MEMMOVE((void *)&UMM_DATA(c), ptr, curSize);
11861194
ptr = (void *)&UMM_DATA(c);
11871195
UMM_CRITICAL_RESUME(id_realloc);
11881196
} else if (blockSize >= blocks) { // 2
@@ -1198,8 +1206,9 @@ void *umm_realloc(void *ptr, size_t size) {
11981206
void *oldptr = ptr;
11991207
if ((ptr = umm_malloc_core(_context, size))) {
12001208
DBGLOG_DEBUG("realloc %d to a bigger block %d, copy, and free the old\n", blockSize, blocks);
1209+
(void)POISON_CHECK_SET_POISON(ptr, size);
12011210
UMM_CRITICAL_SUSPEND(id_realloc);
1202-
memcpy(ptr, oldptr, curSize);
1211+
UMM_POISON_MEMCPY(ptr, oldptr, curSize);
12031212
UMM_CRITICAL_RESUME(id_realloc);
12041213
umm_free_core(_context, oldptr);
12051214
} else {
@@ -1223,8 +1232,9 @@ void *umm_realloc(void *ptr, size_t size) {
12231232
void *oldptr = ptr;
12241233
if ((ptr = umm_malloc_core(_context, size))) {
12251234
DBGLOG_DEBUG("realloc %d to a bigger block %d, copy, and free the old\n", blockSize, blocks);
1235+
(void)POISON_CHECK_SET_POISON(ptr, size);
12261236
UMM_CRITICAL_SUSPEND(id_realloc);
1227-
memcpy(ptr, oldptr, curSize);
1237+
UMM_POISON_MEMCPY(ptr, oldptr, curSize);
12281238
UMM_CRITICAL_RESUME(id_realloc);
12291239
umm_free_core(_context, oldptr);
12301240
} else {
@@ -1250,6 +1260,8 @@ void *umm_realloc(void *ptr, size_t size) {
12501260

12511261
STATS__FREE_BLOCKS_MIN();
12521262

1263+
ptr = POISON_CHECK_SET_POISON(ptr, size);
1264+
12531265
/* Release the critical section... */
12541266
UMM_CRITICAL_EXIT(id_realloc);
12551267

@@ -1258,6 +1270,7 @@ void *umm_realloc(void *ptr, size_t size) {
12581270

12591271
/* ------------------------------------------------------------------------ */
12601272

1273+
#if !defined(UMM_POISON_CHECK) && !defined(UMM_POISON_CHECK_LITE)
12611274
void *umm_calloc(size_t num, size_t item_size) {
12621275
void *ret;
12631276

@@ -1273,6 +1286,7 @@ void *umm_calloc(size_t num, size_t item_size) {
12731286

12741287
return ret;
12751288
}
1289+
#endif
12761290

12771291
/* ------------------------------------------------------------------------ */
12781292

cores/esp8266/umm_malloc/umm_malloc_cfg.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,17 @@ extern bool umm_poison_check(void);
618618
// Local Additions to better report location in code of the caller.
619619
void *umm_poison_realloc_fl(void *ptr, size_t size, const char *file, int line);
620620
void umm_poison_free_fl(void *ptr, const char *file, int line);
621+
#define POISON_CHECK_SET_POISON(p, s) get_poisoned(p, s)
622+
#define POISON_CHECK_SET_POISON_BLOCKS(p, s) \
623+
do { \
624+
size_t super_size = (s * sizeof(umm_block)) - (sizeof(((umm_block *)0)->header)); \
625+
get_poisoned(p, super_size); \
626+
} while (false)
627+
#define UMM_POISON_SKETCH_PTR(p) ((void *)((uintptr_t)p + sizeof(UMM_POISONED_BLOCK_LEN_TYPE) + UMM_POISON_SIZE_BEFORE))
628+
#define UMM_POISON_SKETCH_PTRSZ(p) (*(UMM_POISONED_BLOCK_LEN_TYPE *)p)
629+
#define UMM_POISON_MEMMOVE(t, p, s) memmove(UMM_POISON_SKETCH_PTR(t), UMM_POISON_SKETCH_PTR(p), UMM_POISON_SKETCH_PTRSZ(p))
630+
#define UMM_POISON_MEMCPY(t, p, s) memcpy(UMM_POISON_SKETCH_PTR(t), UMM_POISON_SKETCH_PTR(p), UMM_POISON_SKETCH_PTRSZ(p))
631+
621632
#if defined(UMM_POISON_CHECK_LITE)
622633
/*
623634
* We can safely do individual poison checks at free and realloc and stay
@@ -637,9 +648,12 @@ void umm_poison_free_fl(void *ptr, const char *file, int line);
637648
#else
638649
#define POISON_CHECK() 1
639650
#define POISON_CHECK_NEIGHBORS(c) do {} while (false)
651+
#define POISON_CHECK_SET_POISON(p, s) (p)
652+
#define POISON_CHECK_SET_POISON_BLOCKS(p, s)
653+
#define UMM_POISON_MEMMOVE(t, p, s) memmove((t), (p), (s))
654+
#define UMM_POISON_MEMCPY(t, p, s) memcpy((t), (p), (s))
640655
#endif
641656

642-
643657
#if defined(UMM_POISON_CHECK) || defined(UMM_POISON_CHECK_LITE)
644658
/*
645659
* Overhead adjustments needed for free_blocks to express the number of bytes

cores/esp8266/umm_malloc/umm_poison.c

+12-7
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,11 @@ void *umm_poison_malloc(size_t size) {
163163
add_poison_size(&size);
164164

165165
ret = umm_malloc(size);
166-
167-
ret = get_poisoned(ret, size);
166+
/*
167+
"get_poisoned" is now called from umm_malloc while still in a critical
168+
section. Before umm_malloc returned, the pointer offset was adjusted to
169+
the start of the requested buffer.
170+
*/
168171

169172
return ret;
170173
}
@@ -177,17 +180,16 @@ void *umm_poison_calloc(size_t num, size_t item_size) {
177180
// Use saturated multiply.
178181
// Rely on umm_malloc to supply the fail response as needed.
179182
size_t size = umm_umul_sat(num, item_size);
183+
size_t request_sz = size;
180184

181185
add_poison_size(&size);
182186

183187
ret = umm_malloc(size);
184188

185189
if (NULL != ret) {
186-
memset(ret, 0x00, size);
190+
memset(ret, 0x00, request_sz);
187191
}
188192

189-
ret = get_poisoned(ret, size);
190-
191193
return ret;
192194
}
193195

@@ -200,8 +202,11 @@ void *umm_poison_realloc(void *ptr, size_t size) {
200202

201203
add_poison_size(&size);
202204
ret = umm_realloc(ptr, size);
203-
204-
ret = get_poisoned(ret, size);
205+
/*
206+
"get_poisoned" is now called from umm_realloc while still in a critical
207+
section. Before umm_realloc returned, the pointer offset was adjusted to
208+
the start of the requested buffer.
209+
*/
205210

206211
return ret;
207212
}

0 commit comments

Comments
 (0)