Skip to content

Commit 0c661db

Browse files
committed
Support for 2nd Heap, excess IRAM, through umm_malloc.
Adapted changes to umm_malloc, Esp.cpp, StackThunk.cpp, WiFiClientSecureBearSSL.cpp, and virtualmem.ino to irammem.ino from @earlephilhower PR #6994. Reworked umm_malloc to use context pointers instead of copy context. umm_malloc now supports allocations from IRAM. Added class HeapSelectIram, ... to aid in selecting alternate heaps, modeled after class InterruptLock. Restrict alloc request from ISRs to DRAM. Never ending improvements to debug printing. Sec Heap option now pulls in free IRAM left over in the 1st 32K block. Managed through umm_malloc with HeapSelectIram. Updated examples.
1 parent b443e43 commit 0c661db

File tree

22 files changed

+1300
-276
lines changed

22 files changed

+1300
-276
lines changed

cores/esp8266/Esp.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#include "umm_malloc/umm_malloc.h"
2828
#include "cont.h"
2929
#include "coredecls.h"
30+
#include "umm_malloc/umm_malloc.h"
31+
// #include "core_esp8266_vm.h"
3032

3133
extern "C" {
3234
#include "user_interface.h"
@@ -698,3 +700,47 @@ String EspClass::getSketchMD5()
698700
result = md5.toString();
699701
return result;
700702
}
703+
704+
void EspClass::enableVM()
705+
{
706+
#ifdef UMM_HEAP_EXTERNAL
707+
if (!vmEnabled)
708+
install_vm_exception_handler();
709+
vmEnabled = true;
710+
#endif
711+
}
712+
713+
void EspClass::setExternalHeap()
714+
{
715+
#ifdef UMM_HEAP_EXTERNAL
716+
if (vmEnabled)
717+
umm_push_heap(UMM_HEAP_EXTERNAL);
718+
#endif
719+
}
720+
721+
void EspClass::setIramHeap()
722+
{
723+
#ifdef UMM_HEAP_IRAM
724+
umm_push_heap(UMM_HEAP_IRAM);
725+
#endif
726+
}
727+
728+
void EspClass::setDramHeap()
729+
{
730+
#if defined(UMM_HEAP_EXTERNAL) && !defined(UMM_HEAP_IRAM)
731+
if (vmEnabled)
732+
umm_push_heap(UMM_HEAP_DRAM);
733+
#elif defined(UMM_HEAP_IRAM)
734+
umm_push_heap(UMM_HEAP_DRAM);
735+
#endif
736+
}
737+
738+
void EspClass::resetHeap()
739+
{
740+
#if defined(UMM_HEAP_EXTERNAL) && !defined(UMM_HEAP_IRAM)
741+
if (vmEnabled)
742+
umm_pop_heap();
743+
#elif defined(UMM_HEAP_IRAM)
744+
umm_pop_heap();
745+
#endif
746+
}

cores/esp8266/Esp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,17 @@ class EspClass {
198198
#else
199199
uint32_t getCycleCount();
200200
#endif
201+
202+
void enableVM();
203+
void setDramHeap();
204+
void setIramHeap();
205+
void setExternalHeap();
206+
void setInternalHeap() {setDramHeap();}; // depricated
207+
void resetHeap();
208+
private:
209+
#ifdef UMM_HEAP_EXTERNAL
210+
bool vmEnabled = false;
211+
#endif
201212
};
202213

203214
#ifndef CORE_MOCK

cores/esp8266/StackThunk.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <stdlib.h>
2929
#include "StackThunk.h"
3030
#include <ets_sys.h>
31+
#include <umm_malloc/umm_malloc.h>
3132

