mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-01-07 22:07:39 +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 "ui_debug.hpp"
|
||||||
|
#include "debug.hpp"
|
||||||
|
|
||||||
#include "ch.h"
|
#include "ch.h"
|
||||||
|
|
||||||
@ -406,6 +407,7 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
|
|||||||
{"Touch Test", ui::Color::dark_cyan(), &bitmap_icon_notepad, [&nav]() { nav.push<DebugScreenTest>(); }},
|
{"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>(); }},
|
{"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(); }},
|
{"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
|
//{"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
|
set_max_rows(2); // allow wider buttons
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "portapack.hpp"
|
#include "portapack.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "ui_styles.hpp"
|
#include "ui_styles.hpp"
|
||||||
|
#include "irq_controls.hpp"
|
||||||
|
|
||||||
using namespace ui;
|
using namespace ui;
|
||||||
|
|
||||||
@ -46,7 +47,7 @@ void __debug_log(const std::string& msg) {
|
|||||||
pg_debug_log->write_entry(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);
|
std::string number_to_hex_string(uint32_t);
|
||||||
void draw_line(int32_t, const char*, regarm_t);
|
void draw_line(int32_t, const char*, regarm_t);
|
||||||
static bool error_shown = false;
|
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, 24}, Styles::white, "M? Guru");
|
||||||
painter.draw_string({48 + 8 * 8, 24}, Styles::white, "Meditation");
|
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({48 + 8, 24}, Styles::white, "0");
|
||||||
|
painter.draw_string({12, 320 - 32}, Styles::white, "Press DFU to try Stack Dump");
|
||||||
|
}
|
||||||
|
|
||||||
if (source == CORTEX_M4)
|
if (source == CORTEX_M4)
|
||||||
painter.draw_string({48 + 8, 24}, Styles::white, "4");
|
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);
|
draw_guru_meditation_header(source, hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (source == CORTEX_M0)
|
runtime_error(source);
|
||||||
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, uint32_t cfsr = 0) {
|
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(source);
|
||||||
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) {
|
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));
|
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();
|
led.off();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -139,9 +137,70 @@ void runtime_error(LED led) {
|
|||||||
while (n--)
|
while (n--)
|
||||||
;
|
;
|
||||||
led.toggle();
|
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" {
|
extern "C" {
|
||||||
#if CH_DBG_ENABLED
|
#if CH_DBG_ENABLED
|
||||||
void port_halt(void) {
|
void port_halt(void) {
|
||||||
|
@ -47,4 +47,6 @@ inline uint32_t get_free_stack_space() {
|
|||||||
return stack_space_left;
|
return stack_space_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool stack_dump();
|
||||||
|
|
||||||
#endif /*__DEBUG_H__*/
|
#endif /*__DEBUG_H__*/
|
||||||
|
@ -139,7 +139,9 @@ static uint8_t switches_raw = 0;
|
|||||||
// uint8_t rot_b() const { return (raw_ >> 6) & 1; }
|
// uint8_t rot_b() const { return (raw_ >> 6) & 1; }
|
||||||
// uint8_t dfu() const { return (raw_ >> 7) & 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.
|
return (raw & 0x1F) | // Keep the bottom 5 bits the same.
|
||||||
((raw >> 2) & 0x20) | // Shift the DFU bit down to bit 6.
|
((raw >> 2) & 0x20) | // Shift the DFU bit down to bit 6.
|
||||||
((raw << 1) & 0xC0); // Shift the encoder bits up to be 7 & 8.
|
((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;
|
eventmask_t event_mask = 0;
|
||||||
if (touch_update()) event_mask |= EVT_MASK_TOUCH;
|
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))
|
if (switches_update(switches_raw))
|
||||||
event_mask |= EVT_MASK_SWITCHES;
|
event_mask |= EVT_MASK_SWITCHES;
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ using SwitchesState = std::bitset<6>;
|
|||||||
using EncoderPosition = uint32_t;
|
using EncoderPosition = uint32_t;
|
||||||
|
|
||||||
void controls_init();
|
void controls_init();
|
||||||
|
uint8_t swizzled_switches();
|
||||||
SwitchesState get_switches_state();
|
SwitchesState get_switches_state();
|
||||||
EncoderPosition get_encoder_position();
|
EncoderPosition get_encoder_position();
|
||||||
touch::Frame get_touch_frame();
|
touch::Frame get_touch_frame();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user