mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-27 06:32:19 +03:00
DebugTrace, Nextion, BrokerMQTT
This commit is contained in:
287
src/DebugTrace.cpp
Normal file
287
src/DebugTrace.cpp
Normal file
@@ -0,0 +1,287 @@
|
||||
#include "DebugTrace.h"
|
||||
#if defined(RESTART_DEBUG_INFO) && defined(ESP32) && !defined(esp32c3m_4mb)
|
||||
//#ifdef RESTART_DEBUG_INFO
|
||||
__NOINIT_ATTR static re_restart_debug_t _debug_info;
|
||||
|
||||
#include "esp_debug_helpers.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/cpu.h"
|
||||
|
||||
// RU: Размер буфера для конвертации даты и времeни в строку
|
||||
#define CONFIG_FORMAT_STRFTIME_BUFFER_SIZE 32
|
||||
#define CONFIG_FORMAT_STRFTIME_DTS_BUFFER_SIZE 20 // YYYY.MM.DD HH:NN:SS + \n
|
||||
|
||||
// RU: Форматы даты и времени
|
||||
#define CONFIG_FORMAT_DTS "%d.%m.%Y %H:%M:%S"
|
||||
|
||||
void IRAM_ATTR debugHeapUpdate()
|
||||
{
|
||||
_debug_info.heap_total = heap_caps_get_total_size(MALLOC_CAP_DEFAULT);
|
||||
_debug_info.heap_free = heap_caps_get_free_size(MALLOC_CAP_DEFAULT);
|
||||
size_t _new_free_min = heap_caps_get_minimum_free_size(MALLOC_CAP_DEFAULT);
|
||||
if ((_debug_info.heap_free_min == 0) || (_new_free_min < _debug_info.heap_free_min))
|
||||
{
|
||||
_debug_info.heap_free_min = _new_free_min;
|
||||
_debug_info.heap_min_time = time(nullptr);
|
||||
};
|
||||
}
|
||||
|
||||
void IRAM_ATTR debugBacktraceUpdate()
|
||||
{
|
||||
esp_backtrace_frame_t stk_frame;
|
||||
esp_backtrace_get_start(&(stk_frame.pc), &(stk_frame.sp), &(stk_frame.next_pc));
|
||||
_debug_info.backtrace[0] = esp_cpu_process_stack_pc(stk_frame.pc);
|
||||
|
||||
bool corrupted = (esp_stack_ptr_is_sane(stk_frame.sp) &&
|
||||
esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)))
|
||||
? false
|
||||
: true;
|
||||
|
||||
uint8_t i = CONFIG_RESTART_DEBUG_STACK_DEPTH;
|
||||
while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted)
|
||||
{
|
||||
if (!esp_backtrace_get_next_frame(&stk_frame))
|
||||
{
|
||||
corrupted = true;
|
||||
};
|
||||
_debug_info.backtrace[CONFIG_RESTART_DEBUG_STACK_DEPTH - i] = esp_cpu_process_stack_pc(stk_frame.pc);
|
||||
};
|
||||
}
|
||||
|
||||
void IRAM_ATTR debugUpdate()
|
||||
{
|
||||
debugHeapUpdate();
|
||||
debugBacktraceUpdate();
|
||||
}
|
||||
|
||||
extern "C" void __wrap_esp_panic_handler(void *info)
|
||||
{
|
||||
|
||||
debugHeapUpdate();
|
||||
debugBacktraceUpdate();
|
||||
// Call the original panic handler function to finish processing this error (creating a core dump for example...)
|
||||
__real_esp_panic_handler(info);
|
||||
}
|
||||
|
||||
re_restart_debug_t debugGet()
|
||||
{
|
||||
re_restart_debug_t ret;
|
||||
memset(&ret, 0, sizeof(re_restart_debug_t));
|
||||
esp_reset_reason_t esp_reason = esp_reset_reason();
|
||||
if ((esp_reason != ESP_RST_UNKNOWN) && (esp_reason != ESP_RST_POWERON))
|
||||
{
|
||||
uint8_t i = CONFIG_RESTART_DEBUG_STACK_DEPTH;
|
||||
ret = _debug_info;
|
||||
if (_debug_info.heap_total > heap_caps_get_total_size(MALLOC_CAP_DEFAULT))
|
||||
{
|
||||
memset(&ret, 0, sizeof(re_restart_debug_t));
|
||||
};
|
||||
};
|
||||
memset(&_debug_info, 0, sizeof(re_restart_debug_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define CONFIG_MESSAGE_TG_VERSION_DEF "! Устройство запущено\n\nИмя устройства: %s\nПричина перезапуска: %s\nCPU0: %s\nCPU1: %s"
|
||||
#define CONFIG_MESSAGE_TG_VERSION_HEAP "! Устройство аварийно перезапущено !\n\nИмя устройства: %s\nПричина перезапуска: %s\nCPU0: %s\nCPU1: %s\nHEAP: %s"
|
||||
#define CONFIG_MESSAGE_TG_VERSION_TRACE "! Устройство аварийно перезапущено !\n\nИмя устройства: %s\nПричина перезапуска: %s\nCPU0: %s\nCPU1: %s\nHEAP: %s\nTRACE: %s"
|
||||
|
||||
char *malloc_stringf(const char *format, ...)
|
||||
{
|
||||
char *ret = nullptr;
|
||||
if (format != nullptr)
|
||||
{
|
||||
// get the list of arguments
|
||||
va_list args1, args2;
|
||||
va_start(args1, format);
|
||||
va_copy(args2, args1);
|
||||
// calculate length of resulting string
|
||||
int len = vsnprintf(nullptr, 0, format, args1);
|
||||
va_end(args1);
|
||||
// allocate memory for string
|
||||
if (len > 0)
|
||||
{
|
||||
#if USE_ESP_MALLOC
|
||||
ret = (char *)esp_malloc(len + 1);
|
||||
#else
|
||||
ret = (char *)malloc(len + 1);
|
||||
#endif
|
||||
if (ret != nullptr)
|
||||
{
|
||||
memset(ret, 0, len + 1);
|
||||
vsnprintf(ret, len + 1, format, args2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rlog_e(tagHEAP, "Failed to format string: out of memory!");
|
||||
};
|
||||
};
|
||||
va_end(args2);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *statesGetDebugHeap(re_restart_debug_t *debug)
|
||||
{
|
||||
if ((debug->heap_total > 0) && (debug->heap_total > debug->heap_free))
|
||||
{
|
||||
struct tm timeinfo;
|
||||
localtime_r(&debug->heap_min_time, &timeinfo);
|
||||
char time_buffer[CONFIG_FORMAT_STRFTIME_DTS_BUFFER_SIZE];
|
||||
memset(&time_buffer, 0, CONFIG_FORMAT_STRFTIME_DTS_BUFFER_SIZE);
|
||||
strftime(time_buffer, CONFIG_FORMAT_STRFTIME_DTS_BUFFER_SIZE, CONFIG_FORMAT_DTS, &timeinfo);
|
||||
|
||||
double heapTotal = (double)debug->heap_total / 1024;
|
||||
double heapFree = (double)debug->heap_free / 1024;
|
||||
double heapFreeMin = (double)debug->heap_free_min / 1024;
|
||||
|
||||
return malloc_stringf("Total %.1fkB ; Free %.1fkB (%.1f%%) ; FreeMin %.1fkB (%.1f%%) %s",
|
||||
heapTotal,
|
||||
heapFree, 100.0 * (heapFree / heapTotal),
|
||||
heapFreeMin, 100.0 * (heapFreeMin / heapTotal), time_buffer);
|
||||
};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char *statesGetDebugTrace(re_restart_debug_t *debug)
|
||||
{
|
||||
char *backtrace = nullptr;
|
||||
char *item = nullptr;
|
||||
char *temp = nullptr;
|
||||
for (uint8_t i = 0; i < CONFIG_RESTART_DEBUG_STACK_DEPTH; i++)
|
||||
{
|
||||
if (debug->backtrace[i] != 0)
|
||||
{
|
||||
item = malloc_stringf("0x%08x", debug->backtrace[i]);
|
||||
if (item)
|
||||
{
|
||||
if (backtrace)
|
||||
{
|
||||
temp = backtrace;
|
||||
backtrace = malloc_stringf("%s %s", temp, item);
|
||||
free(item);
|
||||
free(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
backtrace = item;
|
||||
};
|
||||
item = nullptr;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
};
|
||||
return backtrace;
|
||||
}
|
||||
|
||||
void printDebugTrace()
|
||||
{
|
||||
// esp_register_shutdown_handler(debugUpdate);
|
||||
re_restart_debug_t debug = debugGet();
|
||||
char *debug_heap = statesGetDebugHeap(&debug);
|
||||
char *debug_trace = nullptr;
|
||||
if (debug_heap)
|
||||
{
|
||||
debug_trace = statesGetDebugTrace(&debug);
|
||||
if (debug_trace)
|
||||
{
|
||||
Serial.printf(CONFIG_MESSAGE_TG_VERSION_TRACE,
|
||||
jsonReadStr(settingsFlashJson, F("name")), ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str(),
|
||||
debug_heap, debug_trace);
|
||||
// free(debug_trace);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.printf(CONFIG_MESSAGE_TG_VERSION_HEAP,
|
||||
jsonReadStr(settingsFlashJson, F("name")), ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str(),
|
||||
debug_heap);
|
||||
};
|
||||
// free(debug_heap);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Serial.println("DEVICE START");
|
||||
Serial.printf(CONFIG_MESSAGE_TG_VERSION_DEF,
|
||||
jsonReadStr(settingsFlashJson, F("name")), ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sendDebugTraceAndFreeMemory( bool postMsg)
|
||||
{
|
||||
// esp_register_shutdown_handler(debugUpdate);
|
||||
re_restart_debug_t debug = debugGet();
|
||||
char *debug_heap = statesGetDebugHeap(&debug);
|
||||
char *debug_trace = nullptr;
|
||||
|
||||
if (debug_heap)
|
||||
{
|
||||
if (isNetworkActive() && postMsg)
|
||||
{
|
||||
debug_trace = statesGetDebugTrace(&debug);
|
||||
if (debug_trace)
|
||||
{
|
||||
if (tlgrmItem)
|
||||
{
|
||||
char *msg;
|
||||
msg = malloc_stringf(CONFIG_MESSAGE_TG_VERSION_TRACE,
|
||||
jsonReadStr(settingsFlashJson, F("name")).c_str(), ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str(),
|
||||
debug_heap, debug_trace);
|
||||
tlgrmItem->sendTelegramMsg(false, String(msg));
|
||||
tlgrmItem->sendTelegramMsg(false, String("Подробности /helpDebug в Telegram_v2"));
|
||||
free(msg);
|
||||
}
|
||||
free(debug_trace);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Serial.printf(CONFIG_MESSAGE_TG_VERSION_HEAP,
|
||||
jsonReadStr(settingsFlashJson, F("name")), ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str(),
|
||||
debug_heap);
|
||||
*/
|
||||
if (tlgrmItem)
|
||||
{
|
||||
char *msg;
|
||||
msg = malloc_stringf(CONFIG_MESSAGE_TG_VERSION_HEAP,
|
||||
jsonReadStr(settingsFlashJson, F("name")).c_str(), ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str(),
|
||||
debug_heap);
|
||||
tlgrmItem->sendTelegramMsg(false, String(msg));
|
||||
tlgrmItem->sendTelegramMsg(false, String("Подробности /helpDebug в Telegram_v2"));
|
||||
free(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(debug_heap);
|
||||
}
|
||||
/* else
|
||||
{
|
||||
// Serial.println("DEVICE START");
|
||||
// Serial.printf(CONFIG_MESSAGE_TG_VERSION_DEF,
|
||||
// FIRMWARE_VERSION, ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str());
|
||||
if (tlgrmItem && isNetworkActive())
|
||||
{
|
||||
char *msg;
|
||||
msg = malloc_stringf(CONFIG_MESSAGE_TG_VERSION_DEF,
|
||||
WiFi.localIP().toString(), FIRMWARE_VERSION, ESP_getResetReason().c_str(), ESP32GetResetReason(0).c_str(), ESP32GetResetReason(1).c_str());
|
||||
tlgrmItem->sendTelegramMsg(false, String(msg));
|
||||
free(msg);
|
||||
}
|
||||
};*/
|
||||
}
|
||||
|
||||
#else
|
||||
void printDebugTrace() {}
|
||||
void sendDebugTraceAndFreeMemory(bool) {}
|
||||
void IRAM_ATTR debugUpdate() {}
|
||||
extern "C" void __wrap_esp_panic_handler(void *info)
|
||||
{
|
||||
// Call the original panic handler function to finish processing this error (creating a core dump for example...)
|
||||
__real_esp_panic_handler(info);
|
||||
}
|
||||
#endif // RESTART_DEBUG_INFO
|
||||
Reference in New Issue
Block a user