diff --git a/mongoose.c b/mongoose.c index 3b0f1d13..af495f92 100644 --- a/mongoose.c +++ b/mongoose.c @@ -7290,6 +7290,12 @@ static void mg_mdash_rpc_get_info(struct mg_rpc_req *r) { MG_ESC("crash"), mg_print_crash_record); } +static void mg_mdash_rpc_mem_stats(struct mg_rpc_req *r) { + mg_rpc_ok(r, "{%m:%zu,%m:%zu}", // + MG_ESC("stack_used"), (size_t) MG_HEALTH_STACK_USED, // + MG_ESC("heap_used"), (size_t) MG_HEALTH_HEAP_USED); +} + static void mg_mdash_rpc_ota_begin(struct mg_rpc_req *r) { size_t total = (size_t) mg_json_get_long(r->frame, "$.params.size", -1); if (mg_ota_begin(total)) { @@ -7335,6 +7341,7 @@ void mg_mdash_init(struct mg_mgr *mgr) { MG_INFO(("Initialising mdash agent, key [%s]", MG_MDASH_KEY)); mg_rpc_add(&mgr->rpcs, mg_str("RPC.List"), mg_rpc_list, NULL); mg_rpc_add(&mgr->rpcs, mg_str("Sys.GetInfo"), mg_mdash_rpc_get_info, NULL); + mg_rpc_add(&mgr->rpcs, mg_str("Sys.MemStats"), mg_mdash_rpc_mem_stats, NULL); mg_rpc_add(&mgr->rpcs, mg_str("OTA.Begin"), mg_mdash_rpc_ota_begin, NULL); mg_rpc_add(&mgr->rpcs, mg_str("OTA.Write"), mg_mdash_rpc_ota_write, NULL); mg_rpc_add(&mgr->rpcs, mg_str("OTA.End"), mg_mdash_rpc_ota_end, NULL); diff --git a/mongoose.h b/mongoose.h index 251aaa20..41756fb3 100644 --- a/mongoose.h +++ b/mongoose.h @@ -4414,6 +4414,23 @@ void mg_ota_poll(struct mg_mgr *); +// Memory usage in bytes. Override in mongoose_config.h for the target. +#ifndef MG_HEALTH_STACK_USED +#define MG_HEALTH_STACK_USED 0 +#endif + +#ifndef MG_HEALTH_STACK_TOTAL +#define MG_HEALTH_STACK_TOTAL 0 +#endif + +#ifndef MG_HEALTH_HEAP_USED +#define MG_HEALTH_HEAP_USED 0 +#endif + +#ifndef MG_HEALTH_HEAP_TOTAL +#define MG_HEALTH_HEAP_TOTAL 0 +#endif + #ifndef MG_HEALTH_MAGIC #define MG_HEALTH_MAGIC {'M', 'G', 'H', '3'} // '3' is the layout version #endif diff --git a/src/health.h b/src/health.h index 3304732f..541d7b34 100644 --- a/src/health.h +++ b/src/health.h @@ -5,6 +5,23 @@ #include "arch.h" #include "printf.h" +// Memory usage in bytes. Override in mongoose_config.h for the target. +#ifndef MG_HEALTH_STACK_USED +#define MG_HEALTH_STACK_USED 0 +#endif + +#ifndef MG_HEALTH_STACK_TOTAL +#define MG_HEALTH_STACK_TOTAL 0 +#endif + +#ifndef MG_HEALTH_HEAP_USED +#define MG_HEALTH_HEAP_USED 0 +#endif + +#ifndef MG_HEALTH_HEAP_TOTAL +#define MG_HEALTH_HEAP_TOTAL 0 +#endif + #ifndef MG_HEALTH_MAGIC #define MG_HEALTH_MAGIC {'M', 'G', 'H', '3'} // '3' is the layout version #endif diff --git a/src/mdash.c b/src/mdash.c index 8b14ccba..244b01b8 100644 --- a/src/mdash.c +++ b/src/mdash.c @@ -105,6 +105,12 @@ static void mg_mdash_rpc_get_info(struct mg_rpc_req *r) { MG_ESC("crash"), mg_print_crash_record); } +static void mg_mdash_rpc_mem_stats(struct mg_rpc_req *r) { + mg_rpc_ok(r, "{%m:%zu,%m:%zu}", // + MG_ESC("stack_used"), (size_t) MG_HEALTH_STACK_USED, // + MG_ESC("heap_used"), (size_t) MG_HEALTH_HEAP_USED); +} + static void mg_mdash_rpc_ota_begin(struct mg_rpc_req *r) { size_t total = (size_t) mg_json_get_long(r->frame, "$.params.size", -1); if (mg_ota_begin(total)) { @@ -150,6 +156,7 @@ void mg_mdash_init(struct mg_mgr *mgr) { MG_INFO(("Initialising mdash agent, key [%s]", MG_MDASH_KEY)); mg_rpc_add(&mgr->rpcs, mg_str("RPC.List"), mg_rpc_list, NULL); mg_rpc_add(&mgr->rpcs, mg_str("Sys.GetInfo"), mg_mdash_rpc_get_info, NULL); + mg_rpc_add(&mgr->rpcs, mg_str("Sys.MemStats"), mg_mdash_rpc_mem_stats, NULL); mg_rpc_add(&mgr->rpcs, mg_str("OTA.Begin"), mg_mdash_rpc_ota_begin, NULL); mg_rpc_add(&mgr->rpcs, mg_str("OTA.Write"), mg_mdash_rpc_ota_write, NULL); mg_rpc_add(&mgr->rpcs, mg_str("OTA.End"), mg_mdash_rpc_ota_end, NULL); diff --git a/tutorials/stm32/nucleo-h723zg/minimal/hal.c b/tutorials/stm32/nucleo-h723zg/minimal/hal.c index 22175a26..94991dc6 100644 --- a/tutorials/stm32/nucleo-h723zg/minimal/hal.c +++ b/tutorials/stm32/nucleo-h723zg/minimal/hal.c @@ -43,15 +43,15 @@ __attribute__((weak)) int _fstat(int fd, struct stat *st) { } extern unsigned char _end[]; // End of data section, start of heap. See link.ld +extern unsigned char _estack[]; // Initial stack pointer. See link.ld static unsigned char *s_current_heap_end = _end; -size_t hal_ram_used(void) { - return (size_t) (s_current_heap_end - _end); +size_t hal_get_heap(void) { + return (size_t) ((uintptr_t) s_current_heap_end - (uintptr_t) _end); } -size_t hal_ram_free(void) { - unsigned char endofstack; - return (size_t) (&endofstack - s_current_heap_end); +size_t hal_get_stack(void) { + return (size_t) ((uintptr_t) _estack - (uintptr_t) __get_MSP()); } void *_sbrk(int incr) { diff --git a/tutorials/stm32/nucleo-h723zg/minimal/hal.h b/tutorials/stm32/nucleo-h723zg/minimal/hal.h index 4fef7c79..895f0939 100644 --- a/tutorials/stm32/nucleo-h723zg/minimal/hal.h +++ b/tutorials/stm32/nucleo-h723zg/minimal/hal.h @@ -15,8 +15,8 @@ extern bool hal_timer_expired(volatile uint64_t *t, uint64_t prd, uint64_t now); extern uint64_t hal_get_tick(void); -extern size_t hal_ram_free(void); -extern size_t hal_ram_used(void); +extern size_t hal_get_heap(void); // Heap bytes reserved through _sbrk() +extern size_t hal_get_stack(void); // Stack bytes currently used (MSP) extern uint32_t SystemCoreClock; #define BIT(x) (1UL << (x)) diff --git a/tutorials/stm32/nucleo-h723zg/minimal/main.c b/tutorials/stm32/nucleo-h723zg/minimal/main.c index d6a954f3..04e1fc0c 100644 --- a/tutorials/stm32/nucleo-h723zg/minimal/main.c +++ b/tutorials/stm32/nucleo-h723zg/minimal/main.c @@ -78,9 +78,9 @@ static void http_ev_handler(struct mg_connection *c, int ev, void *ev_data) { mg_http_reply(c, 200, "", "Hi from Mongoose!\n" "tick: %llu\n" - "ram used: %zu\n" - "ram free: %zu\n", - hal_get_tick(), hal_ram_used(), hal_ram_free()); + "heap used: %zu\n" + "stack used: %zu\n", + hal_get_tick(), hal_get_heap(), hal_get_stack()); } } } @@ -103,7 +103,7 @@ int main(void) { mg_http_listen(&mgr, "https://0.0.0.0", http_ev_handler, NULL); MG_INFO(("Initialised. CPU clock: %lu MHz", SystemCoreClock / 1000000)); - MG_INFO(("RAM used: %zu, free: %zu", hal_ram_used(), hal_ram_free())); + MG_INFO(("Heap used: %zu, stack used: %zu", hal_get_heap(), hal_get_stack())); MG_INFO(("Crash record: %M", mg_print_crash_record)); for (;;) { diff --git a/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h b/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h index 5f1f6a15..2951a433 100644 --- a/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h +++ b/tutorials/stm32/nucleo-h723zg/minimal/mongoose_config.h @@ -28,6 +28,8 @@ // Crash report support. Health record lives in the .mg_health region, see link.ld #define MG_ENABLE_HEALTH 1 +#define MG_HEALTH_HEAP_USED hal_get_heap() +#define MG_HEALTH_STACK_USED hal_get_stack() // mdash.net device management service support #define MG_ENABLE_MDASH 0