Merge pull request #830 from bernd-herzog/error_handling

added runtime error details to guru meditation
This commit is contained in:
gullradriel 2023-03-13 15:50:27 +01:00 committed by GitHub
commit 023ee2a6f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 295 additions and 80 deletions

View File

@ -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

View File

@ -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 <ch.h>
#include <hal.h>
#include <string>
#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<link_register_value_here>" firmware/application/application.elf
// or for M4
// # arm-none-eabi-gdb --batch --eval-command="x/8i 0x<link_register_value_here>" firmware/baseband/<image_name_here>.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" */

View File

@ -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__*/

View File

@ -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 ) {

View File

@ -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();

View File

@ -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
)

View File

@ -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<sizeof(shared_memory.m4_panic_msg); i++) {
if( *panic_message == 0 ) {
shared_memory.m4_panic_msg[i] = 0;
} else {
shared_memory.m4_panic_msg[i] = *(panic_message++);
}
}
}
extern "C" {
#if CH_DBG_ENABLED
void port_halt(void) {
// Copy debug panic message to M0 region.
const auto* p = dbg_panic_msg;
for(size_t i=0; i<sizeof(shared_memory.m4_panic_msg); i++) {
if( *p == 0 ) {
shared_memory.m4_panic_msg[i] = 0;
} else {
shared_memory.m4_panic_msg[i] = *(p++);
}
}
port_disable();
runtime_error();
}
#if defined(LPC43XX_M4)
if (dbg_panic_msg == nullptr)
dbg_panic_msg = "system halted";
write_m4_panic_msg(dbg_panic_msg, nullptr);
}
#endif
CH_IRQ_HANDLER(MemManageVector) {
#if CH_DBG_ENABLED
chDbgPanic("MemManage");
@ -103,6 +80,31 @@ CH_IRQ_HANDLER(UsageFaultVector) {
chSysHalt();
#endif
}
CH_IRQ_HANDLER(HardFaultVector) {
#if CH_DBG_ENABLED
regarm_t _saved_lr;
asm volatile ("mov %0, lr" : "=r" (_saved_lr) : : "memory");
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();
write_m4_panic_msg("Hard Fault", ctxp);
port_disable();
while (true);
CH_IRQ_EPILOGUE();
#else
chSysHalt();
#endif
}
}