diff --git a/arch/arm/src/arm/up_assert.c b/arch/arm/src/arm/up_assert.c index d706c1bb36c..427799d9876 100644 --- a/arch/arm/src/arm/up_assert.c +++ b/arch/arm/src/arm/up_assert.c @@ -352,6 +352,12 @@ void up_assert(const uint8_t *filename, int lineno) lldbg("Assertion failed at file:%s line: %d\n", filename, lineno); #endif + up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/arm/src/armv6-m/up_assert.c b/arch/arm/src/armv6-m/up_assert.c index 160ced2f991..7b143d81983 100644 --- a/arch/arm/src/armv6-m/up_assert.c +++ b/arch/arm/src/armv6-m/up_assert.c @@ -369,5 +369,10 @@ void up_assert(const uint8_t *filename, int lineno) #endif up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/arm/src/armv7-a/arm_assert.c b/arch/arm/src/armv7-a/arm_assert.c index 3ee0e2ffee6..501119d3ad4 100644 --- a/arch/arm/src/armv7-a/arm_assert.c +++ b/arch/arm/src/armv7-a/arm_assert.c @@ -367,5 +367,10 @@ void up_assert(const uint8_t *filename, int lineno) filename, lineno); #endif up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/arm/src/armv7-m/up_assert.c b/arch/arm/src/armv7-m/up_assert.c index f663802e06f..56c6b445766 100644 --- a/arch/arm/src/armv7-m/up_assert.c +++ b/arch/arm/src/armv7-m/up_assert.c @@ -378,5 +378,10 @@ void up_assert(const uint8_t *filename, int lineno) #endif up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/arm/src/common/up_createstack.c b/arch/arm/src/common/up_createstack.c index a7a49a9b789..460e1b235d1 100644 --- a/arch/arm/src/common/up_createstack.c +++ b/arch/arm/src/common/up_createstack.c @@ -46,6 +46,7 @@ #include #include +#include #include #include "up_arch.h" diff --git a/arch/avr/src/common/up_assert.c b/arch/avr/src/common/up_assert.c index 3ee369767f4..402556eb315 100644 --- a/arch/avr/src/common/up_assert.c +++ b/arch/avr/src/common/up_assert.c @@ -175,6 +175,10 @@ void up_assert(const uint8_t *filename, int lineno) up_dumpstate(); +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + #ifdef CONFIG_ARCH_USBDUMP /* Dump USB trace data */ diff --git a/arch/hc/src/m9s12/m9s12_assert.c b/arch/hc/src/m9s12/m9s12_assert.c index 479dfb00545..efc5d6492a0 100644 --- a/arch/hc/src/m9s12/m9s12_assert.c +++ b/arch/hc/src/m9s12/m9s12_assert.c @@ -337,5 +337,10 @@ void up_assert(const uint8_t *filename, int lineno) #endif up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/mips/src/mips32/up_assert.c b/arch/mips/src/mips32/up_assert.c index f768f5d6af6..29cd6d737d2 100644 --- a/arch/mips/src/mips32/up_assert.c +++ b/arch/mips/src/mips32/up_assert.c @@ -181,5 +181,9 @@ void up_assert(const uint8_t *filename, int lineno) (void)usbtrace_enumerate(assert_tracecallback, NULL); #endif +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/rgmp/src/nuttx.c b/arch/rgmp/src/nuttx.c index dc5478bd2f6..893ee5cc9fa 100644 --- a/arch/rgmp/src/nuttx.c +++ b/arch/rgmp/src/nuttx.c @@ -487,6 +487,10 @@ void up_assert(const uint8_t *filename, int line) { fprintf(stderr, "Assertion failed at file:%s line: %d\n", filename, line); +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, line); +#endif + // in interrupt context or idle task means kernel error // which will stop the OS // if in user space just terminate the task diff --git a/arch/sh/src/common/up_assert.c b/arch/sh/src/common/up_assert.c index 2814083d62a..127f79d5e8d 100644 --- a/arch/sh/src/common/up_assert.c +++ b/arch/sh/src/common/up_assert.c @@ -169,5 +169,9 @@ void up_assert(const uint8_t *filename, int lineno) (void)usbtrace_enumerate(assert_tracecallback, NULL); #endif +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/sim/src/up_head.c b/arch/sim/src/up_head.c index 12893618365..24c76463607 100644 --- a/arch/sim/src/up_head.c +++ b/arch/sim/src/up_head.c @@ -81,5 +81,10 @@ int main(int argc, char **argv, char **envp) void up_assert(const uint8_t *filename, int line) { fprintf(stderr, "Assertion failed at file:%s line: %d\n", filename, line); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, line); +#endif + longjmp(sim_abort, 1); } diff --git a/arch/x86/src/common/up_assert.c b/arch/x86/src/common/up_assert.c index 0288702c3a8..a3b82d3b7f4 100644 --- a/arch/x86/src/common/up_assert.c +++ b/arch/x86/src/common/up_assert.c @@ -299,5 +299,10 @@ void up_assert(const uint8_t *filename, int lineno) #endif up_dumpstate(); + +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/z16/src/common/up_assert.c b/arch/z16/src/common/up_assert.c index 729a10bcbea..55d98535785 100644 --- a/arch/z16/src/common/up_assert.c +++ b/arch/z16/src/common/up_assert.c @@ -181,5 +181,9 @@ void up_assert(void) (void)usbtrace_enumerate(assert_tracecallback, NULL); #endif +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/arch/z80/src/common/up_assert.c b/arch/z80/src/common/up_assert.c index 1ae825e4cea..be886dc44db 100644 --- a/arch/z80/src/common/up_assert.c +++ b/arch/z80/src/common/up_assert.c @@ -180,5 +180,9 @@ void up_assert(void) (void)usbtrace_enumerate(assert_tracecallback, NULL); #endif +#ifdef CONFIG_BOARD_CRASHDUMP + board_crashdump(up_getsp(), g_readytorun.head, filename, lineno); +#endif + _up_assert(EXIT_FAILURE); } diff --git a/configs/Kconfig b/configs/Kconfig index a3f04406c9e..58583c015ab 100644 --- a/configs/Kconfig +++ b/configs/Kconfig @@ -1043,6 +1043,31 @@ config ARCH_BOARD_CUSTOM_DIR to some location outside of the NuttX source tree (like "~/projects/myboard"). +config BOARD_CRASHDUMP + bool "Enable Board level logging of crash dumps" + default n + ---help--- + If selected up_asseert will call out to board_crashdump, in the case + of an assertion failure, prior to calling exit. Or in the + case of a hardfault prior to looping indefinitely. board_crashdump + then has a chance to save the state of the machine. + + The purpose of board_crashdump is to save as much information as it can + about the cause of the fault and then most likely reset the system. + + N.B. There is limited system resources that can be used, who knows + what memory is trashed? So all we can expect to do is save the + "machine state" in a place where on the next reset can write it + to more sophisticated storage in a sane operating environment. + +config BOARD_RESET_ON_CRASH + bool "Eanble Board Reset after the crashdump is saved" + default n + depends on BOARD_CRASHDUMP + ---help--- + If selected the board_crashdump should reset the machine after + saveing the state of the machine + config BOARD_CUSTOM_LEDS bool "Custom board LEDs" default n diff --git a/include/nuttx/board.h b/include/nuttx/board.h index 55aa85b60cf..4c9e1731f14 100644 --- a/include/nuttx/board.h +++ b/include/nuttx/board.h @@ -291,4 +291,34 @@ uint8_t board_buttons(void); xcpt_t board_button_irq(int id, xcpt_t irqhandler); #endif +/**************************************************************************** + * Name: board_crashdump + * + * Description: + * If CONFIG_BOARD_CRASHDUMP is selected then up_asseert will call out to + * board_crashdump prior to calling exit in the case of an assertion failure. + * Or in the case of a hardfault looping indefinitely. board_crashdump then + * has a chance to save the state of the machine. The provided + * board_crashdump should save as much information as it can about the cause + * of the fault and then most likely reset the system. + * + * N.B. There are limited system resources that can be used by the provided + * board_crashdump function. The tems from the fact that most critical/fatal + * crashes are because of a hard fault or during interrupt processing. + * In these cases, up_assert is running from the context of an interrupt + * handlerand it is impossible to use any device driver in this context. + * + * Also consider the following: Who knows what state the system is in? Is + * memory trashed? Is the Heap intact? Therefore all we can expect to do in + * board_crashdump is save the "machine state" in a place where on the next + * reset we can write it to more sophisticated storage in a sane operating + * environment. + * + ****************************************************************************/ + +#ifdef CONFIG_BOARD_CRASHDUMP +void board_crashdump(uint32_t currentsp, void *tcb, uint8_t *filename, + int lineno); +#endif + #endif /* __INCLUDE_NUTTX_BOARD_H */