Skip to content

Commit

Permalink
Support for 2nd Heap, excess IRAM, through umm_malloc.
Browse files Browse the repository at this point in the history
Adapted changes to umm_malloc, Esp.cpp, StackThunk.cpp,
WiFiClientSecureBearSSL.cpp, and virtualmem.ino to irammem.ino from
@earlephilhower PR esp8266#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.
  • Loading branch information
mhightower83 committed Mar 2, 2020
1 parent b443e43 commit 0c661db
Show file tree
Hide file tree
Showing 22 changed files with 1,300 additions and 276 deletions.
46 changes: 46 additions & 0 deletions cores/esp8266/Esp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include "umm_malloc/umm_malloc.h"
#include "cont.h"
#include "coredecls.h"
#include "umm_malloc/umm_malloc.h"
// #include "core_esp8266_vm.h"

extern "C" {
#include "user_interface.h"
Expand Down Expand Up @@ -698,3 +700,47 @@ String EspClass::getSketchMD5()
result = md5.toString();
return result;
}

void EspClass::enableVM()
{
#ifdef UMM_HEAP_EXTERNAL
if (!vmEnabled)
install_vm_exception_handler();
vmEnabled = true;
#endif
}

void EspClass::setExternalHeap()
{
#ifdef UMM_HEAP_EXTERNAL
if (vmEnabled)
umm_push_heap(UMM_HEAP_EXTERNAL);
#endif
}

void EspClass::setIramHeap()
{
#ifdef UMM_HEAP_IRAM
umm_push_heap(UMM_HEAP_IRAM);
#endif
}

void EspClass::setDramHeap()
{
#if defined(UMM_HEAP_EXTERNAL) && !defined(UMM_HEAP_IRAM)
if (vmEnabled)
umm_push_heap(UMM_HEAP_DRAM);
#elif defined(UMM_HEAP_IRAM)
umm_push_heap(UMM_HEAP_DRAM);
#endif
}

void EspClass::resetHeap()
{
#if defined(UMM_HEAP_EXTERNAL) && !defined(UMM_HEAP_IRAM)
if (vmEnabled)
umm_pop_heap();
#elif defined(UMM_HEAP_IRAM)
umm_pop_heap();
#endif
}
11 changes: 11 additions & 0 deletions cores/esp8266/Esp.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,17 @@ class EspClass {
#else
uint32_t getCycleCount();
#endif

void enableVM();
void setDramHeap();
void setIramHeap();
void setExternalHeap();
void setInternalHeap() {setDramHeap();}; // depricated
void resetHeap();
private:
#ifdef UMM_HEAP_EXTERNAL
bool vmEnabled = false;
#endif
};

#ifndef CORE_MOCK
Expand Down
4 changes: 4 additions & 0 deletions cores/esp8266/StackThunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <stdlib.h>
#include "StackThunk.h"
#include <ets_sys.h>
#include <umm_malloc/umm_malloc.h>