3233
extern "C" {
3334

@@ -45,7 +46,10 @@ void stack_thunk_add_ref()
4546
{
4647
stack_thunk_refcnt++;
4748
if (stack_thunk_refcnt == 1) {
49+
ETS_PRINTF("\nStackThunk malloc(%u)\n", _stackSize * sizeof(uint32_t));
50+
HeapSelectDram ephemeral;
4851
stack_thunk_ptr = (uint32_t *)malloc(_stackSize * sizeof(uint32_t));
52+
ETS_PRINTF("StackThunk stack_thunk_ptr: %p\n", stack_thunk_ptr);
4953
stack_thunk_top = stack_thunk_ptr + _stackSize - 1;
5054
stack_thunk_save = NULL;
5155
stack_thunk_repaint();

cores/esp8266/core_esp8266_main.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ extern "C" {
3434
}
3535
#include <core_version.h>
3636
#include "gdb_hooks.h"
37+
#include <umm_malloc/umm_malloc.h>
3738
#include <core_esp8266_non32xfer.h>
3839

3940

@@ -298,18 +299,20 @@ extern "C" void app_entry_redefinable(void)
298299
cont_t s_cont __attribute__((aligned(16)));
299300
g_pcont = &s_cont;
300301

301-
DBG_MM_PRINT_STATUS();
302+
DBG_MMU_PRINT_STATUS();
302303

303-
DBG_MMU_PRINT_IRAM_BANK_REG(0);
304+
DBG_MMU_PRINT_IRAM_BANK_REG(0, "");
305+
306+
DBG_MMU_PRINTF("\nCall call_user_start()\n");
304307

305308
/* Call the entry point of the SDK code. */
306309
call_user_start();
307310
}
308-
309311
static void app_entry_custom (void) __attribute__((weakref("app_entry_redefinable")));
310312

311313
extern "C" void app_entry (void)
312314
{
315+
umm_init();
313316
return app_entry_custom();
314317
}
315318

@@ -331,10 +334,12 @@ extern "C" void user_init(void) {
331334

332335
cont_init(g_pcont);
333336

334-
#ifdef NON32XFER_HANDLER
337+
#if defined(NON32XFER_HANDLER) || defined(MMU_SEC_HEAP)
335338
install_non32xfer_exception_handler();
336339
#endif
337-
340+
#if defined(MMU_SEC_HEAP)
341+
umm_init_iram();
342+
#endif
338343
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.
339344

340345
ets_task(loop_task,

cores/esp8266/core_esp8266_non32xfer.cpp

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,6 @@
3838

3939
extern "C" {
4040

41-
#if 1
42-
#define ETS_PRINTF ets_uart_printf
43-
#else
44-
#define ETS_PRINTF(...) do {} while(false)
45-
#endif
46-
47-
#ifndef __MMU_IRAM_H
48-
bool inline is_iram(uint32_t addr) {
49-
(void)addr;
50-
return true;
51-
}
52-
53-
bool inline is_icache(uint32_t addr) {
54-
(void)addr;
55-
return true;
56-
}
57-
#endif
58-
5941
#define LOAD_MASK 0x00f00fu
6042
#define L8UI_MATCH 0x000002u
6143
#define L16UI_MATCH 0x001002u
@@ -66,10 +48,16 @@ bool inline is_icache(uint32_t addr) {
6648
#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Non 32-bit read/write error */
6749

6850
uint32_t mmu_non32xfer_count = 0;
51+
uint32_t mmu_non32xfer_withinisr_count = 0;
52+
53+
#define DEBUG_WARNING
54+
#ifdef DEBUG_WARNING
6955
static void warning(void)
7056
{
71-
DEBUGV("WARNING: The Non-32-bit transfer hander has been invoked, and performance may suffer.\n");
57+
ETS_PRINTF("WARNING: The Non-32-bit transfer hander has been invoked, and performance may suffer.\n");
7258
}
59+
#endif
60+
7361
static fn_exception_handler_t old_handler = NULL;
7462

7563
static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, uint32_t cause)
@@ -88,12 +76,13 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
8876
*/
8977
uint32_t insn;
9078
__asm(
91-
"movi %0, ~3;" /* prepare a mask for the EPC */
92-
"and %0, %0, %1;" /* apply mask for 32bit aligned base */
93-
"ssa8l %1;" /* set up shift register for src op */
94-
"l32i %1, %0, 0;" /* load part 1 */
95-
"l32i %0, %0, 4;" /* load part 2 */
96-
"src %0, %0, %1;" /* right shift to get faulting instruction */
79+
"rsil %0, 15\n\t" /* Turn IRQs back off, let exit wrapper restore PS */
80+
"movi %0, ~3\n\t" /* prepare a mask for the EPC */
81+
"and %0, %0, %1\n\t" /* apply mask for 32bit aligned base */
82+
"ssa8l %1\n\t" /* set up shift register for src op */
83+
"l32i %1, %0, 0\n\t" /* load part 1 */
84+
"l32i %0, %0, 4\n\t" /* load part 2 */
85+
"src %0, %0, %1\n\t" /* right shift to get faulting instruction */
9786
:"=&r"(insn)
9887
:"r"(ef->epc)
9988
:
@@ -105,10 +94,15 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
10594
an exception handler?
10695
*/
10796
if (ef->ps & 0x0F) {
108-
ETS_PRINTF("\nload/store exception with INTLEVEL 0x%02X\n", ef->ps & 0x0F);
109-
#if 0
110-
continue; /* fail, not safe for IRQ disabled ?? */
111-
#endif
97+
if (0 == mmu_non32xfer_withinisr_count) {
98+
ETS_PRINTF("\nload/store exception with INTLEVEL 0x%02X\n", ef->ps & 0x0F);
99+
#if 0
100+
continue; /* fail, not safe for IRQ disabled ?? */
101+
#endif
102+
}
103+
if (0 == ++mmu_non32xfer_withinisr_count) {
104+
--mmu_non32xfer_withinisr_count; // saturated
105+
}
112106
}
113107

114108
uint32_t what = insn & LOAD_MASK;
@@ -129,9 +123,13 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
129123
continue; /* fail */
130124
}
131125

126+
#ifdef DEBUG_WARNING
132127
if (0 == mmu_non32xfer_count) {
128+
// This may be causing some issues TODO retest with umm_malloc within
129+
// interrupt context.
133130
schedule_function(warning);
134131
}
132+
#endif
135133
// Some accounting information so we know this is happending.
136134
if (0 == ++mmu_non32xfer_count) {
137135
--mmu_non32xfer_count; // saturated
@@ -208,10 +206,13 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
208206
}
209207

210208

211-
void install_non32xfer_exception_handler(void)
209+
void IRAM_ATTR install_non32xfer_exception_handler(void)
212210
{
213-
old_handler =
214-
_xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR, non32xfer_exception_handler);
211+
if (NULL == old_handler) {
212+
old_handler =
213+
_xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR,
214+
non32xfer_exception_handler);
215+
}
215216
}
216217

217218
};

cores/esp8266/esp8266_undocumented.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ struct __exception_frame
8181
typedef void (*fn_exception_handler_t)(struct __exception_frame *ef, uint32_t cause);
8282
extern fn_exception_handler_t _xtos_set_exception_handler(uint32_t reason, fn_exception_handler_t fn);
8383

84-
//D extern void _xtos_unhandled_exception(struct __exception_frame *ef, uint32_t cause);
84+
extern void _xtos_unhandled_exception(struct __exception_frame *ef, uint32_t cause);
8585

8686
#ifdef __cplusplus
8787
};

cores/esp8266/mmu_iram.cpp

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "Arduino.h"
1919
#include "mmu_iram.h"
20+
#include <user_interface.h>
2021

2122
extern "C" {
2223

@@ -110,12 +111,12 @@ void IRAM_ATTR Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v) {
110111
if (0 == mmu_status.enable_count) {
111112
mmu_status.enable_count--; // keep saturated value
112113
}
113-
DBG_MMU_PRINT_IRAM_BANK_REG("before");
114+
DBG_MMU_PRINT_IRAM_BANK_REG("before", "Enable");
114115

115116
real_Cache_Read_Enable(map, p, SOC_CACHE_SIZE);
116117

117-
DBG_MMU_PRINT_IRAM_BANK_REG("after");
118-
DBG_MM_PRINT_STATUS();
118+
DBG_MMU_PRINT_IRAM_BANK_REG("after", "Enable");
119+
DBG_MMU_PRINT_STATUS();
119120
}
120121

121122
#ifndef ROM_Cache_Read_Disable
@@ -129,20 +130,86 @@ constexpr fp_Cache_Read_Disable_t real_Cache_Read_Disable =
129130
*
130131
*/
131132
void IRAM_ATTR Cache_Read_Disable(void) {
132-
133133
mmu_status.disable_count++;
134134
mmu_status.state = 0;
135135
if (0 == mmu_status.disable_count) {
136136
mmu_status.disable_count--; // keep saturated value
137137
}
138-
DBG_MMU_PRINT_IRAM_BANK_REG("before");
138+
DBG_MMU_PRINT_IRAM_BANK_REG("before", "Disable");
139139

140140
real_Cache_Read_Disable();
141141

142-
DBG_MMU_PRINT_IRAM_BANK_REG("after");
143-
DBG_MM_PRINT_STATUS();
142+
DBG_MMU_PRINT_IRAM_BANK_REG("after", "Disable");
143+
DBG_MMU_PRINT_STATUS();
144+
}
145+
146+
#ifdef DEV_DEBUG_PRINT
147+
/*
148+
* Early adjustment for CPU crystal frequency, so debug printing will work.
149+
* This should not be left enabled all the time in Crash_Read..., I am concerned
150+
* that there may be unknown interference with the NONOS SDK startup.
151+
*
152+
* Inspired by:
153+
* https://github.com/pvvx/esp8266web/blob/2e25559bc489487747205db2ef171d48326b32d4/app/sdklib/system/app_main.c#L581-L591
154+
*/
155+
extern "C" uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
156+
extern "C" void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
157+
158+
extern "C" void IRAM_ATTR set_pll(void)
159+
{
160+
#if !defined(F_CRYSTAL)
161+
#define F_CRYSTAL 26000000
162+
#endif
163+
if (F_CRYSTAL != 40000000) {
164+
// At Boot ROM(-BIOS) start, it assumes a 40MHz crystal.
165+
// If it is not, we assume a 26MHz crystal.
166+
// There is no support for 24MHz crustal at this time.
167+
if(rom_i2c_readReg(103,4,1) != 136) { // 8: 40MHz, 136: 26MHz
168+
// Assume 26MHz crystal
169+
// soc_param0: 0: 40MHz, 1: 26MHz, 2: 24MHz
170+
// set 80MHz PLL CPU
171+
rom_i2c_writeReg(103,4,1,136);
172+
rom_i2c_writeReg(103,4,2,145);
173+
}
174+
}
144175
}
145176

177+
extern "C" void IRAM_ATTR dbg_set_pll(void)
178+
{
179+
char r103_4_1 = rom_i2c_readReg(103,4,1);
180+
char r103_4_2 = rom_i2c_readReg(103,4,2);
181+
set_pll();
182+
ets_uart_printf("\nrom_i2c_readReg(103,4,1) == %u\n", r103_4_1);
183+
ets_uart_printf( "rom_i2c_readReg(103,4,2) == %u\n", r103_4_2);
184+
}
185+
186+
/*
187+
This helps keep the UART enabled at user_init() so we can get a few more
188+
messages printed.
189+
*/
190+
extern struct rst_info resetInfo;
191+
extern "C" void __pinMode( uint8_t pin, uint8_t mode );
192+
193+
inline bool is_gpio_persistent(void) {
194+
return REASON_EXCEPTION_RST <= resetInfo.reason &&
195+
REASON_SOFT_RESTART >= resetInfo.reason;
196+
}
197+
198+
extern "C" void pinMode( uint8_t pin, uint8_t mode ) {
199+
static bool in_initPins = true;
200+
if (in_initPins && (1 == pin)) {
201+
if (!is_gpio_persistent()) {
202+
/* Restore pin to TX after Power-on and EXT_RST */
203+
__pinMode(pin, FUNCTION_0);
204+
}
205+
in_initPins = false;
206+
return;
207+
}
208+
209+
__pinMode( pin, mode );
210+
}
211+
#endif
212+
146213
#endif
147214

148215
};

0 commit comments

Comments
 (0)