From b6011a777b08328e14e676246b3a1f3399bb5e33 Mon Sep 17 00:00:00 2001 From: Bernd Herzog Date: Mon, 13 Mar 2023 15:03:40 +0100 Subject: [PATCH] added runtime error details to guru meditation --- firmware/application/CMakeLists.txt | 2 +- firmware/application/debug.cpp | 209 ++++++++++++++++++++++++ firmware/application/debug.hpp | 31 ++++ firmware/application/event_m0.cpp | 36 +--- firmware/application/event_m0.hpp | 1 - firmware/baseband/CMakeLists.txt | 2 +- firmware/{common => baseband}/debug.cpp | 94 +++++------ firmware/{common => baseband}/debug.hpp | 0 8 files changed, 295 insertions(+), 80 deletions(-) create mode 100644 firmware/application/debug.cpp create mode 100644 firmware/application/debug.hpp rename firmware/{common => baseband}/debug.cpp (58%) rename firmware/{common => baseband}/debug.hpp (100%) diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 27b2dd476..760c8d94b 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -125,7 +125,7 @@ set(CPPSRC ${COMMON}/cpld_max5.cpp ${COMMON}/cpld_update.cpp ${COMMON}/cpld_xilinx.cpp - ${COMMON}/debug.cpp + debug.cpp ${COMMON}/ert_packet.cpp ${COMMON}/event.cpp ${COMMON}/gcc.cpp diff --git a/firmware/application/debug.cpp b/firmware/application/debug.cpp new file mode 100644 index 000000000..5dee51327 --- /dev/null +++ b/firmware/application/debug.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "debug.hpp" + +#include +#include +#include + +#include "ui_painter.hpp" +#include "portapack.hpp" +#include "ui_font_fixed_8x16.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) { + ui::Painter painter; + ui::Style style_default { + .font = ui::font::fixed_8x16, + .background = ui::Color::black(), + .foreground = ui::Color::white() + }; + + painter.fill_rectangle( + { 0, 0, portapack::display.width(), portapack::display.height() }, + ui::Color::red() + ); + + constexpr int border = 8; + painter.fill_rectangle( + { border, border, portapack::display.width() - (border * 2), portapack::display.height() - (border * 2) }, + ui::Color::black() + ); + + // NOTE: in situations like a hard fault it seems not possible to write strings longer than 16 characters. + painter.draw_string({ 48, 24 }, style_default, "M? Guru"); + painter.draw_string({ 48 + 8*8, 24 }, style_default, "Meditation"); + + if (source == CORTEX_M0) + painter.draw_string({ 48 + 8, 24 }, style_default, "0"); + + if (source == CORTEX_M4) + painter.draw_string({ 48 + 8, 24 }, style_default, "4"); + + painter.draw_string({ 15, 55 }, style_default, "Hint: "); + painter.draw_string({ 15 + 8*8, 55 }, style_default, hint); +} + +void draw_guru_meditation(uint8_t source, const char *hint) { + if(error_shown == false){ + error_shown = true; + draw_guru_meditation_header(source, hint); + } + + if (source == CORTEX_M0) + runtime_error(hackrf::one::led_rx); + + if (source == CORTEX_M4) + runtime_error(hackrf::one::led_tx); +} + +void draw_guru_meditation(uint8_t source, const char *hint, struct extctx *ctxp) { + if(error_shown == false) + { + error_shown = true; + draw_guru_meditation_header(source, hint); + + if (ctxp != nullptr) { + int i = 0; + draw_line(80 + i++ * 20, "r0:", ctxp->r0); + draw_line(80 + i++ * 20, "r1:", ctxp->r1); + draw_line(80 + i++ * 20, "r2:", ctxp->r2); + draw_line(80 + i++ * 20, "r3:", ctxp->r3); + draw_line(80 + i++ * 20, "r12:", ctxp->r12); + + // NOTE: run for M0 + // # arm-none-eabi-gdb --batch --eval-command="x/8i 0x" firmware/application/application.elf + // or for M4 + // # arm-none-eabi-gdb --batch --eval-command="x/8i 0x" firmware/baseband/.elf + // to see whats causing the fault. + draw_line(80 + i++ * 20, "lr:", ctxp->lr_thd); + draw_line(80 + i++ * 20, "pc:", ctxp->pc); + } + } + + if (source == CORTEX_M0) + runtime_error(hackrf::one::led_rx); + + if (source == CORTEX_M4) + runtime_error(hackrf::one::led_tx); +} + +void draw_line(int32_t y_offset, const char *label, regarm_t value){ + ui::Painter painter; + ui::Style style_default { + .font = ui::font::fixed_8x16, + .background = ui::Color::black(), + .foreground = ui::Color::white() + }; + + 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); +} + +void runtime_error(LED led) { + led.off(); + + while(true) { + volatile size_t n = 1000000U; + while(n--); + led.toggle(); + } +} + +extern "C" { +#if CH_DBG_ENABLED +void port_halt(void) { + port_disable(); + + if (dbg_panic_msg == nullptr) + dbg_panic_msg = "system halted"; + + draw_guru_meditation(CORTEX_M0, dbg_panic_msg); +} +#endif + +CH_IRQ_HANDLER(MemManageVector) { +#if CH_DBG_ENABLED + chDbgPanic("MemManage"); +#else + chSysHalt(); +#endif +} + +CH_IRQ_HANDLER(BusFaultVector) { +#if CH_DBG_ENABLED + chDbgPanic("BusFault"); +#else + chSysHalt(); +#endif +} + +CH_IRQ_HANDLER(UsageFaultVector) { +#if CH_DBG_ENABLED + chDbgPanic("UsageFault"); +#else + chSysHalt(); +#endif +} + +CH_IRQ_HANDLER(HardFaultVector) { +#if CH_DBG_ENABLED + CH_IRQ_PROLOGUE(); + struct extctx *ctxp; + port_lock_from_isr(); + + if ((uint32_t)_saved_lr & 0x04) + ctxp = (struct extctx *)__get_PSP(); + else + ctxp = (struct extctx *)__get_MSP(); + + port_disable(); + draw_guru_meditation(CORTEX_M0, "Hard Fault", ctxp); + + CH_IRQ_EPILOGUE(); +#else + chSysHalt(); +#endif +} + +} /* extern "C" */ diff --git a/firmware/application/debug.hpp b/firmware/application/debug.hpp new file mode 100644 index 000000000..8b203d6c7 --- /dev/null +++ b/firmware/application/debug.hpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#include "hackrf_gpio.hpp" + +extern void draw_guru_meditation(uint8_t, const char *); +extern void draw_guru_meditation(uint8_t, const char *, struct extctx *); + +#endif/*__DEBUG_H__*/ diff --git a/firmware/application/event_m0.cpp b/firmware/application/event_m0.cpp index d15df9fe9..6c3dfff24 100644 --- a/firmware/application/event_m0.cpp +++ b/firmware/application/event_m0.cpp @@ -23,6 +23,7 @@ #include "portapack.hpp" #include "portapack_persistent_memory.hpp" +#include "debug.hpp" #include "sd_card.hpp" #include "rtc_time.hpp" @@ -141,37 +142,10 @@ eventmask_t EventDispatcher::wait() { void EventDispatcher::dispatch(const eventmask_t events) { if( shared_memory.m4_panic_msg[0] != 0 ) { - halt = true; - } - - if( halt ) { - if( shared_memory.m4_panic_msg[0] != 0 ) { - painter.fill_rectangle( - { 0, 0, portapack::display.width(), portapack::display.height() }, - ui::Color::red() - ); - - constexpr int border = 8; - painter.fill_rectangle( - { border, border, portapack::display.width() - (border * 2), portapack::display.height() - (border * 2) }, - ui::Color::black() - ); - - painter.draw_string({ 48, 24 }, top_widget->style(), "M4 Guru Meditation"); - - shared_memory.m4_panic_msg[sizeof(shared_memory.m4_panic_msg) - 1] = 0; - const std::string message = shared_memory.m4_panic_msg; - const int x_offset = (portapack::display.width() - (message.size() * 8)) / 2; - constexpr int y_offset = (portapack::display.height() - 16) / 2; - painter.draw_string( - { x_offset, y_offset }, - top_widget->style(), - message - ); - - shared_memory.m4_panic_msg[0] = 0; - } - return; + 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]); } if( events & EVT_MASK_APPLICATION ) { diff --git a/firmware/application/event_m0.hpp b/firmware/application/event_m0.hpp index 8a43c933d..69ac14fbe 100644 --- a/firmware/application/event_m0.hpp +++ b/firmware/application/event_m0.hpp @@ -98,7 +98,6 @@ private: static bool is_running; bool sd_card_present = false; static bool display_sleep; - bool halt = false; bool in_key_event = false; eventmask_t wait(); diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 7a3951234..7d9739a6b 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -139,7 +139,7 @@ set(CPPSRC audio_stats_collector.cpp ${COMMON}/utility.cpp ${COMMON}/chibios_cpp.cpp - ${COMMON}/debug.cpp + debug.cpp ${COMMON}/gcc.cpp tone_gen.cpp ) diff --git a/firmware/common/debug.cpp b/firmware/baseband/debug.cpp similarity index 58% rename from firmware/common/debug.cpp rename to firmware/baseband/debug.cpp index 40e56d461..95c738930 100644 --- a/firmware/common/debug.cpp +++ b/firmware/baseband/debug.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2023 Bernd Herzog * * This file is part of PortaPack. * @@ -26,60 +27,36 @@ #include "portapack_shared_memory.hpp" -#if defined(LPC43XX_M0) -static void debug_indicate_error_init() { - // TODO: Get knowledge of LED GPIO port/bit from shared place. - LPC_GPIO->CLR[2] = (1 << 2); -} +void write_m4_panic_msg(const char *panic_message, struct extctx *ctxp) { + if (ctxp == nullptr) { + shared_memory.bb_data.data[0] = 0; + } + else { + shared_memory.bb_data.data[0] = 1; + memcpy(&shared_memory.bb_data.data[4], ctxp, sizeof(struct extctx)); + } -static void debug_indicate_error_update() { - // Flash RX (yellow) LED to indicate baseband error. - // TODO: Get knowledge of LED GPIO port/bit from shared place. - LPC_GPIO->NOT[2] = (1 << 2); -} -#endif - -#if defined(LPC43XX_M4) -static void debug_indicate_error_init() { - // TODO: Get knowledge of LED GPIO port/bit from shared place. - LPC_GPIO->CLR[2] = (1 << 8); -} - -static void debug_indicate_error_update() { - // Flash TX (red) LED to indicate baseband error. - // TODO: Get knowledge of LED GPIO port/bit from shared place. - LPC_GPIO->NOT[2] = (1 << 8); -} -#endif - -static void runtime_error() { - debug_indicate_error_init(); - - while(true) { - volatile size_t n = 1000000U; - while(n--); - debug_indicate_error_update(); + for(size_t i=0; i