Skip to content

Commit

Permalink
add HIMEM debugging tools (check free size, and memory test) (#1852)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
nliaudat committed Jan 15, 2023
1 parent 284f7b1 commit 5a8b39f
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 32 deletions.
28 changes: 19 additions & 9 deletions code/components/jomjol_helper/esp_sys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@

#include "esp_chip_info.h"

// for esp_spiram_get_size
extern "C" {

#include <esp32/spiram.h>
#include <esp32/himem.h>
}


void Restart() {
esp_restart();
Expand Down Expand Up @@ -126,13 +119,17 @@ 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());
espInfoResultStr += std::string(aMsgBuf);
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;
}
Expand Down Expand Up @@ -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
#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
35 changes: 20 additions & 15 deletions code/components/jomjol_helper/esp_sys.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@
#include <esp_spi_flash.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();
Expand All @@ -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
#endif // DEBUG_ENABLE_SYSINFO
115 changes: 115 additions & 0 deletions code/components/jomjol_helper/himem_memory_check.cpp
Original file line number Diff line number Diff line change
@@ -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 changes: 41 additions & 0 deletions code/components/jomjol_helper/himem_memory_check.h
Original file line number Diff line number Diff line change
@@ -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
19 changes: 18 additions & 1 deletion code/components/jomjol_helper/perfmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -67,4 +84,4 @@ esp_err_t perfmon_start()
}


#endif // DEBUG_ENABLE_PERFMON
#endif // DEBUG_ENABLE_PERFMON
8 changes: 7 additions & 1 deletion code/include/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 22 additions & 6 deletions code/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 5a8b39f

Please sign in to comment.