Commit 7836c39e authored by Alessandro Rubini's avatar Alessandro Rubini

Optionally detect reset and print a stack trace

The new configuation option CONFIG_CHECK_RESET adds a function to dump
the stack (to the serial port) if a reset is detected. This happens
when a null pointer is followed or when the program is reloaded
(spec-sw/tools/spec-cl, for example).  For this reason, the feature is
disabled by default (actually, spec-cl may clear the RAM first, but it
currently doesn't do that and the check is triggered).
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 0a260fb3
......@@ -27,6 +27,14 @@ config PPSI
endchoice
config CHECK_RESET
bool "Print a stack trace if reset happens"
help
If the CPU is following a NULL pointer, the program will
be restarted. If this option is activated, the main function
detects that it is re-executed and dumps a stack trace; it
then clears the stack (for next time) and restarts again.
config PPSI_VERBOSITY
depends on PPSI
int "Default verbosity for PPSI"
......
......@@ -151,6 +151,7 @@ static void ui_update()
}
extern uint32_t _endram;
extern uint32_t _fstack;
#define ENDRAM_MAGIC 0xbadc0ffe
static void check_stack(void)
......@@ -161,8 +162,63 @@ static void check_stack(void)
}
}
#ifdef CONFIG_CHECK_RESET
static void check_reset(void)
{
extern void _reset_handler(void); /* user to reset again */
/* static variables to preserve stack (for dumping it) */
static uint32_t *p, *save;
/* _endram is set to ENDRAM_MAGIC after calling this function */
if (_endram != ENDRAM_MAGIC)
return;
/* Before calling anything, find the beginning of the stack */
p = &_endram + 1;
while (!*p)
p++;
p = (void *)((unsigned long)p & ~0xf); /* align */
/* Copy it to the beginning of the stack, then reset pointers */
save = &_endram;
while (p <= &_fstack)
*save++ = *p++;
p -= (save - &_endram);
save = &_endram;
/* Ok, now init the devices so we can printf and delay */
sdb_find_devices();
uart_init();
timer_init(1);
pp_printf("\nWarning: the CPU was reset\nStack trace:\n");
while (p < &_fstack) {
pp_printf("%08x: %08x %08x %08x %08x\n",
(int)p, save[0], save[1], save[2], save[3]);
p += 4;
save += 4;
}
pp_printf("Rebooting in 1 second\n\n\n");
timer_delay(1000);
/* Zero the stack and start over (so we dump correctly next time) */
for (p = &_endram; p < &_fstack; p++)
*p = 0;
_endram = 0;
_reset_handler();
}
# else /* no CONFIG_CHECK_RESET */
static void check_reset(void) {}
#endif
int main(void)
{
check_reset();
wrc_extra_debug = 1;
wrc_ui_mode = UI_SHELL_MODE;
_endram = ENDRAM_MAGIC;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment