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
This commit is contained in:
Mark Thompson 2023-11-18 07:16:56 -06:00 committed by GitHub
parent 2c0446e83d
commit de937f02d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 113 additions and 20 deletions

View File

@ -277,14 +277,11 @@ RegistersView::RegistersView(
static_cast<int>(title.size()) * 8, 16}); static_cast<int>(title.size()) * 8, 16});
text_title.set(title); text_title.set(title);
field_write_reg_num.set_value(0);
field_write_reg_num.on_change = [this](SymField&) { 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_value(this->registers_widget.reg_read(field_write_reg_num.to_integer()));
field_write_data_val.set_dirty(); field_write_data_val.set_dirty();
}; };
field_write_data_val.on_change = [this](SymField&) {};
const auto value = registers_widget.reg_read(0); const auto value = registers_widget.reg_read(0);
field_write_data_val.set_value(value); 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<DebugControlsView>(); }}, {"Buttons Test", ui::Color::dark_cyan(), &bitmap_icon_controls, [&nav]() { nav.push<DebugControlsView>(); }},
{"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(); }}, {"M0 Stack Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { stack_dump(); }},
{"Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugMemoryView>(); }}, {"Memory Dump", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugMemoryDumpView>(); }},
{"P.Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugPmemView>(); }}, {"Memory Usage", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugMemoryView>(); }},
{"Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav]() { nav.push<DebugPeripheralsMenuView>(); }}, {"Peripherals", ui::Color::dark_cyan(), &bitmap_icon_peripherals, [&nav]() { nav.push<DebugPeripheralsMenuView>(); }},
{"Pers. Memory", ui::Color::dark_cyan(), &bitmap_icon_memory, [&nav]() { nav.push<DebugPmemView>(); }},
//{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } }, //{ "Radio State", ui::Color::white(), nullptr, [&nav](){ nav.push<NotImplementedView>(); } },
{"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav]() { nav.push<SDCardDebugView>(); }}, {"SD Card", ui::Color::dark_cyan(), &bitmap_icon_sdcard, [&nav]() { nav.push<SDCardDebugView>(); }},
{"Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav]() { nav.push<TemperatureView>(); }}, {"Temperature", ui::Color::dark_cyan(), &bitmap_icon_temperature, [&nav]() { nav.push<TemperatureView>(); }},
@ -466,6 +464,43 @@ DebugMenuView::DebugMenuView(NavigationView& nav) {
set_max_rows(2); // allow wider buttons 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::DebugPmemView(NavigationView& nav) DebugPmemView::DebugPmemView(NavigationView& nav)

View File

@ -48,8 +48,8 @@ class DebugMemoryView : public View {
private: private:
Text text_title{ Text text_title{
{96, 96, 48, 16}, {72, 96, 96, 16},
"Memory", "Memory Usage",
}; };
Text text_label_m0_core_free{ Text text_label_m0_core_free{
@ -301,6 +301,58 @@ class DebugControlsView : public View {
"Done"}; "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 { class DebugPmemView : public View {
public: public:
DebugPmemView(NavigationView& nav); DebugPmemView(NavigationView& nav);

View File

@ -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() { 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; Painter painter;
std::string debug_dir = "DEBUG"; std::string debug_dir = "DEBUG";
std::filesystem::path filename{}; std::filesystem::path filename{};
File stack_dump_file{}; File dump_file{};
bool error; bool error;
std::string str; std::string str;
uint32_t* addr_end;
uint32_t* p; uint32_t* p;
int n{0}; int n{0};
bool data_found{false}; bool data_found{false};
make_new_directory(debug_dir); 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(); error = filename.empty();
if (!error) if (!error)
error = stack_dump_file.create(filename) != 0; error = dump_file.create(filename) != 0;
if (error) { if (error) {
painter.draw_string({16, 320 - 32}, ui::Styles::red, "ERROR DUMPING " + filename.filename().string() + "!"); painter.draw_string({16, 320 - 32}, ui::Styles::red, "ERROR DUMPING " + filename.filename().string() + "!");
return false; 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 // skip past unused stack words
if (!data_found) { if (stack_flag && !data_found) {
if (*p == CRT0_STACKS_FILL_PATTERN) if (*p == CRT0_STACKS_FILL_PATTERN)
continue; continue;
else { else {
data_found = true; data_found = true;
auto stack_space_left = p - &__process_stack_base__; auto stack_space_left = p - addr_start;
stack_dump_file.write_line(to_string_hex((uint32_t)&__process_stack_base__, 8) + ": Unused words " + to_string_dec_uint(stack_space_left)); 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 // align subsequent lines to start on 16-byte boundaries
p -= (stack_space_left & 3); p -= (stack_space_left & 3);
@ -299,20 +304,20 @@ bool stack_dump() {
// write address // write address
if (n++ == 0) { if (n++ == 0) {
str = to_string_hex((uint32_t)p, 8) + ":"; str = to_string_hex((uint32_t)p, 8) + ":";
stack_dump_file.write(str.data(), 9); dump_file.write(str.data(), 9);
} }
// write stack dword // write stack dword
str = " " + to_string_hex(*p, 8); str = " " + to_string_hex(*p, 8);
stack_dump_file.write(str.data(), 9); dump_file.write(str.data(), 9);
if (n == 4) { if (n == 4) {
stack_dump_file.write("\r\n", 2); dump_file.write("\r\n", 2);
n = 0; 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; return true;
} }

View File

@ -48,5 +48,6 @@ inline uint32_t get_free_stack_space() {
} }
bool stack_dump(); bool stack_dump();
bool memory_dump(uint32_t* addr_start, uint32_t num_words, bool stack_flag);
#endif /*__DEBUG_H__*/ #endif /*__DEBUG_H__*/