Просмотр исходного кода

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
Nicolas Liaudat 3 лет назад
Родитель
Сommit
5a8b39f246

+ 19 - 9
code/components/jomjol_helper/esp_sys.cpp

@@ -9,13 +9,6 @@
 
 
 #include "esp_chip_info.h"
 #include "esp_chip_info.h"
 
 
-// for esp_spiram_get_size
-extern "C" {
-    
-#include <esp32/spiram.h>
-#include <esp32/himem.h>
-}
-
 
 
 void Restart() {
 void Restart() {
     esp_restart();
     esp_restart();
@@ -126,6 +119,8 @@ std::string get_device_info()
         else
         else
            espInfoResultStr += "    External Flash memory\n";
            espInfoResultStr += "    External Flash memory\n";
     }
     }
+
+    #ifdef USE_HIMEM_IF_AVAILABLE
         sprintf(aMsgBuf,"spiram size %u\n", esp_spiram_get_size());
         sprintf(aMsgBuf,"spiram size %u\n", esp_spiram_get_size());
         espInfoResultStr += std::string(aMsgBuf);
         espInfoResultStr += std::string(aMsgBuf);
         sprintf(aMsgBuf,"himem free %u\n", esp_himem_get_free_size());
         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());
         sprintf(aMsgBuf,"himem phys %u\n", esp_himem_get_phys_size());
         espInfoResultStr += std::string(aMsgBuf);
         espInfoResultStr += std::string(aMsgBuf);
         sprintf(aMsgBuf,"himem reserved %u\n", esp_himem_reserved_area_size());
         sprintf(aMsgBuf,"himem reserved %u\n", esp_himem_reserved_area_size());
+        espInfoResultStr += std::string(aMsgBuf);
+    #endif
     
     
     return espInfoResultStr; 
     return espInfoResultStr; 
 }
 }
@@ -163,6 +160,19 @@ size_t getMinEverFreeMemInternal(){ //Min. Ever Free Size
 size_t getMinEverFreeMemSPIRAM(){ //Min. Ever Free Size
 size_t getMinEverFreeMemSPIRAM(){ //Min. Ever Free Size
     return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
     return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
 }
 }
-//#endif // ESP_IDF_VERSION
 
 
-#endif //DEBUG_ENABLE_SYSINFO
+#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

+ 20 - 15
code/components/jomjol_helper/esp_sys.h

@@ -16,6 +16,14 @@
 #include <esp_spi_flash.h>
 #include <esp_spi_flash.h>
 #include <esp_heap_caps.h>
 #include <esp_heap_caps.h>
 
 
+// for esp_spiram_get_size
+extern "C" {
+    #include <esp32/spiram.h>
+    #ifdef USE_HIMEM_IF_AVAILABLE
+        #include <esp32/himem.h>
+    #endif
+}
+
 
 
 
 
     void Restart();
     void Restart();
@@ -26,24 +34,21 @@
     uint32_t GetFreeHeap();
     uint32_t GetFreeHeap();
     uint32_t GetLeastHeapFreeSinceBoot();
     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();
     std::string get_device_info();
 
 
     size_t getFreeMemoryInternal();
     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 //ESP_SYS_H
 
 
-#endif // DEBUG_ENABLE_SYSINFO
+#endif // DEBUG_ENABLE_SYSINFO

+ 115 - 0
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

+ 41 - 0
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 <stdio.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+
+#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 <string>
+#include "esp32/himem.h"
+
+
+std::string himem_memory_check();
+
+#endif //HIMEM_MEMORY_CHECK_H
+
+#endif // DEBUG_HIMEM_MEMORY_CHECK

+ 18 - 1
code/components/jomjol_helper/perfmon.c

@@ -2,6 +2,23 @@
 
 
 #include "../../include/defines.h"
 #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
 #ifdef DEBUG_ENABLE_PERFMON
 
 
 #include "perfmon.h"
 #include "perfmon.h"
@@ -67,4 +84,4 @@ esp_err_t perfmon_start()
 }
 }
 
 
 
 
-#endif // DEBUG_ENABLE_PERFMON
+#endif // DEBUG_ENABLE_PERFMON

+ 7 - 1
code/include/defines.h

@@ -14,8 +14,14 @@
     //#define DEBUG_DISABLE_BROWNOUT_DETECTOR
     //#define DEBUG_DISABLE_BROWNOUT_DETECTOR
     //#define DEBUG_ENABLE_SYSINFO
     //#define DEBUG_ENABLE_SYSINFO
     //#define DEBUG_ENABLE_PERFMON
     //#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
     /* 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 
         PLEASE BE AWARE: The following CONFIG parameters have to to be set in 

+ 22 - 6
code/main/main.cpp

@@ -54,6 +54,14 @@
 #endif
 #endif
 #endif //DEBUG_ENABLE_SYSINFO
 #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_TAG;
 extern const char* GIT_REV;
 extern const char* GIT_REV;
 extern const char* GIT_BRANCH;
 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
     WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
 #endif
 #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
     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, "=================================================");
     LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
     LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
     LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
     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();
     CheckIsPlannedReboot();
     CheckOTAUpdate();
     CheckOTAUpdate();