mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-01-06 13:07:47 +00:00
Add Stack Dump option to debug menu and to GURU meditation fault (#1414)
* Stack dump * Stack dump * Stack dump * Stack dump * Stack dump * Stack dump * Update debug.cpp * Clang * Update debug.cpp * Skip dumping unused bytes of stack
This commit is contained in:
parent
014db9e233
commit
d8930db8af
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "ui_debug.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
@ -406,6 +407,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
|
||||
{"Touch Test", ui::Color::dark_cyan(), &bitmap_icon_notepad, [&nav]() { nav.push<DebugScreenTest>(); }},
|
||||
{"P.Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugPmemView>(); }},
|
||||
{"Debug Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { portapack::persistent_memory::debug_dump(); }},
|
||||
{"M0 Stack Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { stack_dump(); }},
|
||||
//{"Fonts Viewer", ui::Color::dark_cyan(), &bitmap_icon_notepad, [&nav]() { nav.push<DebugFontsView>(); }}, // temporarily disabled to conserve ROM space
|
||||
});
|
||||
set_max_rows(2); // allow wider buttons
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "portapack.hpp"
|
||||
#include "string_format.hpp"
|
||||
#include "ui_styles.hpp"
|
||||
#include "irq_controls.hpp"
|
||||
|
||||
using namespace ui;
|
||||
|
||||
@ -46,7 +47,7 @@ void __debug_log(const std::string& msg) {
|
||||
pg_debug_log->write_entry(msg);
|
||||
}
|
||||
|
||||
void runtime_error(LED);
|
||||
void runtime_error(uint8_t source);
|
||||
std::string number_to_hex_string(uint32_t);
|
||||
void draw_line(int32_t, const char*, regarm_t);
|
||||
static bool error_shown = false;
|
||||
@ -67,8 +68,10 @@ void draw_guru_meditation_header(uint8_t source, const char* hint) {
|
||||
painter.draw_string({48, 24}, Styles::white, "M? Guru");
|
||||
painter.draw_string({48 + 8 * 8, 24}, Styles::white, "Meditation");
|
||||
|
||||
if (source == CORTEX_M0)
|
||||
if (source == CORTEX_M0) {
|
||||
painter.draw_string({48 + 8, 24}, Styles::white, "0");
|
||||
painter.draw_string({12, 320 - 32}, Styles::white, "Press DFU to try Stack Dump");
|
||||
}
|
||||
|
||||
if (source == CORTEX_M4)
|
||||
painter.draw_string({48 + 8, 24}, Styles::white, "4");
|
||||
@ -83,11 +86,7 @@ void draw_guru_meditation(uint8_t source, const char* hint) {
|
||||
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);
|
||||
runtime_error(source);
|
||||
}
|
||||
|
||||
void draw_guru_meditation(uint8_t source, const char* hint, struct extctx* ctxp, uint32_t cfsr = 0) {
|
||||
@ -117,11 +116,7 @@ void draw_guru_meditation(uint8_t source, const char* hint, struct extctx* ctxp,
|
||||
}
|
||||
}
|
||||
|
||||
if (source == CORTEX_M0)
|
||||
runtime_error(hackrf::one::led_rx);
|
||||
|
||||
if (source == CORTEX_M4)
|
||||
runtime_error(hackrf::one::led_tx);
|
||||
runtime_error(source);
|
||||
}
|
||||
|
||||
void draw_line(int32_t y_offset, const char* label, regarm_t value) {
|
||||
@ -131,7 +126,10 @@ void draw_line(int32_t y_offset, const char* label, regarm_t value) {
|
||||
painter.draw_string({15 + 8 * 8, y_offset}, Styles::white, to_string_hex((uint32_t)value, 8));
|
||||
}
|
||||
|
||||
void runtime_error(LED led) {
|
||||
void runtime_error(uint8_t source) {
|
||||
bool dumped{false};
|
||||
LED led = (source == CORTEX_M0) ? hackrf::one::led_rx : hackrf::one::led_tx;
|
||||
|
||||
led.off();
|
||||
|
||||
while (true) {
|
||||
@ -139,9 +137,70 @@ void runtime_error(LED led) {
|
||||
while (n--)
|
||||
;
|
||||
led.toggle();
|
||||
|
||||
// Stack dump is not guaranteed to work in this state, so wait for DFU button press to attempt it
|
||||
if (!dumped && (swizzled_switches() & (1 << (int)Switch::Dfu))) {
|
||||
dumped = true;
|
||||
stack_dump();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Fix this function to work after a fault; might need to write to screen instead or to Flash memory.
|
||||
// Using the stack while dumping the stack isn't ideal, but hopefully anything imporant is still on the call stack.
|
||||
bool stack_dump() {
|
||||
ui::Painter painter{};
|
||||
std::string debug_dir = "DEBUG";
|
||||
std::filesystem::path filename{};
|
||||
File stack_dump_file{};
|
||||
bool error;
|
||||
std::string str;
|
||||
uint32_t* p;
|
||||
int n;
|
||||
bool data_found;
|
||||
|
||||
make_new_directory(debug_dir);
|
||||
filename = next_filename_matching_pattern(debug_dir + "/STACK_DUMP_????.TXT");
|
||||
error = filename.empty();
|
||||
if (!error)
|
||||
error = stack_dump_file.create(filename) != 0;
|
||||
if (error) {
|
||||
painter.draw_string({16, 320 - 32}, ui::Styles::red, "ERROR DUMPING " + filename.filename().string() + "!");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (p = &__process_stack_base__, n = 0, data_found = false; p < &__process_stack_end__; p++) {
|
||||
if (!data_found) {
|
||||
if (*p == CRT0_STACKS_FILL_PATTERN)
|
||||
continue;
|
||||
else {
|
||||
data_found = true;
|
||||
auto stack_space_left = p - &__process_stack_base__;
|
||||
stack_dump_file.write_line(to_string_hex((uint32_t)&__process_stack_base__, 8) + ": Unused bytes " + to_string_dec_uint(stack_space_left * sizeof(uint32_t)));
|
||||
|
||||
// align subsequent lines to start on 16-byte boundaries
|
||||
p -= (stack_space_left & 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (n++ == 0) {
|
||||
str = to_string_hex((uint32_t)p, 8) + ":";
|
||||
stack_dump_file.write(str.data(), 9);
|
||||
}
|
||||
|
||||
str = " " + to_string_hex(*p, 8);
|
||||
stack_dump_file.write(str.data(), 9);
|
||||
|
||||
if (n == 4) {
|
||||
stack_dump_file.write("\r\n", 2);
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
painter.draw_string({16, 320 - 32}, ui::Styles::green, filename.filename().string() + " dumped!");
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#if CH_DBG_ENABLED
|
||||
void port_halt(void) {
|
||||
|
@ -47,4 +47,6 @@ inline uint32_t get_free_stack_space() {
|
||||
return stack_space_left;
|
||||
}
|
||||
|
||||
bool stack_dump();
|
||||
|
||||
#endif /*__DEBUG_H__*/
|
||||
|
@ -139,7 +139,9 @@ static uint8_t switches_raw = 0;
|
||||
// uint8_t rot_b() const { return (raw_ >> 6) & 1; }
|
||||
// uint8_t dfu() const { return (raw_ >> 7) & 1; }};
|
||||
|
||||
static uint8_t swizzle_raw(uint8_t raw) {
|
||||
uint8_t swizzled_switches() {
|
||||
uint8_t raw = io.io_update(touch_pins_configs[touch_phase]);
|
||||
|
||||
return (raw & 0x1F) | // Keep the bottom 5 bits the same.
|
||||
((raw >> 2) & 0x20) | // Shift the DFU bit down to bit 6.
|
||||
((raw << 1) & 0xC0); // Shift the encoder bits up to be 7 & 8.
|
||||
@ -183,7 +185,7 @@ void timer0_callback(GPTDriver* const) {
|
||||
eventmask_t event_mask = 0;
|
||||
if (touch_update()) event_mask |= EVT_MASK_TOUCH;
|
||||
|
||||
switches_raw = swizzle_raw(io.io_update(touch_pins_configs[touch_phase]));
|
||||
switches_raw = swizzled_switches();
|
||||
if (switches_update(switches_raw))
|
||||
event_mask |= EVT_MASK_SWITCHES;
|
||||
|
||||
|
@ -43,6 +43,7 @@ using SwitchesState = std::bitset<6>;
|
||||
using EncoderPosition = uint32_t;
|
||||
|
||||
void controls_init();
|
||||
uint8_t swizzled_switches();
|
||||
SwitchesState get_switches_state();
|
||||
EncoderPosition get_encoder_position();
|
||||
touch::Frame get_touch_frame();
|
||||
|
Loading…
x
Reference in New Issue
Block a user