diff --git a/hal/inc/core_hal.h b/hal/inc/core_hal.h index 454aa91b57..f514f92275 100644 --- a/hal/inc/core_hal.h +++ b/hal/inc/core_hal.h @@ -179,6 +179,10 @@ typedef struct runtime_info_t { uint16_t flags; /* reserved, set to 0. */ uint32_t freeheap; /* Amount of guaranteed heap memory available. */ uint32_t system_version; + uint32_t total_init_heap; + uint32_t total_heap; + uint32_t max_used_heap; // The "highwater mark" for allocated space—that is, the maximum amount of space that was ever allocated. + uint32_t user_static_ram; } runtime_info_t; uint32_t HAL_Core_Runtime_Info(runtime_info_t* info, void* reserved); diff --git a/hal/src/stm32f2xx/core_hal_stm32f2xx.c b/hal/src/stm32f2xx/core_hal_stm32f2xx.c index 1f959c7d9e..9cac823c89 100644 --- a/hal/src/stm32f2xx/core_hal_stm32f2xx.c +++ b/hal/src/stm32f2xx/core_hal_stm32f2xx.c @@ -59,6 +59,8 @@ #include "wlan_hal.h" #endif +extern char link_heap_location, link_heap_location_end; + #define STOP_MODE_EXIT_CONDITION_PIN 0x01 #define STOP_MODE_EXIT_CONDITION_RTC 0x02 @@ -1239,6 +1241,21 @@ uint32_t HAL_Core_Runtime_Info(runtime_info_t* info, void* reserved) struct mallinfo heapinfo = mallinfo(); // fordblks The total number of bytes in free blocks. info->freeheap = heapinfo.fordblks; + if (offsetof(runtime_info_t, total_init_heap) + sizeof(info->total_init_heap) <= info->size) { + info->total_init_heap = (uint32_t)(&link_heap_location_end - &link_heap_location); + } + + if (offsetof(runtime_info_t, total_heap) + sizeof(info->total_heap) <= info->size) { + info->total_heap = heapinfo.arena; + } + + if (offsetof(runtime_info_t, max_used_heap) + sizeof(info->max_used_heap) <= info->size) { + info->max_used_heap = heapinfo.usmblks; + } + + if (offsetof(runtime_info_t, user_static_ram) + sizeof(info->user_static_ram) <= info->size) { + info->user_static_ram = info->total_init_heap - info->total_heap; + } return 0; } diff --git a/services/inc/diagnostics.h b/services/inc/diagnostics.h index eb9ea4dad2..f950a355b8 100644 --- a/services/inc/diagnostics.h +++ b/services/inc/diagnostics.h @@ -45,6 +45,8 @@ constexpr const char* DIAG_NAME_CLOUD_DISCONNECTS = "cloud:disconn"; constexpr const char* DIAG_NAME_CLOUD_REPEATED_MESSAGES = "coap:resend"; constexpr const char* DIAG_NAME_CLOUD_UNACKNOWLEDGED_MESSAGES = "coap:unack"; constexpr const char* DIAG_NAME_CLOUD_RATE_LIMITED_EVENTS = "pub:limit"; +constexpr const char* DIAG_NAME_SYSTEM_TOTAL_RAM = "sys:tram"; +constexpr const char* DIAG_NAME_SYSTEM_USED_RAM = "sys:uram"; #endif @@ -72,6 +74,8 @@ typedef enum diag_id { DIAG_ID_CLOUD_REPEATED_MESSAGES = 21, // coap:resend DIAG_ID_CLOUD_UNACKNOWLEDGED_MESSAGES = 22, // coap:unack DIAG_ID_CLOUD_RATE_LIMITED_EVENTS = 20, // pub:throttle + DIAG_ID_SYSTEM_TOTAL_RAM = 25, // sys:tram + DIAG_ID_SYSTEM_USED_RAM = 26, // sys:uram DIAG_ID_USER = 32768 // Base value for application-specific source IDs } diag_id; diff --git a/system/src/main.cpp b/system/src/main.cpp index e5956cfae2..cc8aa7860d 100644 --- a/system/src/main.cpp +++ b/system/src/main.cpp @@ -548,12 +548,46 @@ class UptimeDiagnosticData: public AbstractIntegerDiagnosticData { } }; +class RunTimeInfoDiagnosticData: public AbstractIntegerDiagnosticData { +public: + typedef IntType(*func_t)(const runtime_info_t&); + RunTimeInfoDiagnosticData(uint16_t id, const char* name, func_t f) : + AbstractIntegerDiagnosticData(id, name), + f_(f) { + } + + virtual int get(IntType& val) override { + runtime_info_t info = {0}; + info.size = sizeof(info); + if (HAL_Core_Runtime_Info(&info, nullptr) == 0) { + val = f_(info); + return SYSTEM_ERROR_NONE; + } + return SYSTEM_ERROR_UNKNOWN; + } + +private: + func_t f_; +}; + // Certain HAL events can be generated before app_setup_and_loop() is called. Using constructor of a // global variable allows to register a handler for HAL events early HALEventHandler g_halEventHandler; UptimeDiagnosticData g_uptimeDiagData; +RunTimeInfoDiagnosticData g_totalRamDiagData(DIAG_ID_SYSTEM_TOTAL_RAM, DIAG_NAME_SYSTEM_TOTAL_RAM, + [](const runtime_info_t& info) -> RunTimeInfoDiagnosticData::IntType { + return info.total_init_heap; + } +); + +RunTimeInfoDiagnosticData g_usedRamDiagData(DIAG_ID_SYSTEM_USED_RAM, DIAG_NAME_SYSTEM_USED_RAM, + [](const runtime_info_t& info) -> RunTimeInfoDiagnosticData::IntType { + return (info.total_init_heap - info.freeheap); + } +); + } // namespace /*******************************************************************************