mirror of
https://github.com/arendst/Tasmota.git
synced 2026-07-27 20:05:46 +00:00
Add define USE_ESP8266_DEBUG_HEAP to control (#24777)
This commit is contained in:
@@ -1354,6 +1354,7 @@
|
||||
//#define DEBUG_TASMOTA_DRIVER // Enable driver debug messages
|
||||
//#define DEBUG_TASMOTA_SENSOR // Enable sensor debug messages
|
||||
//#define USE_DEBUG_DRIVER // Use xdrv_99_debug.ino providing commands CpuChk, CfgXor, CfgDump, CfgPeek and CfgPoke
|
||||
//#define USE_ESP8266_DEBUG_HEAP // Add heap fragmentation display support. Needs build_flags -DUMM_STATS_FULL and -DUMM_INLINE_METRICS too (+2k5 code)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Profiling features
|
||||
|
||||
@@ -2804,12 +2804,21 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
||||
TasAutoMutex mutex((SemaphoreHandle_t *)&TasmotaGlobal.log_buffer_mutex);
|
||||
#endif // ESP32
|
||||
|
||||
char mxtime[25]; // "13:45:21.999-123/12 " or with fragmentation suffix
|
||||
char mxtime[21]; // "13:45:21.999-123/12 "
|
||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%02d" D_HOUR_MINUTE_SEPARATOR "%02d" D_MINUTE_SECOND_SEPARATOR "%02d.%03d"),
|
||||
RtcTime.hour, RtcTime.minute, RtcTime.second, RtcMillis());
|
||||
if (Settings->flag5.show_heap_with_timestamp) {
|
||||
#ifdef ESP8266
|
||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%s-%03d"),
|
||||
mxtime, ESP_getFreeHeap1024());
|
||||
#ifdef USE_ESP8266_DEBUG_HEAP
|
||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%s/%02d"),
|
||||
mxtime, ESP_getHeapFragmentation());
|
||||
#endif // USE_ESP8266_DEBUG_HEAP
|
||||
#else // ESP32
|
||||
snprintf_P(mxtime, sizeof(mxtime), PSTR("%s-%03d/%02d"),
|
||||
mxtime, ESP_getFreeHeap1024(), ESP_getHeapFragmentation());
|
||||
#endif // ESP8266 or ESP32
|
||||
}
|
||||
strcat(mxtime, " ");
|
||||
|
||||
|
||||
@@ -17,10 +17,6 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef ESP8266
|
||||
#include <umm_malloc/umm_malloc_cfg.h>
|
||||
#endif
|
||||
|
||||
const char kTasmotaCommands[] PROGMEM = "|" // No prefix
|
||||
// SetOptions synonyms
|
||||
D_SO_WIFINOSLEEP "|"
|
||||
@@ -905,11 +901,15 @@ void CmndStatus(void)
|
||||
|
||||
if (0 == XdrvMailbox.index) { payload = 0; } // All status messages in one MQTT message (status0)
|
||||
|
||||
while (payload > MAX_STATUS) {
|
||||
#ifdef ESP8266
|
||||
if (payload > MAX_STATUS && 44 != payload) { return; } // {"Command":"Error"}
|
||||
#else
|
||||
if (payload > MAX_STATUS) { return; } // {"Command":"Error"}
|
||||
#endif
|
||||
#ifdef USE_ESP8266_DEBUG_HEAP
|
||||
if (44 == payload) { break; }
|
||||
#endif // USE_ESP8266_DEBUG_HEAP
|
||||
#endif // ESP8266
|
||||
return; // {"Command":"Error"}
|
||||
}
|
||||
|
||||
if (!Settings->flag.mqtt_enabled && (6 == payload)) { return; } // SetOption3 - Enable MQTT
|
||||
if (!TasmotaGlobal.energy_driver && (9 == payload)) { return; }
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
@@ -1027,37 +1027,28 @@ void CmndStatus(void)
|
||||
|
||||
// Status 4 - StatusMEM
|
||||
if ((0 == payload) || (4 == payload)) {
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\""
|
||||
#ifdef ESP32
|
||||
D_JSON_STACKLOWMARK "\":%d,\"" D_JSON_PSRMAXMEMORY "\":%d,\"" D_JSON_PSRFREEMEMORY "\":%d,\""
|
||||
#endif // ESP32
|
||||
D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d"
|
||||
",\"" D_JSON_FLASHCHIPID "\":\"%06X\""
|
||||
",\"FlashFrequency\":%d,\"" D_JSON_FLASHMODE "\":\"" D_TASMOTA_FLASHMODE "\""),
|
||||
ESP_getSketchSize()/1024, ESP_getFreeSketchSpace()/1024, ESP_getFreeHeap1024(),
|
||||
#ifdef ESP32
|
||||
uxTaskGetStackHighWaterMark(nullptr) / 1024, ESP.getPsramSize()/1024, ESP.getFreePsram()/1024,
|
||||
ESP_getFlashChipMagicSize()/1024, ESP.getFlashChipSize()/1024
|
||||
#endif // ESP32
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d"),
|
||||
ESP_getSketchSize()/1024, ESP_getFreeSketchSpace()/1024, ESP_getFreeHeap1024());
|
||||
|
||||
#ifdef ESP8266
|
||||
#ifdef USE_ESP8266_DEBUG_HEAP
|
||||
ResponseAppendHeapInfo();
|
||||
#endif // USE_ESP8266_DEBUG_HEAP
|
||||
#else // ESP32
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_STACKLOWMARK "\":%d,\"" D_JSON_PSRMAXMEMORY "\":%d,\"" D_JSON_PSRFREEMEMORY "\":%d"),
|
||||
uxTaskGetStackHighWaterMark(nullptr) / 1024, ESP.getPsramSize()/1024, ESP.getFreePsram()/1024);
|
||||
#endif // ESP8266 or ESP32
|
||||
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d"
|
||||
",\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"FlashFrequency\":%d"
|
||||
",\"" D_JSON_FLASHMODE "\":\"" D_TASMOTA_FLASHMODE "\""),
|
||||
#ifdef ESP8266
|
||||
ESP_getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024
|
||||
#endif // ESP8266
|
||||
, ESP_getFlashChipId()
|
||||
, ESP_getFlashChipSpeed()/1000000);
|
||||
#ifdef ESP8266
|
||||
ESP_UpdateHeapMetrics();
|
||||
ResponseAppend_P(PSTR(",\"MaxFreeBlock\":%d,\"Frag\":%d"),
|
||||
(uint32_t)ESP_getMaxAllocHeap()/1024,
|
||||
(int32_t)ESP_getHeapFragmentation());
|
||||
#if defined(UMM_INLINE_METRICS) || defined(UMM_STATS_FULL)
|
||||
ResponseAppend_P(PSTR(",\"OomCount\":%d"), (uint32_t)umm_get_oom_count());
|
||||
#endif
|
||||
#ifdef UMM_STATS_FULL
|
||||
ResponseAppend_P(PSTR(",\"HeapLwm\":%d,\"MaxAllocSz\":%d"),
|
||||
(uint32_t)umm_free_heap_size_lw_min()/1024,
|
||||
(uint32_t)umm_get_max_alloc_size());
|
||||
#endif // UMM_STATS_FULL
|
||||
#endif // ESP8266
|
||||
#else // ESP32
|
||||
ESP_getFlashChipMagicSize()/1024, ESP.getFlashChipSize()/1024
|
||||
#endif // ESP8266 or ESP32
|
||||
, ESP_getFlashChipId(), ESP_getFlashChipSpeed()/1000000);
|
||||
|
||||
ResponseAppendFeatures();
|
||||
XsnsDriverState();
|
||||
ResponseAppend_P(PSTR(",\"Sensors\":"));
|
||||
@@ -1207,16 +1198,14 @@ void CmndStatus(void)
|
||||
#endif
|
||||
|
||||
#ifdef ESP8266
|
||||
// Status 44 - trigger umm heap dump to serial + OOM test
|
||||
// ESP8266-only heap diagnostic. Chosen above the standard range
|
||||
// (0-MAX_STATUS = 0-13) and below the reserved value 99 (full status dump).
|
||||
#ifdef USE_ESP8266_DEBUG_HEAP
|
||||
// Status 44 - Trigger umm heap dump to serial + OOM test
|
||||
if (44 == payload) {
|
||||
umm_info(nullptr, true);
|
||||
ESP_HeapOomTest();
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS "44\":{\"HeapDump\":\"serial\"}}"));
|
||||
SerialHeapDump();
|
||||
Response_P(PSTR("{\"" D_CMND_STATUS "44\":{\"HeapDump\":\"Serial output only\"}}"));
|
||||
CmndStatusResponse(44);
|
||||
return;
|
||||
}
|
||||
#endif // USE_ESP8266_DEBUG_HEAP
|
||||
#endif // ESP8266
|
||||
|
||||
CmndStatusResponse(99);
|
||||
|
||||
@@ -106,20 +106,28 @@ float ESP_getFreeHeap1024(void) {
|
||||
}
|
||||
*/
|
||||
|
||||
#ifndef USE_ESP8266_DEBUG_HEAP
|
||||
|
||||
uint32_t ESP_getMaxAllocHeap(void) {
|
||||
return ESP.getFreeHeap();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// umm_max_block_size() requires a heap walk (ICACHE_FLASH_ATTR, IRQs disabled).
|
||||
// Cache the result; refresh once per second via ESP_UpdateHeapMetrics().
|
||||
// umm_max_block_size() and umm_free_heap_size_lw() are available unconditionally
|
||||
// (UMM_INFO and UMM_STATS are hardcoded active in umm_malloc_cfg.h).
|
||||
static uint32_t s_umm_max_free_block = 0;
|
||||
|
||||
void ESP_UpdateHeapMetrics(void) {
|
||||
s_umm_max_free_block = umm_max_block_size();
|
||||
}
|
||||
|
||||
uint32_t ESP_getMaxAllocHeap(void) {
|
||||
return s_umm_max_free_block ? s_umm_max_free_block : ESP.getFreeHeap();
|
||||
}
|
||||
|
||||
void ESP_UpdateHeapMetrics(void) {
|
||||
s_umm_max_free_block = umm_max_block_size(); // ESP.getMaxFreeBlockSize();
|
||||
}
|
||||
|
||||
int32_t ESP_getHeapFragmentation(void) {
|
||||
// Same formula as ESP32: 100 - (largestFreeBlock * 100 / totalFree)
|
||||
uint32_t free_heap = umm_free_heap_size_lw(); // ISR-safe, no heap walk
|
||||
@@ -128,7 +136,10 @@ int32_t ESP_getHeapFragmentation(void) {
|
||||
return (frag < 0) ? 0 : frag;
|
||||
}
|
||||
|
||||
void ESP_HeapOomCheck(void) {
|
||||
void ESP_HeapUsageUpdate(void) {
|
||||
if (Settings->flag5.show_heap_with_timestamp) {
|
||||
ESP_UpdateHeapMetrics();
|
||||
}
|
||||
#if defined(UMM_INLINE_METRICS) || defined(UMM_STATS_FULL)
|
||||
static size_t oom_prev = 0;
|
||||
size_t oom = UMM_OOM_COUNT;
|
||||
@@ -139,12 +150,33 @@ void ESP_HeapOomCheck(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void ESP_HeapOomTest(void) {
|
||||
void ResponseAppendHeapInfo(void) {
|
||||
ESP_UpdateHeapMetrics();
|
||||
ResponseAppend_P(PSTR(",\"MaxFree\":%d,\"Frag\":%d"),
|
||||
(uint32_t)ESP_getMaxAllocHeap()/1024,
|
||||
(int32_t)ESP_getHeapFragmentation());
|
||||
#if defined(UMM_INLINE_METRICS) || defined(UMM_STATS_FULL)
|
||||
ResponseAppend_P(PSTR(",\"OomCount\":%d"), (uint32_t)umm_get_oom_count());
|
||||
#endif
|
||||
#ifdef UMM_STATS_FULL
|
||||
ResponseAppend_P(PSTR(",\"HeapLwm\":%d,\"MaxAllocSz\":%d"),
|
||||
(uint32_t)umm_free_heap_size_lw_min()/1024,
|
||||
(uint32_t)umm_get_max_alloc_size());
|
||||
#endif // UMM_STATS_FULL
|
||||
}
|
||||
|
||||
void SerialHeapDump(void) {
|
||||
// Status 44 - trigger umm heap dump to serial + OOM test
|
||||
// ESP8266-only heap diagnostic. Chosen above the standard range
|
||||
// (0-MAX_STATUS = 0-13) and below the reserved value 99 (full status dump).
|
||||
umm_info(nullptr, true);
|
||||
#if defined(UMM_INLINE_METRICS) || defined(UMM_STATS_FULL)
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("OOM: count %u (test-trigger)"), (uint32_t)umm_get_oom_count());
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // USE_ESP8266_DEBUG_HEAP
|
||||
|
||||
uint32_t ESP_getFlashChipId(void) {
|
||||
return ESP.getFlashChipId();
|
||||
}
|
||||
@@ -349,4 +381,4 @@ extern "C" void __wrap_sntp_stop(void) {
|
||||
// Prevent lwIP SNTP client from stopping on WiFi disconnects and causing timeout list corruption
|
||||
}
|
||||
|
||||
#endif // ESP8266
|
||||
#endif // ESP8266
|
||||
@@ -1128,11 +1128,10 @@ void PerformEverySecond(void)
|
||||
TasmotaGlobal.uptime++;
|
||||
|
||||
#ifdef ESP8266
|
||||
if (Settings->flag5.show_heap_with_timestamp) {
|
||||
ESP_UpdateHeapMetrics();
|
||||
}
|
||||
ESP_HeapOomCheck();
|
||||
#endif
|
||||
#ifdef USE_ESP8266_DEBUG_HEAP
|
||||
ESP_HeapUsageUpdate();
|
||||
#endif // USE_ESP8266_DEBUG_HEAP
|
||||
#endif // ESP8266
|
||||
|
||||
if (POWER_CYCLE_TIME == TasmotaGlobal.uptime) {
|
||||
UpdateQuickPowerCycle(false);
|
||||
|
||||
Reference in New Issue
Block a user