From 49583699572ca38f8894e95ecd841002db5b745d Mon Sep 17 00:00:00 2001 From: Liu Zhongwei Date: Wed, 11 Dec 2024 19:27:44 +0800 Subject: [PATCH] feat(memory): add print memory info --- idf_component.yml | 2 +- library.properties | 2 +- micropython.cmake | 14 +++++--- mpy_support/esp_utils_mp_module.c | 28 +++++++++++++++ src/memory/esp_utils_mem.c | 59 +++++++++++++++++++++++++++++-- src/memory/esp_utils_mem.h | 36 +++++++++---------- test_apps/main/test_on_c.c | 2 ++ test_apps/main/test_on_cpp.cpp | 2 ++ 8 files changed, 118 insertions(+), 27 deletions(-) create mode 100644 mpy_support/esp_utils_mp_module.c diff --git a/idf_component.yml b/idf_component.yml index e489f8a..5c842ee 100644 --- a/idf_component.yml +++ b/idf_component.yml @@ -1,4 +1,4 @@ -version: "0.1.1" +version: "0.1.2" description: esp-lib-utils is a library designed for ESP SoCs to provide utility functions, including logging, checking, and memory. url: https://github.com/esp-arduino-libs/esp-lib-utils repository: https://github.com/esp-arduino-libs/esp-lib-utils.git diff --git a/library.properties b/library.properties index a7569ee..bb47f68 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=esp-lib-utils -version=0.1.1 +version=0.1.2 author=espressif maintainer=espressif sentence=esp-lib-utils is a library designed for ESP SoCs to provide utility functions, including logging, checking, and memory. diff --git a/micropython.cmake b/micropython.cmake index a350f51..1d57969 100644 --- a/micropython.cmake +++ b/micropython.cmake @@ -2,15 +2,21 @@ add_library(usermod_esp_lib_utils INTERFACE) -# Set the source directorya and find all source files. +# Find all source files in the `src` directory. set(SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src) -file(GLOB_RECURSE SRCS ${SRC_DIR}/*.c) +file(GLOB_RECURSE SRCS_C ${SRC_DIR}/*.c) +file(GLOB_RECURSE SRCS_CXX ${SRC_DIR}/*.cpp) + +# Find all source files in the `micropython` directory. +set(MPY_DIR ${CMAKE_CURRENT_LIST_DIR}/mpy_support) +file(GLOB_RECURSE MPY_C ${MPY_DIR}/*.c) +file(GLOB_RECURSE MPY_CXX ${MPY_DIR}/*.cpp) # Add our source files to the library. -target_sources(usermod_esp_lib_utils INTERFACE ${SRCS}) +target_sources(usermod_esp_lib_utils INTERFACE ${SRCS_C} ${SRCS_CXX} ${MPY_C} ${MPY_CXX}) # Add the current directory as an include directory. -target_include_directories(usermod_esp_lib_utils INTERFACE ${SRC_DIR}) +target_include_directories(usermod_esp_lib_utils INTERFACE ${SRC_DIR} ${MPY_DIR}) # Link our INTERFACE library to the usermod target. target_link_libraries(usermod INTERFACE usermod_esp_lib_utils) diff --git a/mpy_support/esp_utils_mp_module.c b/mpy_support/esp_utils_mp_module.c new file mode 100644 index 0000000..226234b --- /dev/null +++ b/mpy_support/esp_utils_mp_module.c @@ -0,0 +1,28 @@ +#include "py/runtime.h" +#include "memory/esp_utils_mem.h" + +static mp_obj_t mem_info(void) +{ + return mp_obj_new_bool(esp_utils_mem_print_info()); +} +MP_DEFINE_CONST_FUN_OBJ_0(mem_info_func_obj, mem_info); + +// Define all attributes of the module. +// Table entries are key/value pairs of the attribute name (a string) +// and the MicroPython object reference. +// All identifiers and strings are written as MP_QSTR_xxx and will be +// optimized to word-sized integers by the build system (interned strings). +static const mp_rom_map_elem_t module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp_utils) }, + { MP_ROM_QSTR(MP_QSTR_mem_info), MP_ROM_PTR(&mem_info_func_obj) }, +}; +static MP_DEFINE_CONST_DICT(module_globals, module_globals_table); + +// Define module object. +const mp_obj_module_t esp_utils_mp_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&module_globals, +}; + +// Register the module to make it available in Python. +MP_REGISTER_MODULE(MP_QSTR_esp_utils, esp_utils_mp_module); diff --git a/src/memory/esp_utils_mem.c b/src/memory/esp_utils_mem.c index 2c8e254..e865582 100644 --- a/src/memory/esp_utils_mem.c +++ b/src/memory/esp_utils_mem.c @@ -3,8 +3,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include +#include "esp_heap_caps.h" #include "esp_utils_conf_internal.h" #include "check/esp_utils_check.h" #include "log/esp_utils_log.h" @@ -18,8 +20,12 @@ #include #endif // ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE +#define PRINT_INFO_BUFFER_SIZE 256 + void *esp_utils_mem_gen_malloc(size_t size) { + ESP_UTILS_LOG_TRACE_ENTER(); + void *p = NULL; #if ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE == ESP_UTILS_MEM_ALLOC_TYPE_STDLIB p = malloc(size); @@ -29,17 +35,22 @@ void *esp_utils_mem_gen_malloc(size_t size) p = ESP_UTILS_CONF_MEM_GEN_ALLOC_CUSTOM_MALLOC(size); #elif ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE == ESP_UTILS_MEM_ALLOC_TYPE_MICROPYTHON #if MICROPY_MALLOC_USES_ALLOCATED_SIZE - return gc_alloc(size, true); + p = gc_alloc(size, true); #else - return m_malloc(size); + p = m_malloc(size); #endif // MICROPY_MALLOC_USES_ALLOCATED_SIZE #endif // ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE ESP_UTILS_LOGD("Malloc @%p: %d", p, (int)size); + + ESP_UTILS_LOG_TRACE_EXIT(); + return p; } void esp_utils_mem_gen_free(void *p) { + ESP_UTILS_LOG_TRACE_ENTER(); + ESP_UTILS_LOGD("Free @%p", p); #if ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE == ESP_UTILS_MEM_ALLOC_TYPE_STDLIB free(p); @@ -54,4 +65,48 @@ void esp_utils_mem_gen_free(void *p) m_free(p); #endif // MICROPY_MALLOC_USES_ALLOCATED_SIZE #endif // ESP_UTILS_CONF_MEM_GEN_ALLOC_TYPE + + ESP_UTILS_LOG_TRACE_EXIT(); +} + +void *esp_utils_mem_gen_calloc(size_t n, size_t size) +{ + ESP_UTILS_LOG_TRACE_ENTER(); + + size_t total_size = (size_t)n * size; + void *p = esp_utils_mem_gen_malloc(total_size); + if (p != NULL) { + memset(p, 0, total_size); + } + + ESP_UTILS_LOG_TRACE_EXIT(); + + return p; +} + +bool esp_utils_mem_print_info(void) +{ + ESP_UTILS_LOG_TRACE_ENTER(); + + char *buffer = esp_utils_mem_gen_calloc(1, PRINT_INFO_BUFFER_SIZE); + ESP_UTILS_CHECK_NULL_RETURN(buffer, false, "Allocate buffer failed"); + + snprintf( + buffer, PRINT_INFO_BUFFER_SIZE, + "ESP Memory Info:\n" + " Biggest / Free / Total\n" + " SRAM : [%8d / %8d / %8d]\n" + "PSRAM : [%8d / %8d / %8d]", + (int)heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL), (int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL), + (int)heap_caps_get_total_size(MALLOC_CAP_INTERNAL), + (int)heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM), (int)heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + (int)heap_caps_get_total_size(MALLOC_CAP_SPIRAM) + ); + printf("%s\n", buffer); + + esp_utils_mem_gen_free(buffer); + + ESP_UTILS_LOG_TRACE_EXIT(); + + return true; } diff --git a/src/memory/esp_utils_mem.h b/src/memory/esp_utils_mem.h index 4bbaa15..09c3a34 100644 --- a/src/memory/esp_utils_mem.h +++ b/src/memory/esp_utils_mem.h @@ -5,16 +5,27 @@ */ #pragma once +#include +#include #include "sdkconfig.h" #include "esp_utils_conf_internal.h" #ifdef __cplusplus +extern "C" { +#endif -#include -#include +void *esp_utils_mem_gen_malloc(size_t size); +void esp_utils_mem_gen_free(void *p); +void *esp_utils_mem_gen_calloc(size_t n, size_t size); +bool esp_utils_mem_print_info(void); + +#ifdef __cplusplus +} +#endif + +#ifdef __cplusplus -extern "C" void *esp_utils_mem_gen_malloc(size_t size); -extern "C" void esp_utils_mem_gen_free(void *p); +#include namespace esp_utils { @@ -73,11 +84,6 @@ std::shared_ptr make_shared(Args &&... args) } // namespace esp_utils -#else - -void *esp_utils_mem_gen_malloc(size_t size); -void esp_utils_mem_gen_free(void *p); - #endif // __cplusplus /** @@ -88,13 +94,5 @@ void esp_utils_mem_gen_free(void *p); #undef free #undef calloc #define malloc(size) esp_utils_mem_gen_malloc(size) -#define free(ptr) esp_utils_mem_gen_free(ptr) -#define calloc(n, size) \ - ({ \ - size_t _size = (size_t)n * size; \ - void *p = malloc(_size); \ - if (p != NULL) { \ - memset(p, 0, _size); \ - } \ - p; \ - }) +#define free(p) esp_utils_mem_gen_free(p) +#define calloc(n, size) esp_utils_mem_gen_calloc(n, size) diff --git a/test_apps/main/test_on_c.c b/test_apps/main/test_on_c.c index ace00c5..e09483e 100644 --- a/test_apps/main/test_on_c.c +++ b/test_apps/main/test_on_c.c @@ -24,6 +24,8 @@ TEST_CASE("Test log functions on C", "[utils][log][C]") TEST_CASE("Test memory functions on C", "[utils][memory][C]") { + TEST_ASSERT_TRUE_MESSAGE(esp_utils_mem_print_info(), "Print memory info failed"); + char *good_ptr = (char *)calloc(1, MALLOC_GOOD_SIZE); ESP_UTILS_CHECK_NULL_GOTO(good_ptr, err, "Failed to allocate memory size: %d", MALLOC_GOOD_SIZE); ESP_UTILS_LOGI("Malloced value: %d", good_ptr[0]); diff --git a/test_apps/main/test_on_cpp.cpp b/test_apps/main/test_on_cpp.cpp index 6fa8de9..67ba6a3 100644 --- a/test_apps/main/test_on_cpp.cpp +++ b/test_apps/main/test_on_cpp.cpp @@ -34,6 +34,8 @@ using TestBadClass = TestClass; TEST_CASE("Test memory functions on cpp", "[utils][memory][CPP]") { + TEST_ASSERT_TRUE_MESSAGE(esp_utils_mem_print_info(), "Print memory info failed"); + std::shared_ptr good_ptr = nullptr; ESP_UTILS_CHECK_EXCEPTION_GOTO( (good_ptr = esp_utils::make_shared()), err, "Failed to allocate memory size: %d",