mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-02 14:22:55 +03:00
Call umm_init just before starting SDK (#8207)
* Recover the BearSSL crash stack before the Heap is initialized and zeros it. * Added comments for hwdt_pre_sdk_init() * Keep Basic ASM version of app_entry_redefinable and removed alternate "C"/Extended ASM version. Update comments. * Improved example HwdtStackDump to use StackThunk
This commit is contained in:
@ -9,6 +9,7 @@
|
|||||||
#include <c_types.h>
|
#include <c_types.h>
|
||||||
#include "cont.h"
|
#include "cont.h"
|
||||||
#include "coredecls.h"
|
#include "coredecls.h"
|
||||||
|
#include <umm_malloc/umm_malloc.h>
|
||||||
|
|
||||||
void disable_extra4k_at_link_time (void)
|
void disable_extra4k_at_link_time (void)
|
||||||
{
|
{
|
||||||
@ -38,6 +39,7 @@ extern "C" void app_entry_redefinable(void)
|
|||||||
{
|
{
|
||||||
g_pcont = &g_cont;
|
g_pcont = &g_cont;
|
||||||
|
|
||||||
|
umm_init();
|
||||||
/* Call the entry point of the SDK code. */
|
/* Call the entry point of the SDK code. */
|
||||||
call_user_start();
|
call_user_start();
|
||||||
}
|
}
|
||||||
|
@ -318,6 +318,9 @@ extern "C" void app_entry_redefinable(void)
|
|||||||
cont_t s_cont __attribute__((aligned(16)));
|
cont_t s_cont __attribute__((aligned(16)));
|
||||||
g_pcont = &s_cont;
|
g_pcont = &s_cont;
|
||||||
|
|
||||||
|
/* Doing umm_init just once before starting the SDK, allowed us to remove
|
||||||
|
test and init calls at each malloc API entry point, saving IRAM. */
|
||||||
|
umm_init();
|
||||||
/* Call the entry point of the SDK code. */
|
/* Call the entry point of the SDK code. */
|
||||||
call_user_start();
|
call_user_start();
|
||||||
}
|
}
|
||||||
@ -325,7 +328,6 @@ static void app_entry_custom (void) __attribute__((weakref("app_entry_redefinabl
|
|||||||
|
|
||||||
extern "C" void app_entry (void)
|
extern "C" void app_entry (void)
|
||||||
{
|
{
|
||||||
umm_init();
|
|
||||||
return app_entry_custom();
|
return app_entry_custom();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +369,7 @@ extern "C" void user_init(void) {
|
|||||||
#if defined(UMM_HEAP_EXTERNAL)
|
#if defined(UMM_HEAP_EXTERNAL)
|
||||||
install_vm_exception_handler();
|
install_vm_exception_handler();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)
|
#if defined(NON32XFER_HANDLER) || defined(MMU_IRAM_HEAP)
|
||||||
install_non32xfer_exception_handler();
|
install_non32xfer_exception_handler();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1048,6 +1048,22 @@ static void printSanityCheck() {
|
|||||||
}
|
}
|
||||||
#endif //DEBUG_ESP_HWDT_DEV_DEBUG
|
#endif //DEBUG_ESP_HWDT_DEV_DEBUG
|
||||||
|
|
||||||
|
/*
|
||||||
|
hwdt_pre_sdk_init() is the result of a hook for development diagnotics which
|
||||||
|
evolved and was generlized to run any optional diagnostic code supplied at
|
||||||
|
link time.
|
||||||
|
|
||||||
|
Summary of the hwdt_pre_sdk_init() runtime environment:
|
||||||
|
* The code can run from flash and use PROGMEM strings.
|
||||||
|
* All functions must be extern "C" type
|
||||||
|
* C/C++ runtime has not started. Structures have not been initialized and
|
||||||
|
should have the values prior to reboot. With the exception of hwdt_info,
|
||||||
|
which was updated before this call.
|
||||||
|
* You can reference hwdt_info.reset_reason to control the action of the diagnostic.
|
||||||
|
* The stack is on the SYS stack. You have about 3K available before you
|
||||||
|
overwrite ROM Data area.
|
||||||
|
* Printing will work best with ets_uart_printf and umm_info_safe_printf_P.
|
||||||
|
*/
|
||||||
void hwdt_pre_sdk_init(void) __attribute__((weak));
|
void hwdt_pre_sdk_init(void) __attribute__((weak));
|
||||||
void hwdt_pre_sdk_init(void) {
|
void hwdt_pre_sdk_init(void) {
|
||||||
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
|
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
|
||||||
@ -1072,14 +1088,12 @@ void hwdt_pre_sdk_init_icache(void) {
|
|||||||
Cache_Read_Disable();
|
Cache_Read_Disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 1
|
|
||||||
/*
|
/*
|
||||||
An asm function alternative to the function with inline asm at the #else. I
|
For app_entry_redefinable, use Basic ASM instead of "C" with Extended ASM. The
|
||||||
find the inline asm requires constant inspection to verify that the compiler
|
(inline) Extended ASM approach required constant inspection to verify that the
|
||||||
optimizer does not clobber needed registers, after small changes in code or
|
compiler's optimizer did not clobber needed registers or do something weird
|
||||||
compiler updates. Hints to the compiler don't always work for me. Last I
|
after minor changes in code or compiler updates. Also, I think Basic ASM is
|
||||||
checked, the inline version below was working.
|
the safer route when changing the stack pointer multiple times.
|
||||||
*/
|
*/
|
||||||
cont_t *hwdt_app_entry__cont_stack __attribute__((used)) = CONT_STACK;
|
cont_t *hwdt_app_entry__cont_stack __attribute__((used)) = CONT_STACK;
|
||||||
|
|
||||||
@ -1089,6 +1103,7 @@ asm (
|
|||||||
".literal .g_pcont, g_pcont\n\t"
|
".literal .g_pcont, g_pcont\n\t"
|
||||||
".literal .pcont_stack, hwdt_app_entry__cont_stack\n\t"
|
".literal .pcont_stack, hwdt_app_entry__cont_stack\n\t"
|
||||||
".literal .sys_stack_first, sys_stack_first\n\t"
|
".literal .sys_stack_first, sys_stack_first\n\t"
|
||||||
|
".literal .umm_init, umm_init\n\t"
|
||||||
".literal .call_user_start, call_user_start\n\t"
|
".literal .call_user_start, call_user_start\n\t"
|
||||||
".literal .get_noextra4k_g_pcont, get_noextra4k_g_pcont\n\t"
|
".literal .get_noextra4k_g_pcont, get_noextra4k_g_pcont\n\t"
|
||||||
".align 4\n\t"
|
".align 4\n\t"
|
||||||
@ -1135,90 +1150,39 @@ asm (
|
|||||||
"l32r a13, .pcont_stack\n\t"
|
"l32r a13, .pcont_stack\n\t"
|
||||||
"l32r a0, .get_noextra4k_g_pcont\n\t"
|
"l32r a0, .get_noextra4k_g_pcont\n\t"
|
||||||
"l32r a14, .g_pcont\n\t"
|
"l32r a14, .g_pcont\n\t"
|
||||||
|
// We now switch to the SYS stack the SDK will use
|
||||||
"l32i.n a1, a2, 0\n\t" // delayed load for pipeline
|
"l32i.n a1, a2, 0\n\t" // delayed load for pipeline
|
||||||
"l32i.n a13, a13, 0\n\t"
|
"l32i.n a13, a13, 0\n\t"
|
||||||
"callx0 a0\n\t"
|
"callx0 a0\n\t"
|
||||||
"moveqz a2, a13, a2\n\t"
|
"moveqz a2, a13, a2\n\t"
|
||||||
"s32i.n a2, a14, 0\n\t"
|
"s32i.n a2, a14, 0\n\t"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allow for running additional diagnotics supplied at link time.
|
||||||
|
*/
|
||||||
"call0 hwdt_pre_sdk_init_icache\n\t"
|
"call0 hwdt_pre_sdk_init_icache\n\t"
|
||||||
|
|
||||||
|
// In case somebody cares, leave things as we found them
|
||||||
|
// - Restore ROM BSS zeros.
|
||||||
"movi a2, 0x3FFFE000\n\t" // ROM BSS Area
|
"movi a2, 0x3FFFE000\n\t" // ROM BSS Area
|
||||||
"movi a3, 0x0b30\n\t" // ROM BSS Size
|
"movi a3, 0x0b30\n\t" // ROM BSS Size
|
||||||
"call0 ets_bzero\n\t"
|
"call0 ets_bzero\n\t"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Up until this call, the heap at crash time has been available for
|
||||||
|
* analysis. This is needed for dumping the bearssl stack. Also, future
|
||||||
|
* improvements could possibly use hwdt_pre_sdk_init() to run other early
|
||||||
|
* diagnostic tools.
|
||||||
|
*/
|
||||||
|
"l32r a0, .umm_init\n\t"
|
||||||
|
"callx0 a0\n\t"
|
||||||
|
|
||||||
"l32r a3, .call_user_start\n\t"
|
"l32r a3, .call_user_start\n\t"
|
||||||
"movi a0, 0x4000044c\n\t"
|
"movi a0, 0x4000044c\n\t"
|
||||||
"jx a3\n\t"
|
"jx a3\n\t"
|
||||||
".size app_entry_redefinable, .-app_entry_redefinable\n\t"
|
".size app_entry_redefinable, .-app_entry_redefinable\n\t"
|
||||||
);
|
);
|
||||||
|
|
||||||
#else
|
|
||||||
void IRAM_ATTR app_entry_start(void) {
|
|
||||||
|
|
||||||
#ifdef USE_IRAM
|
|
||||||
handle_hwdt();
|
|
||||||
#else
|
|
||||||
handle_hwdt_icache();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Continuation context is in BSS.
|
|
||||||
*/
|
|
||||||
g_pcont = get_noextra4k_g_pcont();
|
|
||||||
|
|
||||||
if (!g_pcont) {
|
|
||||||
/*
|
|
||||||
* The continuation context is on the stack just after the reserved
|
|
||||||
* space for the ROM/eboot stack and before the SYS stack begins. All
|
|
||||||
* computations were done at top, save pointer to it now.
|
|
||||||
*/
|
|
||||||
g_pcont = CONT_STACK;
|
|
||||||
}
|
|
||||||
#if defined(DEBUG_ESP_HWDT_DEV_DEBUG) && !defined(USE_IRAM)
|
|
||||||
print_sanity_check_icache();
|
|
||||||
#endif
|
|
||||||
/*
|
|
||||||
* Use new calculated SYS stack from top.
|
|
||||||
* Call the entry point of the SDK code.
|
|
||||||
*/
|
|
||||||
asm volatile ("mov.n a1, %0\n\t"
|
|
||||||
"movi a0, 0x4000044c\n\t" /* Should never return; however, set return to Boot ROM Breakpoint */
|
|
||||||
"jx %1\n\t" ::
|
|
||||||
"r" (sys_stack_first), "r" (call_user_start):
|
|
||||||
"a0", "memory");
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR app_entry_redefinable(void) {
|
|
||||||
/*
|
|
||||||
* There are 4 sections of code that share the stack starting near
|
|
||||||
* 0x40000000.
|
|
||||||
* 1) The Boot ROM (uses around 640 bytes)
|
|
||||||
* 2) The Bootloader, eboot.elf (last seen using 720 bytes.)
|
|
||||||
* 3) `app_entry_redefinable()` just before it starts the SDK.
|
|
||||||
* 4) The NONOS SDK, optionally the Core when the extra 4K option is
|
|
||||||
* selected.
|
|
||||||
*
|
|
||||||
* Use the ROM BSS zeroed out memory as the home for our temporary stack.
|
|
||||||
* This way no additional information will be lost. That will remove this
|
|
||||||
* tool from the list of possible concerns for stack overwrite.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
asm volatile ("movi a1, 0x3fffeb30\n\t"
|
|
||||||
"j app_entry_start" ::: "memory");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Keep this function with just asm seems to help avoid a stack frame being
|
|
||||||
* created for this function and things getting really confused.
|
|
||||||
*/
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(DEBUG_ESP_HWDT_INFO) || defined(ROM_STACK_DUMP)
|
#if defined(DEBUG_ESP_HWDT_INFO) || defined(ROM_STACK_DUMP)
|
||||||
void debug_hwdt_init(void) {
|
void debug_hwdt_init(void) {
|
||||||
/*
|
/*
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
speed defaults to 115200 bps. The HWDT stack dump will always print on port
|
speed defaults to 115200 bps. The HWDT stack dump will always print on port
|
||||||
'Serial'.
|
'Serial'.
|
||||||
|
|
||||||
To demonstrates this tool, this Sketch offers a few options for crashing the
|
To demonstrate this tool, this Sketch offers a few options for crashing the
|
||||||
ESP8266 with and without a HWDT reset.
|
ESP8266 with and without a HWDT reset.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
@ -20,6 +20,7 @@
|
|||||||
#include <Esp.h>
|
#include <Esp.h>
|
||||||
#include <user_interface.h>
|
#include <user_interface.h>
|
||||||
#include <coredecls.h> // g_pcont - only needed for this debug demo
|
#include <coredecls.h> // g_pcont - only needed for this debug demo
|
||||||
|
#include <StackThunk.h>
|
||||||
|
|
||||||
#ifndef STASSID
|
#ifndef STASSID
|
||||||
#define STASSID "your-ssid"
|
#define STASSID "your-ssid"
|
||||||
@ -29,6 +30,22 @@
|
|||||||
const char* ssid = STASSID;
|
const char* ssid = STASSID;
|
||||||
const char* password = STAPSK;
|
const char* password = STAPSK;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// This block is just for putting something on the BearSSL stack
|
||||||
|
// to show that it has not been zeroed out before HWDT stack dump
|
||||||
|
// gets to runs.
|
||||||
|
extern "C" {
|
||||||
|
#if CORE_MOCK
|
||||||
|
#define thunk_ets_uart_printf ets_uart_printf
|
||||||
|
|
||||||
|
#else
|
||||||
|
int thunk_ets_uart_printf(const char *format, ...) __attribute__((format(printf, 1, 2)));
|
||||||
|
// Second stack thunked helper - this macro creates the global function thunk_ets_uart_printf
|
||||||
|
make_stack_thunk(ets_uart_printf);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void setup(void) {
|
void setup(void) {
|
||||||
WiFi.persistent(false); // w/o this a flash write occurs at every boot
|
WiFi.persistent(false); // w/o this a flash write occurs at every boot
|
||||||
WiFi.mode(WIFI_OFF);
|
WiFi.mode(WIFI_OFF);
|
||||||
@ -39,6 +56,10 @@ void setup(void) {
|
|||||||
Serial.println(F("The Hardware Watchdog Timer Demo is starting ..."));
|
Serial.println(F("The Hardware Watchdog Timer Demo is starting ..."));
|
||||||
Serial.println();
|
Serial.println();
|
||||||
|
|
||||||
|
// This allows us to test dumping a BearSSL stack after HWDT.
|
||||||
|
stack_thunk_add_ref();
|
||||||
|
thunk_ets_uart_printf("Using Thunk Stack to print this line.\n\n");
|
||||||
|
|
||||||
// We don't need this for this example; however, starting WiFi uses a little
|
// We don't need this for this example; however, starting WiFi uses a little
|
||||||
// more of the SYS stack.
|
// more of the SYS stack.
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
|
Reference in New Issue
Block a user