From b83f43793c639fac9b3df362a1904d1257d6fd77 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Sat, 18 Mar 2023 22:41:26 +0100 Subject: [PATCH] improved runtime error handling --- firmware/application/debug.cpp | 32 +++++++++++++------------------ firmware/application/debug.hpp | 14 +++++++++++++- firmware/application/event_m0.cpp | 6 +++++- firmware/baseband/debug.cpp | 20 ++++++++++++++----- firmware/baseband/debug.hpp | 21 ++++++++++++++++++++ firmware/common/chibios_cpp.cpp | 10 ++++++++-- 6 files changed, 75 insertions(+), 28 deletions(-) diff --git a/firmware/application/debug.cpp b/firmware/application/debug.cpp index 5dee5132..9621d0ca 100644 --- a/firmware/application/debug.cpp +++ b/firmware/application/debug.cpp @@ -29,13 +29,14 @@ #include "ui_painter.hpp" #include "portapack.hpp" #include "ui_font_fixed_8x16.hpp" +#include "string_format.hpp" void runtime_error(LED); std::string number_to_hex_string(uint32_t); void draw_line(int32_t, const char *, regarm_t); static bool error_shown = false; -extern void draw_guru_meditation_header(uint8_t source, const char *hint) { +void draw_guru_meditation_header(uint8_t source, const char *hint) { ui::Painter painter; ui::Style style_default { .font = ui::font::fixed_8x16, @@ -81,7 +82,7 @@ void draw_guru_meditation(uint8_t source, const char *hint) { runtime_error(hackrf::one::led_tx); } -void draw_guru_meditation(uint8_t source, const char *hint, struct extctx *ctxp) { +void draw_guru_meditation(uint8_t source, const char *hint, struct extctx *ctxp, uint32_t cfsr = 0) { if(error_shown == false) { error_shown = true; @@ -102,6 +103,10 @@ void draw_guru_meditation(uint8_t source, const char *hint, struct extctx *ctxp) // to see whats causing the fault. draw_line(80 + i++ * 20, "lr:", ctxp->lr_thd); draw_line(80 + i++ * 20, "pc:", ctxp->pc); + + // see SCB_CFSR_* in libopencm3/cm3/scb.h for details + if (cfsr != 0) + draw_line(80 + i++ * 20, "cfsr:", (void *)cfsr); } } @@ -121,23 +126,7 @@ void draw_line(int32_t y_offset, const char *label, regarm_t value){ }; painter.draw_string({ 15, y_offset }, style_default, label); - painter.draw_string({ 15 + 8*8, y_offset }, style_default, number_to_hex_string((uint32_t)value)); -} - -std::string number_to_hex_string(uint32_t number){ - char str[16]; - char* p = &str[16]; - do { - p--; - uint32_t digit = number % 16; - number /= 16; - *p = digit>=10 ? 'A' + (digit-10) : '0' + digit; - } while ( number > 0 ); - p--; - *p = 'x'; - p--; - *p = '0'; - return std::string(p, &str[16]-p); + painter.draw_string({ 15 + 8*8, y_offset }, style_default, to_string_hex((uint32_t)value, 8)); } void runtime_error(LED led) { @@ -198,6 +187,11 @@ CH_IRQ_HANDLER(HardFaultVector) { ctxp = (struct extctx *)__get_MSP(); port_disable(); + + auto stack_space_left = get_free_stack_space(); + if (stack_space_left < 16) + draw_guru_meditation(CORTEX_M0, "Stack Overflow", ctxp); + draw_guru_meditation(CORTEX_M0, "Hard Fault", ctxp); CH_IRQ_EPILOGUE(); diff --git a/firmware/application/debug.hpp b/firmware/application/debug.hpp index 8b203d6c..a538d59c 100644 --- a/firmware/application/debug.hpp +++ b/firmware/application/debug.hpp @@ -26,6 +26,18 @@ #include "hackrf_gpio.hpp" extern void draw_guru_meditation(uint8_t, const char *); -extern void draw_guru_meditation(uint8_t, const char *, struct extctx *); +extern void draw_guru_meditation(uint8_t, const char *, struct extctx *, uint32_t); + +extern uint32_t __process_stack_base__; +extern uint32_t __process_stack_end__; +#define CRT0_STACKS_FILL_PATTERN 0x55555555 + +inline uint32_t get_free_stack_space(){ + uint32_t *p; + for (p = &__process_stack_base__; *p == CRT0_STACKS_FILL_PATTERN && p < &__process_stack_end__; p++); + auto stack_space_left = p - &__process_stack_base__; + + return stack_space_left; +} #endif/*__DEBUG_H__*/ diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index 6c3dfff2..583c4004 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -145,7 +145,11 @@ void EventDispatcher::dispatch(const eventmask_t events) { if (shared_memory.bb_data.data[0] == 0) draw_guru_meditation(CORTEX_M4, shared_memory.m4_panic_msg); else - draw_guru_meditation(CORTEX_M4, shared_memory.m4_panic_msg, (struct extctx *)&shared_memory.bb_data.data[4]); + draw_guru_meditation( + CORTEX_M4, + shared_memory.m4_panic_msg, + (struct extctx *)&shared_memory.bb_data.data[8], + *(uint32_t *)&shared_memory.bb_data.data[4]); } if( events & EVT_MASK_APPLICATION ) { diff --git a/firmware/baseband/debug.cpp b/firmware/baseband/debug.cpp index 95c73893..f69f4053 100644 --- a/firmware/baseband/debug.cpp +++ b/firmware/baseband/debug.cpp @@ -33,7 +33,8 @@ void write_m4_panic_msg(const char *panic_message, struct extctx *ctxp) { } else { shared_memory.bb_data.data[0] = 1; - memcpy(&shared_memory.bb_data.data[4], ctxp, sizeof(struct extctx)); + *((uint32_t *)&shared_memory.bb_data.data[4]) = SCB->CFSR; + memcpy(&shared_memory.bb_data.data[8], ctxp, sizeof(struct extctx)); } for(size_t i=0; i + +extern uint32_t __process_stack_base__; +extern uint32_t __process_stack_end__; +#define CRT0_STACKS_FILL_PATTERN 0x55555555 + +inline uint32_t get_free_stack_space(){ + uint32_t *p; + for (p = &__process_stack_base__; *p == CRT0_STACKS_FILL_PATTERN && p < &__process_stack_end__; p++); + auto stack_space_left = p - &__process_stack_base__; + + return stack_space_left; +} + +#define HALT_IF_DEBUGGING() \ + do { \ + if ((*(volatile uint32_t *)0xE000EDF0) & (1 << 0)) { \ + __asm__ __volatile__("bkpt 1"); \ + } \ +} while (0) + #endif/*__DEBUG_H__*/ diff --git a/firmware/common/chibios_cpp.cpp b/firmware/common/chibios_cpp.cpp index d148ca1d..97ca30b1 100644 --- a/firmware/common/chibios_cpp.cpp +++ b/firmware/common/chibios_cpp.cpp @@ -26,11 +26,17 @@ #include void* operator new(size_t size) { - return chHeapAlloc(0x0, size); + void *p = chHeapAlloc(0x0, size); + if (p == nullptr) + chDbgPanic("Out of Memory"); + return p; } void* operator new[](size_t size) { - return chHeapAlloc(0x0, size); + void *p = chHeapAlloc(0x0, size); + if (p == nullptr) + chDbgPanic("Out of Memory"); + return p; } void operator delete(void* p) noexcept {