#include #include #include #include "RemoteDebugging.h" #include "freertos/FreeRTOS.h" #include "esp_debug_helpers.h" #include "esp_core_dump.h" #define TAG "RemoteDebugging" std::string RemoteDebugging::get_task_manager() { std::string out; out.resize(1024); vTaskGetRunTimeStats(out.data()); out.resize(425); return out; } std::string RemoteDebugging::get_logs() { std::string out; for (const auto& log : log_buffer->peek_drain()) { out.append(log); } out.resize(800); return out; } std::string RemoteDebugging::get_coredump_summary() { esp_err_t check_err = esp_core_dump_image_check(); if (check_err == ESP_ERR_NOT_FOUND) { ESP_LOGW(TAG, "No core dump found in flash."); return "No core dump found in flash.\n"; } if (check_err == ESP_ERR_NOT_SUPPORTED) { ESP_LOGW(TAG, "Core dump partition not found."); return "Core dump partition not found.\n"; } if (check_err == ESP_ERR_INVALID_CRC) { ESP_LOGW(TAG, "Core dump flash is corrupted (checksum mismatch)"); return "Core dump in flash is corrupted (checksum mismatch).\n"; } if (check_err != ESP_OK) { ESP_LOGW(TAG, "Core dump check failed: 0x%x", check_err); char buf[80]; snprintf(buf, sizeof(buf), "Core dump check failed: 0x%x\n", check_err); return buf; } esp_core_dump_summary_t *summary = static_cast( malloc(sizeof(esp_core_dump_summary_t))); if (!summary) { ESP_LOGW(TAG, "Failed to allocate memory for core dump summary"); return "Failed to allocate memory for core dump summary.\n"; } std::string out; esp_err_t err = esp_core_dump_get_summary(summary); if (err != ESP_OK) { ESP_LOGW(TAG, "Failed to get core dump summary: 0x%x", err); char buf[64]; snprintf(buf, sizeof(buf), "Failed to get core dump summary: 0x%x\n", err); out = std::string(buf); free(summary); return out; } // Panic reason char reason[200] = {}; if (esp_core_dump_get_panic_reason(reason, sizeof(reason)) == ESP_OK) { ESP_LOGI(TAG, "Panic reason: %s", reason); out += "Panic reason: "; out += reason; out += "\n"; } // Faulting task and PC char line[128]; snprintf(line, sizeof(line), "Faulting task: %s (TCB: 0x%08" PRIx32 ")\n" "Exception PC: 0x%08" PRIx32 "\n" "Exception cause: %" PRIu32 " vaddr: 0x%08" PRIx32 "\n", summary->exc_task, summary->exc_tcb, summary->exc_pc, summary->ex_info.exc_cause, summary->ex_info.exc_vaddr); out += line; ESP_LOGI(TAG, "%s", line); // Backtrace out += "Backtrace:"; for (uint32_t i = 0; i < summary->exc_bt_info.depth && i < 16; i++) { char bt_entry[16]; snprintf(bt_entry, sizeof(bt_entry), " 0x%08" PRIx32, summary->exc_bt_info.bt[i]); out += bt_entry; } if (summary->exc_bt_info.corrupted) { out += " (corrupted)"; } out += "\n"; ESP_LOGI(TAG, "Backtrace: %s", out); free(summary); return out; } void RemoteDebugging::register_calls(MessagingInterface &messaging_interface) { messaging_interface.register_function(2, [](const uint8_t *parameters, size_t parameter_size, Writer& writer) { auto out = get_task_manager(); std::vector vec(out.begin(), out.end()); writer.write(vec); }); messaging_interface.register_function(3, [](const uint8_t *parameters, size_t parameter_size, Writer& writer) { auto out = get_logs(); std::vector vec(out.begin(), out.end()); writer.write(vec); }); messaging_interface.register_function(69, [](const uint8_t *parameters, size_t parameter_size, Writer& writer) { uint8_t out = esp_reset_reason(); std::vector vec{out}; }); messaging_interface.register_function(13, [](const uint8_t *parameters, size_t parameter_size, Writer& writer) { auto out = get_coredump_summary(); std::vector vec(out.begin(), out.end()); writer.write(vec); }); } int RemoteDebugging::custom_log_write(const char *data, va_list args) { char tmp[512]; va_list copy; va_copy(copy, args); int len = vsnprintf(tmp, sizeof(tmp), data, copy); va_end(copy); std::string str; str.assign(tmp, len); std::cout << str; log_buffer->push(std::move(str)); return 0; }