From 5b1f50e63a1b112a64525fbc591355ee377eb0dc Mon Sep 17 00:00:00 2001 From: Albert Kharisov Date: Fri, 31 Dec 2021 21:32:49 +0400 Subject: [PATCH] Much better crash handling. So wow. * Furi, FuriHal, Desktop: much better crash handling. So wow. * FuriHal: add missing include in FreeRTOSConfig.h Co-authored-by: Aleksandr Kutuzov --- applications/desktop/desktop.c | 4 ++ .../desktop/scenes/desktop_scene_config.h | 1 + .../desktop/scenes/desktop_scene_fault.c | 49 +++++++++++++++++++ core/furi/check.c | 33 ++++++++++--- firmware/targets/f6/Inc/FreeRTOSConfig.h | 3 +- firmware/targets/f6/Src/main.c | 3 +- .../targets/f6/furi-hal/furi-hal-interrupt.c | 14 ++---- firmware/targets/f6/furi-hal/furi-hal-os.c | 3 +- firmware/targets/f6/furi-hal/furi-hal-rtc.c | 8 +++ firmware/targets/f7/Inc/FreeRTOSConfig.h | 3 +- firmware/targets/f7/Src/main.c | 3 +- .../targets/f7/furi-hal/furi-hal-interrupt.c | 14 ++---- firmware/targets/f7/furi-hal/furi-hal-os.c | 3 +- firmware/targets/f7/furi-hal/furi-hal-rtc.c | 8 +++ .../targets/furi-hal-include/furi-hal-rtc.h | 5 ++ lib/ST25RFAL002/platform.c | 1 - 16 files changed, 116 insertions(+), 39 deletions(-) create mode 100644 applications/desktop/scenes/desktop_scene_fault.c diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index 9d4df2a7..5b3640e5 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -176,6 +176,10 @@ int32_t desktop_srv(void* p) { scene_manager_next_scene(desktop->scene_manager, DesktopSceneHwMismatch); } + if(furi_hal_rtc_get_fault_data()) { + scene_manager_next_scene(desktop->scene_manager, DesktopSceneFault); + } + view_dispatcher_run(desktop->view_dispatcher); furi_pubsub_unsubscribe(dolphin_pubsub, dolphin_subscription); furi_pubsub_unsubscribe(storage_pubsub, storage_subscription); diff --git a/applications/desktop/scenes/desktop_scene_config.h b/applications/desktop/scenes/desktop_scene_config.h index 3c325a83..c19fa852 100644 --- a/applications/desktop/scenes/desktop_scene_config.h +++ b/applications/desktop/scenes/desktop_scene_config.h @@ -6,3 +6,4 @@ ADD_SCENE(desktop, first_start, FirstStart) ADD_SCENE(desktop, hw_mismatch, HwMismatch) ADD_SCENE(desktop, pinsetup, PinSetup) ADD_SCENE(desktop, levelup, LevelUp) +ADD_SCENE(desktop, fault, Fault) diff --git a/applications/desktop/scenes/desktop_scene_fault.c b/applications/desktop/scenes/desktop_scene_fault.c new file mode 100644 index 00000000..eec27ec4 --- /dev/null +++ b/applications/desktop/scenes/desktop_scene_fault.c @@ -0,0 +1,49 @@ +#include "../desktop_i.h" + +#define DesktopFaultEventExit 0x00FF00FF + +void desktop_scene_fault_callback(void* context) { + Desktop* desktop = (Desktop*)context; + view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopFaultEventExit); +} + +void desktop_scene_fault_on_enter(void* context) { + Desktop* desktop = (Desktop*)context; + + Popup* popup = desktop->hw_mismatch_popup; + popup_set_context(popup, desktop); + popup_set_header( + popup, + "Flipper crashed\n and was rebooted", + 60, + 14 + STATUS_BAR_Y_SHIFT, + AlignCenter, + AlignCenter); + + char* message = (char*)furi_hal_rtc_get_fault_data(); + popup_set_text(popup, message, 60, 37 + STATUS_BAR_Y_SHIFT, AlignCenter, AlignCenter); + popup_set_callback(popup, desktop_scene_fault_callback); + view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewHwMismatch); +} + +bool desktop_scene_fault_on_event(void* context, SceneManagerEvent event) { + Desktop* desktop = (Desktop*)context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case DesktopFaultEventExit: + scene_manager_previous_scene(desktop->scene_manager); + consumed = true; + break; + default: + break; + } + } + + return consumed; +} + +void desktop_scene_fault_on_exit(void* context) { + furi_hal_rtc_set_fault_data(0); +} diff --git a/core/furi/check.c b/core/furi/check.c index c6c56608..698e32b4 100644 --- a/core/furi/check.c +++ b/core/furi/check.c @@ -1,9 +1,10 @@ #include "check.h" #include "furi-hal-task.h" #include +#include #include -void __furi_print_name(void) { +__attribute__((always_inline)) inline static void __furi_print_name() { if(task_is_isr_context()) { furi_hal_console_puts("[ISR] "); } else { @@ -18,18 +19,34 @@ void __furi_print_name(void) { } } -void __furi_abort(void) { - __disable_irq(); - asm("bkpt 1"); - while(1) { - } +__attribute__((always_inline)) inline static void __furi_halt() { + asm volatile("bkpt 0x00 \n" + "loop: \n" + "wfi \n" + "b loop \n" + : + : + : "memory"); } void furi_crash(const char* message) { + __disable_irq(); + + if(message == NULL) { + message = "Fatal Error"; + } + furi_hal_console_puts("\r\n\033[0;31m[CRASH]"); __furi_print_name(); - furi_hal_console_puts(message ? message : "Programming Error"); + furi_hal_console_puts(message); +#ifdef FURI_DEBUG furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); furi_hal_console_puts("\033[0m\r\n"); - __furi_abort(); + __furi_halt(); +#else + furi_hal_rtc_set_fault_data((uint32_t)message); + furi_hal_console_puts("\r\nRebooting system.\r\n"); + furi_hal_console_puts("\033[0m\r\n"); + NVIC_SystemReset(); +#endif } diff --git a/firmware/targets/f6/Inc/FreeRTOSConfig.h b/firmware/targets/f6/Inc/FreeRTOSConfig.h index 4a031f70..6235a2d4 100644 --- a/firmware/targets/f6/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f6/Inc/FreeRTOSConfig.h @@ -119,7 +119,8 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ /* Normal assert() semantics without relying on the provision of an assert.h header file. */ -#define configASSERT( x ) if ((x) == 0) { taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; ); } +#include +#define configASSERT( x ) if ((x) == 0) { furi_crash("FreeRTOS Assert"); } /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names. */ diff --git a/firmware/targets/f6/Src/main.c b/firmware/targets/f6/Src/main.c index a546086f..44c5013e 100644 --- a/firmware/targets/f6/Src/main.c +++ b/firmware/targets/f6/Src/main.c @@ -30,8 +30,7 @@ int main(void) { } void Error_Handler(void) { - asm("bkpt 1"); - while(1) {} + furi_crash("ErrorHandler"); } #ifdef USE_FULL_ASSERT diff --git a/firmware/targets/f6/furi-hal/furi-hal-interrupt.c b/firmware/targets/f6/furi-hal/furi-hal-interrupt.c index 4ff2bc7b..8e24c488 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-interrupt.c +++ b/firmware/targets/f6/furi-hal/furi-hal-interrupt.c @@ -182,25 +182,19 @@ void NMI_Handler(void) { } void HardFault_Handler(void) { - if ((*(volatile uint32_t *)CoreDebug_BASE) & (1 << 0)) { - __asm("bkpt 1"); - } - while (1) {} + furi_crash("HardFault"); } void MemManage_Handler(void) { - __asm("bkpt 1"); - while (1) {} + furi_crash("MemManage"); } void BusFault_Handler(void) { - __asm("bkpt 1"); - while (1) {} + furi_crash("BusFault"); } void UsageFault_Handler(void) { - __asm("bkpt 1"); - while (1) {} + furi_crash("UsageFault"); } void DebugMon_Handler(void) { diff --git a/firmware/targets/f6/furi-hal/furi-hal-os.c b/firmware/targets/f6/furi-hal/furi-hal-os.c index cd182136..f166c5ec 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-os.c +++ b/firmware/targets/f6/furi-hal/furi-hal-os.c @@ -140,6 +140,5 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) { - asm("bkpt 1"); - while(1) {}; + furi_crash("StackOverflow"); } diff --git a/firmware/targets/f6/furi-hal/furi-hal-rtc.c b/firmware/targets/f6/furi-hal/furi-hal-rtc.c index 45498077..a13913a1 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-rtc.c +++ b/firmware/targets/f6/furi-hal/furi-hal-rtc.c @@ -153,3 +153,11 @@ bool furi_hal_rtc_validate_datetime(FuriHalRtcDateTime* datetime) { return !invalid; } + +void furi_hal_rtc_set_fault_data(uint32_t value) { + furi_hal_rtc_set_register(FuriHalRtcRegisterFaultData, value); +} + +uint32_t furi_hal_rtc_get_fault_data() { + return furi_hal_rtc_get_register(FuriHalRtcRegisterFaultData); +} diff --git a/firmware/targets/f7/Inc/FreeRTOSConfig.h b/firmware/targets/f7/Inc/FreeRTOSConfig.h index 4a031f70..6235a2d4 100644 --- a/firmware/targets/f7/Inc/FreeRTOSConfig.h +++ b/firmware/targets/f7/Inc/FreeRTOSConfig.h @@ -119,7 +119,8 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ /* Normal assert() semantics without relying on the provision of an assert.h header file. */ -#define configASSERT( x ) if ((x) == 0) { taskDISABLE_INTERRUPTS(); asm("bkpt 1"); for( ;; ); } +#include +#define configASSERT( x ) if ((x) == 0) { furi_crash("FreeRTOS Assert"); } /* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names. */ diff --git a/firmware/targets/f7/Src/main.c b/firmware/targets/f7/Src/main.c index a546086f..44c5013e 100644 --- a/firmware/targets/f7/Src/main.c +++ b/firmware/targets/f7/Src/main.c @@ -30,8 +30,7 @@ int main(void) { } void Error_Handler(void) { - asm("bkpt 1"); - while(1) {} + furi_crash("ErrorHandler"); } #ifdef USE_FULL_ASSERT diff --git a/firmware/targets/f7/furi-hal/furi-hal-interrupt.c b/firmware/targets/f7/furi-hal/furi-hal-interrupt.c index 4ff2bc7b..8e24c488 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-interrupt.c +++ b/firmware/targets/f7/furi-hal/furi-hal-interrupt.c @@ -182,25 +182,19 @@ void NMI_Handler(void) { } void HardFault_Handler(void) { - if ((*(volatile uint32_t *)CoreDebug_BASE) & (1 << 0)) { - __asm("bkpt 1"); - } - while (1) {} + furi_crash("HardFault"); } void MemManage_Handler(void) { - __asm("bkpt 1"); - while (1) {} + furi_crash("MemManage"); } void BusFault_Handler(void) { - __asm("bkpt 1"); - while (1) {} + furi_crash("BusFault"); } void UsageFault_Handler(void) { - __asm("bkpt 1"); - while (1) {} + furi_crash("UsageFault"); } void DebugMon_Handler(void) { diff --git a/firmware/targets/f7/furi-hal/furi-hal-os.c b/firmware/targets/f7/furi-hal/furi-hal-os.c index cd182136..f166c5ec 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-os.c +++ b/firmware/targets/f7/furi-hal/furi-hal-os.c @@ -140,6 +140,5 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { } void vApplicationStackOverflowHook(TaskHandle_t xTask, char * pcTaskName) { - asm("bkpt 1"); - while(1) {}; + furi_crash("StackOverflow"); } diff --git a/firmware/targets/f7/furi-hal/furi-hal-rtc.c b/firmware/targets/f7/furi-hal/furi-hal-rtc.c index 45498077..a13913a1 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-rtc.c +++ b/firmware/targets/f7/furi-hal/furi-hal-rtc.c @@ -153,3 +153,11 @@ bool furi_hal_rtc_validate_datetime(FuriHalRtcDateTime* datetime) { return !invalid; } + +void furi_hal_rtc_set_fault_data(uint32_t value) { + furi_hal_rtc_set_register(FuriHalRtcRegisterFaultData, value); +} + +uint32_t furi_hal_rtc_get_fault_data() { + return furi_hal_rtc_get_register(FuriHalRtcRegisterFaultData); +} diff --git a/firmware/targets/furi-hal-include/furi-hal-rtc.h b/firmware/targets/furi-hal-include/furi-hal-rtc.h index 36bf218c..3a00b0da 100644 --- a/firmware/targets/furi-hal-include/furi-hal-rtc.h +++ b/firmware/targets/furi-hal-include/furi-hal-rtc.h @@ -37,6 +37,7 @@ typedef enum { FuriHalRtcRegisterSystem, FuriHalRtcRegisterSystemVersion, FuriHalRtcRegisterLfsFingerprint, + FuriHalRtcRegisterFaultData, } FuriHalRtcRegister; /** Initialize RTC subsystem */ @@ -62,6 +63,10 @@ void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime); bool furi_hal_rtc_validate_datetime(FuriHalRtcDateTime* datetime); +void furi_hal_rtc_set_fault_data(uint32_t value); + +uint32_t furi_hal_rtc_get_fault_data(); + #ifdef __cplusplus } #endif diff --git a/lib/ST25RFAL002/platform.c b/lib/ST25RFAL002/platform.c index a91acf9e..4684af2e 100644 --- a/lib/ST25RFAL002/platform.c +++ b/lib/ST25RFAL002/platform.c @@ -58,7 +58,6 @@ HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t } if(!ret) { - asm("bkpt 1"); return HAL_ERROR; } else { return HAL_OK;