extern "C" {

Expand All @@ -45,7 +46,10 @@ void stack_thunk_add_ref()
{
stack_thunk_refcnt++;
if (stack_thunk_refcnt == 1) {
ETS_PRINTF("\nStackThunk malloc(%u)\n", _stackSize * sizeof(uint32_t));
HeapSelectDram ephemeral;
stack_thunk_ptr = (uint32_t *)malloc(_stackSize * sizeof(uint32_t));
ETS_PRINTF("StackThunk stack_thunk_ptr: %p\n", stack_thunk_ptr);
stack_thunk_top = stack_thunk_ptr + _stackSize - 1;
stack_thunk_save = NULL;
stack_thunk_repaint();
Expand Down
15 changes: 10 additions & 5 deletions cores/esp8266/core_esp8266_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ extern "C" {
}
#include <core_version.h>
#include "gdb_hooks.h"
#include <umm_malloc/umm_malloc.h>
#include <core_esp8266_non32xfer.h>


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

DBG_MM_PRINT_STATUS();
DBG_MMU_PRINT_STATUS();

DBG_MMU_PRINT_IRAM_BANK_REG(0);
DBG_MMU_PRINT_IRAM_BANK_REG(0, "");

DBG_MMU_PRINTF("\nCall call_user_start()\n");

/* Call the entry point of the SDK code. */
call_user_start();
}

static void app_entry_custom (void) __attribute__((weakref("app_entry_redefinable")));

extern "C" void app_entry (void)
{
umm_init();
return app_entry_custom();
}

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

cont_init(g_pcont);

#ifdef NON32XFER_HANDLER
#if defined(NON32XFER_HANDLER) || defined(MMU_SEC_HEAP)
install_non32xfer_exception_handler();
#endif

#if defined(MMU_SEC_HEAP)
umm_init_iram();
#endif
preinit(); // Prior to C++ Dynamic Init (not related to above init() ). Meant to be user redefinable.

ets_task(loop_task,
Expand Down
65 changes: 33 additions & 32 deletions cores/esp8266/core_esp8266_non32xfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,6 @@

extern "C" {

#if 1
#define ETS_PRINTF ets_uart_printf
#else
#define ETS_PRINTF(...) do {} while(false)
#endif

#ifndef __MMU_IRAM_H
bool inline is_iram(uint32_t addr) {
(void)addr;
return true;
}

bool inline is_icache(uint32_t addr) {
(void)addr;
return true;
}
#endif

#define LOAD_MASK 0x00f00fu
#define L8UI_MATCH 0x000002u
#define L16UI_MATCH 0x001002u
Expand All @@ -66,10 +48,16 @@ bool inline is_icache(uint32_t addr) {
#define EXCCAUSE_LOAD_STORE_ERROR 3 /* Non 32-bit read/write error */

uint32_t mmu_non32xfer_count = 0;
uint32_t mmu_non32xfer_withinisr_count = 0;

#define DEBUG_WARNING
#ifdef DEBUG_WARNING
static void warning(void)
{
DEBUGV("WARNING: The Non-32-bit transfer hander has been invoked, and performance may suffer.\n");
ETS_PRINTF("WARNING: The Non-32-bit transfer hander has been invoked, and performance may suffer.\n");
}
#endif

static fn_exception_handler_t old_handler = NULL;

static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef, uint32_t cause)
Expand All @@ -88,12 +76,13 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
*/
uint32_t insn;
__asm(
"movi %0, ~3;" /* prepare a mask for the EPC */
"and %0, %0, %1;" /* apply mask for 32bit aligned base */
"ssa8l %1;" /* set up shift register for src op */
"l32i %1, %0, 0;" /* load part 1 */
"l32i %0, %0, 4;" /* load part 2 */
"src %0, %0, %1;" /* right shift to get faulting instruction */
"rsil %0, 15\n\t" /* Turn IRQs back off, let exit wrapper restore PS */
"movi %0, ~3\n\t" /* prepare a mask for the EPC */
"and %0, %0, %1\n\t" /* apply mask for 32bit aligned base */
"ssa8l %1\n\t" /* set up shift register for src op */
"l32i %1, %0, 0\n\t" /* load part 1 */
"l32i %0, %0, 4\n\t" /* load part 2 */
"src %0, %0, %1\n\t" /* right shift to get faulting instruction */
:"=&r"(insn)
:"r"(ef->epc)
:
Expand All @@ -105,10 +94,15 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
an exception handler?
*/
if (ef->ps & 0x0F) {
ETS_PRINTF("\nload/store exception with INTLEVEL 0x%02X\n", ef->ps & 0x0F);
#if 0
continue; /* fail, not safe for IRQ disabled ?? */
#endif
if (0 == mmu_non32xfer_withinisr_count) {
ETS_PRINTF("\nload/store exception with INTLEVEL 0x%02X\n", ef->ps & 0x0F);
#if 0
continue; /* fail, not safe for IRQ disabled ?? */
#endif
}
if (0 == ++mmu_non32xfer_withinisr_count) {
--mmu_non32xfer_withinisr_count; // saturated
}
}

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

#ifdef DEBUG_WARNING
if (0 == mmu_non32xfer_count) {
// This may be causing some issues TODO retest with umm_malloc within
// interrupt context.
schedule_function(warning);
}
#endif
// Some accounting information so we know this is happending.
if (0 == ++mmu_non32xfer_count) {
--mmu_non32xfer_count; // saturated
Expand Down Expand Up @@ -208,10 +206,13 @@ static IRAM_ATTR void non32xfer_exception_handler(struct __exception_frame *ef,
}


void install_non32xfer_exception_handler(void)
void IRAM_ATTR install_non32xfer_exception_handler(void)
{
old_handler =
_xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR, non32xfer_exception_handler);
if (NULL == old_handler) {
old_handler =
_xtos_set_exception_handler(EXCCAUSE_LOAD_STORE_ERROR,
non32xfer_exception_handler);
}
}

};
2 changes: 1 addition & 1 deletion cores/esp8266/esp8266_undocumented.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ struct __exception_frame
typedef void (*fn_exception_handler_t)(struct __exception_frame *ef, uint32_t cause);
extern fn_exception_handler_t _xtos_set_exception_handler(uint32_t reason, fn_exception_handler_t fn);

//D extern void _xtos_unhandled_exception(struct __exception_frame *ef, uint32_t cause);
extern void _xtos_unhandled_exception(struct __exception_frame *ef, uint32_t cause);

#ifdef __cplusplus
};
Expand Down
81 changes: 74 additions & 7 deletions cores/esp8266/mmu_iram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "Arduino.h"
#include "mmu_iram.h"
#include <user_interface.h>

extern "C" {

Expand Down Expand Up @@ -110,12 +111,12 @@ void IRAM_ATTR Cache_Read_Enable(uint8_t map, uint8_t p, uint8_t v) {
if (0 == mmu_status.enable_count) {
mmu_status.enable_count--; // keep saturated value
}
DBG_MMU_PRINT_IRAM_BANK_REG("before");
DBG_MMU_PRINT_IRAM_BANK_REG("before", "Enable");

real_Cache_Read_Enable(map, p, SOC_CACHE_SIZE);

DBG_MMU_PRINT_IRAM_BANK_REG("after");
DBG_MM_PRINT_STATUS();
DBG_MMU_PRINT_IRAM_BANK_REG("after", "Enable");
DBG_MMU_PRINT_STATUS();
}

#ifndef ROM_Cache_Read_Disable
Expand All @@ -129,20 +130,86 @@ constexpr fp_Cache_Read_Disable_t real_Cache_Read_Disable =
*
*/
void IRAM_ATTR Cache_Read_Disable(void) {

mmu_status.disable_count++;
mmu_status.state = 0;
if (0 == mmu_status.disable_count) {
mmu_status.disable_count--; // keep saturated value
}
DBG_MMU_PRINT_IRAM_BANK_REG("before");
DBG_MMU_PRINT_IRAM_BANK_REG("before", "Disable");

real_Cache_Read_Disable();

DBG_MMU_PRINT_IRAM_BANK_REG("after");
DBG_MM_PRINT_STATUS();
DBG_MMU_PRINT_IRAM_BANK_REG("after", "Disable");
DBG_MMU_PRINT_STATUS();
}

#ifdef DEV_DEBUG_PRINT
/*
* Early adjustment for CPU crystal frequency, so debug printing will work.
* This should not be left enabled all the time in Crash_Read..., I am concerned
* that there may be unknown interference with the NONOS SDK startup.
*
* Inspired by:
* https://github.com/pvvx/esp8266web/blob/2e25559bc489487747205db2ef171d48326b32d4/app/sdklib/system/app_main.c#L581-L591
*/
extern "C" uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
extern "C" void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);

extern "C" void IRAM_ATTR set_pll(void)
{
#if !defined(F_CRYSTAL)
#define F_CRYSTAL 26000000
#endif
if (F_CRYSTAL != 40000000) {
// At Boot ROM(-BIOS) start, it assumes a 40MHz crystal.
// If it is not, we assume a 26MHz crystal.
// There is no support for 24MHz crustal at this time.
if(rom_i2c_readReg(103,4,1) != 136) { // 8: 40MHz, 136: 26MHz
// Assume 26MHz crystal
// soc_param0: 0: 40MHz, 1: 26MHz, 2: 24MHz
// set 80MHz PLL CPU
rom_i2c_writeReg(103,4,1,136);
rom_i2c_writeReg(103,4,2,145);
}
}
}

extern "C" void IRAM_ATTR dbg_set_pll(void)
{
char r103_4_1 = rom_i2c_readReg(103,4,1);
char r103_4_2 = rom_i2c_readReg(103,4,2);
set_pll();
ets_uart_printf("\nrom_i2c_readReg(103,4,1) == %u\n", r103_4_1);
ets_uart_printf( "rom_i2c_readReg(103,4,2) == %u\n", r103_4_2);
}

/*
This helps keep the UART enabled at user_init() so we can get a few more
messages printed.
*/
extern struct rst_info resetInfo;
extern "C" void __pinMode( uint8_t pin, uint8_t mode );

inline bool is_gpio_persistent(void) {
return REASON_EXCEPTION_RST <= resetInfo.reason &&
REASON_SOFT_RESTART >= resetInfo.reason;
}

extern "C" void pinMode( uint8_t pin, uint8_t mode ) {
static bool in_initPins = true;
if (in_initPins && (1 == pin)) {
if (!is_gpio_persistent()) {
/* Restore pin to TX after Power-on and EXT_RST */
__pinMode(pin, FUNCTION_0);
}
in_initPins = false;
return;
}

__pinMode( pin, mode );
}
#endif

#endif

};
Loading

0 comments on commit 0c661db

Please sign in to comment.