From 5a8b39f2461cd795bc02831ca58ced9ba4bcfead Mon Sep 17 00:00:00 2001 From: Nicolas Liaudat Date: Sun, 15 Jan 2023 22:42:11 +0100 Subject: [PATCH] add HIMEM debugging tools (check free size, and memory test) (#1852) * Update defines.h * Update esp_sys.h * Update esp_sys.cpp * Add files via upload * Update perfmon.c * Update main.cpp * Update main.cpp * Delete himem_memory_check.c * Add files via upload * Update defines.h * Update himem_memory_check.cpp * Update main.cpp * Update himem_memory_check.cpp * Update himem_memory_check.h * Update main.cpp --- code/components/jomjol_helper/esp_sys.cpp | 28 +++-- code/components/jomjol_helper/esp_sys.h | 35 +++--- .../jomjol_helper/himem_memory_check.cpp | 115 ++++++++++++++++++ .../jomjol_helper/himem_memory_check.h | 41 +++++++ code/components/jomjol_helper/perfmon.c | 19 ++- code/include/defines.h | 8 +- code/main/main.cpp | 28 ++++- 7 files changed, 242 insertions(+), 32 deletions(-) create mode 100644 code/components/jomjol_helper/himem_memory_check.cpp create mode 100644 code/components/jomjol_helper/himem_memory_check.h diff --git a/code/components/jomjol_helper/esp_sys.cpp b/code/components/jomjol_helper/esp_sys.cpp index 7a4d8110..2a222552 100644 --- a/code/components/jomjol_helper/esp_sys.cpp +++ b/code/components/jomjol_helper/esp_sys.cpp @@ -9,13 +9,6 @@ #include "esp_chip_info.h" -// for esp_spiram_get_size -extern "C" { - -#include -#include -} - void Restart() { esp_restart(); @@ -126,6 +119,8 @@ std::string get_device_info() else espInfoResultStr += " External Flash memory\n"; } + + #ifdef USE_HIMEM_IF_AVAILABLE sprintf(aMsgBuf,"spiram size %u\n", esp_spiram_get_size()); espInfoResultStr += std::string(aMsgBuf); sprintf(aMsgBuf,"himem free %u\n", esp_himem_get_free_size()); @@ -133,6 +128,8 @@ std::string get_device_info() sprintf(aMsgBuf,"himem phys %u\n", esp_himem_get_phys_size()); espInfoResultStr += std::string(aMsgBuf); sprintf(aMsgBuf,"himem reserved %u\n", esp_himem_reserved_area_size()); + espInfoResultStr += std::string(aMsgBuf); + #endif return espInfoResultStr; } @@ -163,6 +160,19 @@ size_t getMinEverFreeMemInternal(){ //Min. Ever Free Size size_t getMinEverFreeMemSPIRAM(){ //Min. Ever Free Size return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); } -//#endif // ESP_IDF_VERSION -#endif //DEBUG_ENABLE_SYSINFO \ No newline at end of file +#ifdef USE_HIMEM_IF_AVAILABLE + size_t getHimemTotSpace(){ + return esp_himem_get_phys_size(); + } + + size_t getHimemFreeSpace(){ + return esp_himem_get_free_size(); + } + + size_t getHimemReservedArea(){ + return esp_himem_reserved_area_size(); + } +#endif + +#endif //DEBUG_ENABLE_SYSINFO diff --git a/code/components/jomjol_helper/esp_sys.h b/code/components/jomjol_helper/esp_sys.h index 23c3eedf..b07ee00f 100644 --- a/code/components/jomjol_helper/esp_sys.h +++ b/code/components/jomjol_helper/esp_sys.h @@ -16,6 +16,14 @@ #include #include +// for esp_spiram_get_size +extern "C" { + #include + #ifdef USE_HIMEM_IF_AVAILABLE + #include + #endif +} + void Restart(); @@ -26,24 +34,21 @@ uint32_t GetFreeHeap(); uint32_t GetLeastHeapFreeSinceBoot(); -/* - bool CHIP_FEATURE_EMB_FLASH; //Chip has embedded flash memory. - bool CHIP_FEATURE_WIFI_BGN; //Chip has 2.4GHz WiFi. - bool CHIP_FEATURE_BLE; //Chip has Bluetooth LE. - bool CHIP_FEATURE_BT; //Chip has Bluetooth Classic. - bool CHIP_FEATURE_IEEE802154; //Chip has IEEE 802.15.4 (Zigbee/Thread) - bool CHIP_FEATURE_EMB_PSRAM; //Chip has embedded psram. -*/ - std::string get_device_info(); size_t getFreeMemoryInternal(); - size_t getFreeMemorySPIRAM(); - size_t getLargestFreeBlockInternal(); - size_t getLargestFreeBlockSPIRAM(); - size_t getMinEverFreeMemInternal(); - size_t getMinEverFreeMemSPIRAM(); + size_t getFreeMemorySPIRAM(); + size_t getLargestFreeBlockInternal(); + size_t getLargestFreeBlockSPIRAM(); + size_t getMinEverFreeMemInternal(); + size_t getMinEverFreeMemSPIRAM(); + #ifdef USE_HIMEM_IF_AVAILABLE + size_t getHimemTotSpace(); + size_t getHimemFreeSpace(); + size_t getHimemReservedArea(); + #endif + #endif //ESP_SYS_H -#endif // DEBUG_ENABLE_SYSINFO \ No newline at end of file +#endif // DEBUG_ENABLE_SYSINFO diff --git a/code/components/jomjol_helper/himem_memory_check.cpp b/code/components/jomjol_helper/himem_memory_check.cpp new file mode 100644 index 00000000..5d1955e6 --- /dev/null +++ b/code/components/jomjol_helper/himem_memory_check.cpp @@ -0,0 +1,115 @@ + +// need [env:esp32cam-dev-himem] +//CONFIG_SPIRAM_BANKSWITCH_ENABLE=y +//CONFIG_SPIRAM_BANKSWITCH_RESERVE=4 + + + +#include "../../include/defines.h" + +#ifdef DEBUG_HIMEM_MEMORY_CHECK + +#include "himem_memory_check.h" + +//source adapted from : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c + + +//Fill memory with pseudo-random data generated from the given seed. +//Fills the memory in 32-bit words for speed. +static void fill_mem_seed(int seed, void *mem, int len) +{ + uint32_t *p = (uint32_t *)mem; + unsigned int rseed = seed ^ 0xa5a5a5a5; + for (int i = 0; i < len / 4; i++) { + *p++ = rand_r(&rseed); + } +} + +//Check the memory filled by fill_mem_seed. Returns true if the data matches the data +//that fill_mem_seed wrote (when given the same seed). +//Returns true if there's a match, false when the region differs from what should be there. +static bool check_mem_seed(int seed, void *mem, int len, int phys_addr) +{ + uint32_t *p = (uint32_t *)mem; + unsigned int rseed = seed ^ 0xa5a5a5a5; + for (int i = 0; i < len / 4; i++) { + uint32_t ex = rand_r(&rseed); + if (ex != *p) { + //printf("check_mem_seed: %x has 0x%08"PRIx32" expected 0x%08"PRIx32"\n", phys_addr+((char*)p-(char*)mem), *p, ex); + return false; + } + p++; + } + return true; +} + +//Allocate a himem region, fill it with data, check it and release it. +static bool test_region(int check_size, int seed) +{ + esp_himem_handle_t mh; //Handle for the address space we're using + esp_himem_rangehandle_t rh; //Handle for the actual RAM. + bool ret = true; + + //Allocate the memory we're going to check. + ESP_ERROR_CHECK(esp_himem_alloc(check_size, &mh)); + //Allocate a block of address range + ESP_ERROR_CHECK(esp_himem_alloc_map_range(ESP_HIMEM_BLKSZ, &rh)); + for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) { + uint32_t *ptr = NULL; + //Map in block, write pseudo-random data, unmap block. + ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr)); + fill_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ); // + ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ)); + } + vTaskDelay(5); //give the OS some time to do things so the task watchdog doesn't bark + for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) { + uint32_t *ptr; + //Map in block, check against earlier written pseudo-random data, unmap block. + ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr)); + if (!check_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ, i)) { + //printf("Error in block %d\n", i / ESP_HIMEM_BLKSZ); + ret = false; + } + ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ)); + if (!ret) break; //don't check rest of blocks if error occurred + } + //Okay, all done! + ESP_ERROR_CHECK(esp_himem_free(mh)); + ESP_ERROR_CHECK(esp_himem_free_map_range(rh)); + return ret; +} + + +std::string himem_memory_check() +{ + size_t memcnt=esp_himem_get_phys_size(); + size_t memfree=esp_himem_get_free_size(); + + std::string espInfoResultStr = ""; + char aMsgBuf[40]; + + espInfoResultStr += "Running HIMEM memory check"; + + sprintf(aMsgBuf,"Himem has %dKiB of memory", (int)memcnt/1024); + espInfoResultStr += std::string(aMsgBuf); + + sprintf(aMsgBuf,"%dKiB of which is free", (int)memfree/1024); + espInfoResultStr += std::string(aMsgBuf); + + espInfoResultStr += "\n please wait ....\n"; + + //running memory checks + //assert(test_region(memfree, 0xaaaa)); + + if(test_region(memfree, 0xaaaa)) { + espInfoResultStr += "Himem check Failed!\n"; + } else { + espInfoResultStr += "Himem check Done!\n"; + } + + return espInfoResultStr; + +} + + +#endif // DEBUG_HIMEM_MEMORY_CHECK diff --git a/code/components/jomjol_helper/himem_memory_check.h b/code/components/jomjol_helper/himem_memory_check.h new file mode 100644 index 00000000..a09321a5 --- /dev/null +++ b/code/components/jomjol_helper/himem_memory_check.h @@ -0,0 +1,41 @@ + +// need [env:esp32cam-dev-himem] +//CONFIG_SPIRAM_BANKSWITCH_ENABLE=y +//CONFIG_SPIRAM_BANKSWITCH_RESERVE=4 + +#pragma once + +#include "../../include/defines.h" + +#ifdef DEBUG_HIMEM_MEMORY_CHECK + +#ifndef HIMEM_MEMORY_CHECK_H +#define HIMEM_MEMORY_CHECK_H + + + +//source : //source : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c + + +#include +#include +#include +#include + + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_system.h" +#include "esp_heap_caps.h" +#include "esp32/himem.h" + +#include +#include "esp32/himem.h" + + +std::string himem_memory_check(); + +#endif //HIMEM_MEMORY_CHECK_H + +#endif // DEBUG_HIMEM_MEMORY_CHECK diff --git a/code/components/jomjol_helper/perfmon.c b/code/components/jomjol_helper/perfmon.c index 6c2c10e5..47acce8b 100644 --- a/code/components/jomjol_helper/perfmon.c +++ b/code/components/jomjol_helper/perfmon.c @@ -2,6 +2,23 @@ #include "../../include/defines.h" +/* +ESP32 CPU usage monitor +Gives you a rough idea of how the Xtensa cores are utilized. + +Works by attaching idle hooks and measuring how often they get called. The core usage is calculated: usage% = idle ticks since last measurement / expected idle ticks if core were idle * 100%. The expected idle tick count was measured by running an empty program. + +Limitations: +Should only be used for user information, not in logic that needs accurate values +New IDF versions could optimize performance and therefore introduce an error to usage estimation. +When one core is at 100% the other might report a negative value + +Usage: +#include "perfmon.h" +Call perfmon_start() once + +*/ + #ifdef DEBUG_ENABLE_PERFMON #include "perfmon.h" @@ -67,4 +84,4 @@ esp_err_t perfmon_start() } -#endif // DEBUG_ENABLE_PERFMON \ No newline at end of file +#endif // DEBUG_ENABLE_PERFMON diff --git a/code/include/defines.h b/code/include/defines.h index 0d9dd716..5a9210ef 100644 --- a/code/include/defines.h +++ b/code/include/defines.h @@ -14,8 +14,14 @@ //#define DEBUG_DISABLE_BROWNOUT_DETECTOR //#define DEBUG_ENABLE_SYSINFO //#define DEBUG_ENABLE_PERFMON + //#define DEBUG_HIMEM_MEMORY_CHECK + // need [env:esp32cam-dev-himem] + //=> CONFIG_SPIRAM_BANKSWITCH_ENABLE=y + //=> CONFIG_SPIRAM_BANKSWITCH_RESERVE=4 - + + // use himem //https://github.com/jomjol/AI-on-the-edge-device/issues/1842 + #define USE_HIMEM_IF_AVAILABLE /* Uncomment this to generate task list with stack sizes using the /heap handler PLEASE BE AWARE: The following CONFIG parameters have to to be set in diff --git a/code/main/main.cpp b/code/main/main.cpp index a24df3c5..dedd89cf 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -54,6 +54,14 @@ #endif #endif //DEBUG_ENABLE_SYSINFO + +#ifdef USE_HIMEM_IF_AVAILABLE + #include "esp32/himem.h" + #ifdef DEBUG_HIMEM_MEMORY_CHECK + #include "himem_memory_check.h" + #endif +#endif + extern const char* GIT_TAG; extern const char* GIT_REV; extern const char* GIT_BRANCH; @@ -160,12 +168,6 @@ extern "C" void app_main(void) WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector #endif -#ifdef DEBUG_ENABLE_SYSINFO -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 ) - LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Device Info" + get_device_info() ); - ESP_LOGD(TAG, "Device infos %s", get_device_info().c_str()); -#endif -#endif //DEBUG_ENABLE_SYSINFO ESP_LOGI(TAG, "\n\n\n\n\n"); // Add mark on log to see when it restarted @@ -200,6 +202,20 @@ extern "C" void app_main(void) LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================================================="); LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason()); + +#ifdef DEBUG_ENABLE_SYSINFO + #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 ) + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device Info : " + get_device_info() ); + ESP_LOGD(TAG, "Device infos %s", get_device_info().c_str()); + #endif +#endif //DEBUG_ENABLE_SYSINFO + +#ifdef USE_HIMEM_IF_AVAILABLE + #ifdef DEBUG_HIMEM_MEMORY_CHECK + LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Himem mem check : " + himem_memory_check() ); + ESP_LOGD(TAG, "Himem mem check %s", himem_memory_check().c_str()); + #endif +#endif CheckIsPlannedReboot(); CheckOTAUpdate();