From de937f02d4d4af25da07d42cee7c6402a64069b5 Mon Sep 17 00:00:00 2001 From: Mark Thompson <129641948+NotherNgineer@users.noreply.github.com> Date: Sat, 18 Nov 2023 07:16:56 -0600 Subject: [PATCH] Added Memory Dump app for Debug (#1588) * Add files via upload * Add files via upload * Added single word read/write support * Add files via upload --- firmware/application/apps/ui_debug.cpp | 45 ++++++++++++++++++--- firmware/application/apps/ui_debug.hpp | 56 +++++++++++++++++++++++++- firmware/application/debug.cpp | 31 ++++++++------ firmware/application/debug.hpp | 1 + 4 files changed, 113 insertions(+), 20 deletions(-) diff --git a/firmware/application/apps/ui_debug.cpp b/firmware/application/apps/ui_debug.cpp index eeeefd03..9e689783 100644 --- a/firmware/application/apps/ui_debug.cpp +++ b/firmware/application/apps/ui_debug.cpp @@ -277,14 +277,11 @@ RegistersView::RegistersView( static_cast(title.size()) * 8, 16}); text_title.set(title); - field_write_reg_num.set_value(0); field_write_reg_num.on_change = [this](SymField&) { field_write_data_val.set_value(this->registers_widget.reg_read(field_write_reg_num.to_integer())); field_write_data_val.set_dirty(); }; - field_write_data_val.on_change = [this](SymField&) {}; - const auto value = registers_widget.reg_read(0); field_write_data_val.set_value(value); @@ -450,9 +447,10 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { {"Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav]() { nav.push(); }}, {"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(); }}, - {"Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push(); }}, - {"P.Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push(); }}, + {"Memory Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push(); }}, + {"Memory Usage", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push(); }}, {"Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav]() { nav.push(); }}, + {"Pers. Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push(); }}, //{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push(); } }, {"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav]() { nav.push(); }}, {"Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav]() { nav.push(); }}, @@ -466,6 +464,43 @@ DebugMenuView::DebugMenuView(NavigationView& nav) { set_max_rows(2); // allow wider buttons } +/* DebugMemoryDumpView *********************************************************/ + +DebugMemoryDumpView::DebugMemoryDumpView(NavigationView& nav) { + add_children({ + &button_dump, + &button_read, + &button_write, + &button_done, + &labels, + &field_starting_address, + &field_byte_count, + &field_rw_address, + &field_data_value, + }); + + button_done.on_select = [&nav](Button&) { nav.pop(); }; + + button_dump.on_select = [this](Button&) { + if (field_byte_count.to_integer() != 0) + memory_dump((uint32_t*)field_starting_address.to_integer(), ((uint32_t)field_byte_count.to_integer() + 3) / 4, false); + }; + + button_read.on_select = [this](Button&) { + field_data_value.set_value(*(uint32_t*)field_rw_address.to_integer()); + field_data_value.set_dirty(); + }; + + button_write.set_style(&Styles::red); + button_write.on_select = [this](Button&) { + *(uint32_t*)field_rw_address.to_integer() = (uint32_t)field_data_value.to_integer(); + }; +} + +void DebugMemoryDumpView::focus() { + button_done.focus(); +} + /* DebugPmemView *********************************************************/ DebugPmemView::DebugPmemView(NavigationView& nav) diff --git a/firmware/application/apps/ui_debug.hpp b/firmware/application/apps/ui_debug.hpp index f8f46402..8328a997 100644 --- a/firmware/application/apps/ui_debug.hpp +++ b/firmware/application/apps/ui_debug.hpp @@ -48,8 +48,8 @@ class DebugMemoryView : public View { private: Text text_title{ - {96, 96, 48, 16}, - "Memory", + {72, 96, 96, 16}, + "Memory Usage", }; Text text_label_m0_core_free{ @@ -301,6 +301,58 @@ class DebugControlsView : public View { "Done"}; }; +class DebugMemoryDumpView : public View { + public: + DebugMemoryDumpView(NavigationView& nav); + void focus() override; + std::string title() const override { return "Memory Dump"; }; + + private: + Button button_dump{ + {72, 4 * 16, 96, 24}, + "Dump"}; + + Button button_read{ + {16, 11 * 16, 96, 24}, + "Read"}; + + Button button_write{ + {128, 11 * 16, 96, 24}, + "Write"}; + + Button button_done{ + {128, 240, 96, 24}, + "Done"}; + + Labels labels{ + {{5 * 8, 1 * 16}, "Dump Range to File", Color::yellow()}, + {{0 * 8, 2 * 16}, "Starting Address: 0x", Color::light_grey()}, + {{0 * 8, 3 * 16}, "Byte Count: 0x", Color::light_grey()}, + {{3 * 8, 8 * 16}, "Read/Write Single Word", Color::yellow()}, + {{0 * 8, 9 * 16}, "Memory Address: 0x", Color::light_grey()}, + {{0 * 8, 10 * 16}, "Data Value: 0x", Color::light_grey()}}; + + SymField field_starting_address{ + {20 * 8, 2 * 16}, + 8, + SymField::Type::Hex}; + + SymField field_byte_count{ + {20 * 8, 3 * 16}, + 8, + SymField::Type::Hex}; + + SymField field_rw_address{ + {20 * 8, 9 * 16}, + 8, + SymField::Type::Hex}; + + SymField field_data_value{ + {20 * 8, 10 * 16}, + 8, + SymField::Type::Hex}; +}; + class DebugPmemView : public View { public: DebugPmemView(NavigationView& nav); diff --git a/firmware/application/debug.cpp b/firmware/application/debug.cpp index 57a2281f..d4bf1975 100644 --- a/firmware/application/debug.cpp +++ b/firmware/application/debug.cpp @@ -258,38 +258,43 @@ void draw_stack_dump() { } } -// Disk I/O in this function doesn't work after a fault -// Using the stack while dumping the stack isn't ideal, but hopefully anything imporant is still on the call stack. bool stack_dump() { + uint32_t num_words = &__process_stack_end__ - &__process_stack_base__; + return memory_dump(&__process_stack_base__, num_words, true); +} + +bool memory_dump(uint32_t* addr_start, uint32_t num_words, bool stack_flag) { Painter painter; std::string debug_dir = "DEBUG"; std::filesystem::path filename{}; - File stack_dump_file{}; + File dump_file{}; bool error; std::string str; + uint32_t* addr_end; uint32_t* p; int n{0}; bool data_found{false}; make_new_directory(debug_dir); - filename = next_filename_matching_pattern(debug_dir + "/STACK_DUMP_????.TXT"); + filename = next_filename_matching_pattern(debug_dir + "/" + (stack_flag ? "STACK" : "MEMORY") + "_DUMP_????.TXT"); error = filename.empty(); if (!error) - error = stack_dump_file.create(filename) != 0; + error = 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__; p < &__process_stack_end__; p++) { + addr_end = addr_start + num_words; + for (p = addr_start; p < addr_end; p++) { // skip past unused stack words - if (!data_found) { + if (stack_flag && !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 words " + to_string_dec_uint(stack_space_left)); + auto stack_space_left = p - addr_start; + dump_file.write_line(to_string_hex((uint32_t)addr_start, 8) + ": Unused words " + to_string_dec_uint(stack_space_left)); // align subsequent lines to start on 16-byte boundaries p -= (stack_space_left & 3); @@ -299,20 +304,20 @@ bool stack_dump() { // write address if (n++ == 0) { str = to_string_hex((uint32_t)p, 8) + ":"; - stack_dump_file.write(str.data(), 9); + dump_file.write(str.data(), 9); } // write stack dword str = " " + to_string_hex(*p, 8); - stack_dump_file.write(str.data(), 9); + dump_file.write(str.data(), 9); if (n == 4) { - stack_dump_file.write("\r\n", 2); + dump_file.write("\r\n", 2); n = 0; } } - painter.draw_string({16, 320 - 32}, ui::Styles::green, filename.filename().string() + " dumped!"); + painter.draw_string({0, 320 - 16}, ui::Styles::green, filename.filename().string() + " dumped!"); return true; } diff --git a/firmware/application/debug.hpp b/firmware/application/debug.hpp index 4e0ad8e6..b84e0797 100644 --- a/firmware/application/debug.hpp +++ b/firmware/application/debug.hpp @@ -48,5 +48,6 @@ inline uint32_t get_free_stack_space() { } bool stack_dump(); +bool memory_dump(uint32_t* addr_start, uint32_t num_words, bool stack_flag); #endif /*__DEBUG_H__*/