Shared PSRAM memory (#2285)

* enable PSRAM logging

* add extra functions for psram shared memroy handling

* CImageBasis objects still should used dynamic memory (eg. rawImage), haw ever tmpImage must be placed inside the shared memory

* Place all STBI allocs inside the shared memory

* The models are placed in the shared PSRAM reagion and must be allocated through the dedicated functions

* .

* renaming

* fix cast warning

* add flag to switch STBI PSRAM usage

* improve PSRAM shared handling

* reserve shared PSRAM as early as possible

* init logging eralier so we can use it in PSRAM shared alloc

* move Wifi_LWIP, BSS_SEG and MQTT Outbox into PSRAM to ffree internal memory

* Check if model fits into reserved shared memory

* Update code/components/jomjol_tfliteclass/CTfLiteClass.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_flowcontroll/ClassFlowControll.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_image_proc/CImageBasis.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* Update code/components/jomjol_helper/psram.cpp

* .

* .

* .

* .

* Korrektur Merge Conflict in main.cpp

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
This commit is contained in:
CaCO3
2023-04-19 21:17:41 +02:00
committed by GitHub
parent 19158c998f
commit de92c29245
12 changed files with 332 additions and 107 deletions

View File

@@ -190,10 +190,10 @@ bool ClassFlowAlignment::doFlow(string time)
if (!ImageTMP) if (!ImageTMP)
{ {
ImageTMP = new CImageBasis("ImageTMP", ImageBasis); ImageTMP = new CImageBasis("tmpImage", ImageBasis); // Make sure the name does not get change, it is relevant for the PSRAM allocation!
if (!ImageTMP) if (!ImageTMP)
{ {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate ImageTMP -> Exec this round aborted!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tmpImage -> Exec this round aborted!");
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow"); LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
return false; return false;
} }

View File

@@ -374,8 +374,11 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
} }
} }
if (!getNetworkParameter()) if (!getNetworkParameter()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "An error occured on setting up the Network -> Disabling it!");
disabled = true; // An error occured, disable this CNN!
return false; return false;
}
for (int _ana = 0; _ana < GENERAL.size(); ++_ana) for (int _ana = 0; _ana < GENERAL.size(); ++_ana)

View File

@@ -373,7 +373,7 @@ bool ClassFlowControll::doFlow(string time)
zw_time = getCurrentTimeString("%H:%M:%S"); zw_time = getCurrentTimeString("%H:%M:%S");
aktstatus = TranslateAktstatus(FlowControll[i]->name()); aktstatus = TranslateAktstatus(FlowControll[i]->name());
aktstatusWithTime = aktstatus + " (" + zw_time + ")"; aktstatusWithTime = aktstatus + " (" + zw_time + ")";
//LogFile.WriteToFile(ESP_LOG_INFO, TAG, aktstatusWithTime); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Status: " + aktstatusWithTime);
#ifdef ENABLE_MQTT #ifdef ENABLE_MQTT
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", aktstatus, qos, false); MQTTPublish(mqttServer_getMainTopic() + "/" + "status", aktstatus, qos, false);
#endif //ENABLE_MQTT #endif //ENABLE_MQTT

View File

@@ -8,6 +8,7 @@
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_log.h" #include "esp_log.h"
#include "../../include/defines.h" #include "../../include/defines.h"
#include "psram.h"
#include <time.h> #include <time.h>
@@ -183,6 +184,8 @@ string ClassFlowTakeImage::getHTMLSingleStep(string host)
bool ClassFlowTakeImage::doFlow(string zwtime) bool ClassFlowTakeImage::doFlow(string zwtime)
{ {
psram_init_shared_memory_for_take_image_step();
string logPath = CreateLogFolder(zwtime); string logPath = CreateLogFolder(zwtime);
int flash_duration = (int) (waitbeforepicture * 1000); int flash_duration = (int) (waitbeforepicture * 1000);

View File

@@ -1,11 +1,128 @@
#include "ClassLogFile.h" #include "ClassLogFile.h"
#include "esp_heap_caps.h" #include "../../include/defines.h"
#include "psram.h"
static const char* TAG = "PSRAM"; static const char* TAG = "PSRAM";
using namespace std; using namespace std;
void *shared_region = NULL;
uint32_t allocatedBytesForSTBI = 0;
/** Reserve a large block in the PSRAM which will be shared between the different steps.
* Each step uses it differently but only wiuthin itself. */
bool reserve_psram_shared_region(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating shared PSRAM region (" +
std::to_string(TENSOR_ARENA_SIZE + MAX_MODEL_SIZE) + " bytes)...");
shared_region = malloc_psram_heap("Shared PSRAM region", TENSOR_ARENA_SIZE + MAX_MODEL_SIZE,
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
if (shared_region == NULL) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocating shared PSRAM region!");
return false;
}
else {
return true;
}
}
/*******************************************************************
* Memory used in Take Image (STBI)
*******************************************************************/
void psram_init_shared_memory_for_take_image_step(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Init shared memory for step 'Take Image' (STBI buffers)");
allocatedBytesForSTBI = 0;
}
void *psram_reserve_shared_stbi_memory(size_t size) {
/* Only large buffers should be placed in the shared PSRAM
* If we also place all smaller STBI buffers here, we get artefacts for some reasons. */
if (size >= 100000) {
if ((allocatedBytesForSTBI + size) > TENSOR_ARENA_SIZE + MAX_MODEL_SIZE) { // Check if it still fits in the shared region
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Shared memory in PSRAM too small (STBI) to fit additional " +
std::to_string(size) + "bytes! Available: " + std::to_string(TENSOR_ARENA_SIZE + MAX_MODEL_SIZE - allocatedBytesForSTBI) + " bytes!");
return NULL;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating memory (" + std::to_string(size) + " bytes) for STBI (use shared memory in PSRAM)...");
allocatedBytesForSTBI += size;
return (uint8_t *)shared_region + allocatedBytesForSTBI - size;
}
else { // Normal PSRAM
return malloc_psram_heap("STBI", size, MALLOC_CAP_SPIRAM);
}
}
void *psram_reallocate_shared_stbi_memory(void *ptr, size_t newsize) {
char buf[20];
sprintf(buf, "%p", ptr);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "STBI requested realloc for " + std::string(buf) + " but this is currently unsupported!");
return NULL;
}
void psram_free_shared_stbi_memory(void *p) {
if ((p >= shared_region) && (p <= ((uint8_t *)shared_region + allocatedBytesForSTBI))) { // was allocated inside the shared memory
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Part of shared memory used for STBI (PSRAM, part of shared memory) is free again");
}
else { // Normal PSRAM
free_psram_heap("STBI", p);
}
}
/*******************************************************************
* Memory used in Aligning Step
* During this step we only use the shared part of the PSRAM
* for the tmpImage.
*******************************************************************/
void *psram_reserve_shared_tmp_image_memory(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating tmpImage (" + std::to_string(IMAGE_SIZE) + " bytes, use shared memory in PSRAM)...");
return shared_region; // Use 1th part of the shared memory for the tmpImage (only user)
}
void psram_free_shared_temp_image_memory(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Shared memory used for tmpImage (PSRAM, part of shared memory) is free again");
}
/*******************************************************************
* Memory used in Digitalization Steps
* During this step we only use the shared part of the PSRAM for the
* Tensor Arena and one of the Models.
* The shared memory is large enough for the largest model and the
* Tensor Arena. Therefore we do not need to monitor the usage.
*******************************************************************/
void *psram_get_shared_tensor_arena_memory(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating Tensor Arena (" + std::to_string(TENSOR_ARENA_SIZE) + " bytes, use shared memory in PSRAM)...");
return shared_region; // Use 1th part of the shared memory for Tensor
}
void *psram_get_shared_model_memory(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocating Model memory (" + std::to_string(MAX_MODEL_SIZE) + " bytes, use shared memory in PSRAM)...");
return (uint8_t *)shared_region + TENSOR_ARENA_SIZE; // Use 2nd part of the shared memory (after Tensor Arena) for the model
}
void psram_free_shared_tensor_arena_and_model_memory(void) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Shared memory used for Tensor Arena and model (PSRAM, part of shared memory) is free again");
}
/*******************************************************************
* General
*******************************************************************/
void *malloc_psram_heap(std::string name, size_t size, uint32_t caps) { void *malloc_psram_heap(std::string name, size_t size, uint32_t caps) {
void *ptr; void *ptr;
@@ -21,12 +138,25 @@ void *malloc_psram_heap(std::string name, size_t size, uint32_t caps) {
} }
void *realloc_psram_heap(std::string name, void *ptr, size_t size, uint32_t caps) {
ptr = heap_caps_realloc(ptr, size, caps);
if (ptr != NULL) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Reallocated " + to_string(size) + " bytes in PSRAM for '" + name + "'");
}
else {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to reallocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!");
}
return ptr;
}
void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps) { void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps) {
void *ptr; void *ptr;
ptr = heap_caps_calloc(n, size, caps); ptr = heap_caps_calloc(n, size, caps);
if (ptr != NULL) { if (ptr != NULL) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Allocated " + to_string(size) + " bytes in PSRAM for '" + name + "'"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Allocated " + to_string(size) + " bytes in PSRAM for '" + name + "'");
} }
else { else {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to allocate " + to_string(size) + " bytes in PSRAM for '" + name + "'!");
@@ -39,4 +169,4 @@ void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps)
void free_psram_heap(std::string name, void *ptr) { void free_psram_heap(std::string name, void *ptr) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Freeing memory in PSRAM used for '" + name + "'..."); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Freeing memory in PSRAM used for '" + name + "'...");
heap_caps_free(ptr); heap_caps_free(ptr);
} }

View File

@@ -1,7 +1,34 @@
#pragma once
#ifndef PSRAM_h
#define PSRAM_h
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
bool reserve_psram_shared_region(void);
/* Memory used in Take Image Step */
void psram_init_shared_memory_for_take_image_step(void);
void *psram_reserve_shared_stbi_memory(size_t size);
void *psram_reallocate_shared_stbi_memory(void *ptr, size_t newsize);
void psram_free_shared_stbi_memory(void *p);
/* Memory used in Aligning Step */
void *psram_reserve_shared_tmp_image_memory(void);
void psram_free_shared_temp_image_memory(void);
/* Memory used in Digitalization Steps */
void *psram_get_shared_tensor_arena_memory(void);
void *psram_get_shared_model_memory(void);
void psram_free_shared_tensor_arena_and_model_memory(void);
/* General */
void *malloc_psram_heap(std::string name, size_t size, uint32_t caps); void *malloc_psram_heap(std::string name, size_t size, uint32_t caps);
void *realloc_psram_heap(std::string name, void *ptr, size_t size, uint32_t caps);
void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps); void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps);
void free_psram_heap(std::string name, void *ptr); void free_psram_heap(std::string name, void *ptr);
#endif // PSRAM_h

View File

@@ -477,7 +477,13 @@ CImageBasis::CImageBasis(string _name, CImageBasis *_copyfrom)
memsize = width * height * channels; memsize = width * height * channels;
rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM);
if (name == "tmpImage") {
rgb_image = (unsigned char*)psram_reserve_shared_tmp_image_memory();
}
else {
rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM);
}
if (rgb_image == NULL) if (rgb_image == NULL)
{ {
@@ -618,9 +624,20 @@ CImageBasis::~CImageBasis()
{ {
RGBImageLock(); RGBImageLock();
if (!externalImage) { if (!externalImage) {
//stbi_image_free(rgb_image); if (name == "tmpImage") { // This image should be placed in the shared part of PSRAM
free_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ", " + to_string(memsize) + ")", rgb_image); psram_free_shared_temp_image_memory();
}
else { // All other images are much smaller and can go into the normal PSRAM region
//stbi_image_free(rgb_image);
if (memsize == 0) {
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Not freeing (" + name + " as there was never PSRAM allocated for it)");
}
else {
free_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ", " + to_string(memsize) + ")", rgb_image);
}
}
} }
RGBImageRelease(); RGBImageRelease();

View File

@@ -1,8 +1,23 @@
#include <stdint.h> #include <stdint.h>
#include <string> #include <string>
#include "psram.h"
#include "../../include/defines.h" #include "../../include/defines.h"
#define USE_SHARED_PSRAM_FOR_STBI
#ifdef USE_SHARED_PSRAM_FOR_STBI
#define STBI_MALLOC(sz) psram_reserve_shared_stbi_memory(sz)
#define STBI_REALLOC(p,newsz) psram_reallocate_shared_stbi_memory(p, newsz)
#define STBI_FREE(p) psram_free_shared_stbi_memory(p)
#else // Use normal PSRAM
#define STBI_MALLOC(sz) malloc_psram_heap("STBI", sz, MALLOC_CAP_SPIRAM)
#define STBI_REALLOC(p,newsz) realloc_psram_heap("STBI", p, newsz, MALLOC_CAP_SPIRAM)
#define STBI_FREE(p) free_psram_heap("STBI", p)
#endif
#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_IMPLEMENTATION
#include "../stb/stb_image.h" #include "../stb/stb_image.h"

View File

@@ -243,15 +243,22 @@ bool CTfLiteClass::ReadFileToModel(std::string _fn)
if (size == -1) if (size == -1)
{ {
ESP_LOGE(TAG, "CTfLiteClass::ReadFileToModel: Model file doesn't exist: %s", _fn.c_str()); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Model file doesn't exist: " + _fn + "!");
return false; return false;
} }
else if(size > MAX_MODEL_SIZE) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to load model '" + _fn + "'! It does not fit in the reserved shared memory in PSRAM!");
return false;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Loading Model " + _fn + " /size: " + std::to_string(size) + " bytes...");
#ifdef DEBUG_DETAIL_ON #ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start"); LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start");
#endif #endif
modelfile = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->modelfile", size, MALLOC_CAP_SPIRAM); modelfile = (unsigned char*)psram_get_shared_model_memory();
if(modelfile != NULL) if(modelfile != NULL)
{ {
@@ -304,9 +311,9 @@ CTfLiteClass::CTfLiteClass()
this->modelfile = NULL; this->modelfile = NULL;
this->interpreter = nullptr; this->interpreter = nullptr;
this->input = nullptr; this->input = nullptr;
this->output = nullptr; this->output = nullptr;
this->kTensorArenaSize = 800 * 1024; /// according to testfile: 108000 - so far 600;; 2021-09-11: 200 * 1024 this->kTensorArenaSize = TENSOR_ARENA_SIZE;
this->tensor_arena = (uint8_t*)malloc_psram_heap(std::string(TAG) + "->tensor_arena", kTensorArenaSize, MALLOC_CAP_SPIRAM); this->tensor_arena = (uint8_t*)psram_get_shared_tensor_arena_memory();
} }
@@ -315,8 +322,7 @@ CTfLiteClass::~CTfLiteClass()
delete this->interpreter; delete this->interpreter;
delete this->error_reporter; delete this->error_reporter;
free_psram_heap(std::string(TAG) + "->modelfile", modelfile); psram_free_shared_tensor_arena_and_model_memory();
free_psram_heap(std::string(TAG) + "->tensor_arena", this->tensor_arena);
} }

View File

@@ -208,6 +208,12 @@
//#define DEBUG_DETAIL_ON //#define DEBUG_DETAIL_ON
/////////////////////////////////////////////
//// PSRAM Allocations ////
/////////////////////////////////////////////
#define MAX_MODEL_SIZE (unsigned int)(1.3 * 1024 * 1024) // Space for the currently largest model (1.1 MB) + some spare
#define TENSOR_ARENA_SIZE 800 * 1024 // Space for the Tensor Arena, (819200 Bytes)
#define IMAGE_SIZE 640 * 480 * 3 // Space for a extracted image (921600 Bytes)
///////////////////////////////////////////// /////////////////////////////////////////////
//// Conditionnal definitions //// //// Conditionnal definitions ////
///////////////////////////////////////////// /////////////////////////////////////////////

View File

@@ -11,9 +11,13 @@
//#include "sdkconfig.h" //#include "sdkconfig.h"
#include "esp_psram.h" #include "esp_psram.h"
#include "esp_pm.h" #include "esp_pm.h"
#include "psram.h"
#include "esp_chip_info.h" #include "esp_chip_info.h"
// SD-Card //////////////////// // SD-Card ////////////////////
//#include "nvs_flash.h" //#include "nvs_flash.h"
#include "esp_vfs_fat.h" #include "esp_vfs_fat.h"
@@ -190,15 +194,6 @@ extern "C" void app_main(void)
// ******************************************** // ********************************************
ESP_LOGI(TAG, "\n\n\n\n================ Start app_main ================="); ESP_LOGI(TAG, "\n\n\n\n================ Start app_main =================");
// Init camera
// ********************************************
PowerResetCamera();
esp_err_t camStatus = Camera.InitCam();
Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
// Init SD card // Init SD card
// ******************************************** // ********************************************
@@ -220,6 +215,105 @@ extern "C" void app_main(void)
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Start ======================"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Start ======================");
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================================================="); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
// Init external PSRAM
// ********************************************
esp_err_t PSRAMStatus = esp_psram_init();
if (PSRAMStatus != ESP_OK) { // ESP_FAIL -> Failed to init PSRAM
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM init failed (" + std::to_string(PSRAMStatus) + ")! PSRAM not found or defective");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
StatusLED(PSRAM_INIT, 1, true);
}
else { // ESP_OK -> PSRAM init OK --> continue to check PSRAM size
size_t psram_size = esp_psram_get_size(); // size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "PSRAM size: " + std::to_string(psram_size) + " byte (" + std::to_string(psram_size/1024/1024) +
"MB / " + std::to_string(psram_size/1024/1024*8) + "MBit)");
// Check PSRAM size
// ********************************************
if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes (32Mbit)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM size >= 4MB (32Mbit) is mandatory to run this application");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
StatusLED(PSRAM_INIT, 2, true);
}
else { // PSRAM size OK --> continue to check heap size
size_t _hsize = getESPHeapSize();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Total heap: " + std::to_string(_hsize) + " byte");
// Check heap memory
// ********************************************
if (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Total heap >= 4000000 byte is mandatory to run this application");
setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL);
StatusLED(PSRAM_INIT, 3, true);
}
else { // HEAP size OK --> continue to reserve shared memory block and check camera init
/* Allocate static PSRAM memory regions */
if (! reserve_psram_shared_region()) {
setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL);
StatusLED(PSRAM_INIT, 3, true);
}
else { // OK
// Init camera
// ********************************************
PowerResetCamera();
esp_err_t camStatus = Camera.InitCam();
Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
// Check camera init
// ********************************************
if (camStatus != ESP_OK) { // Camera init failed, retry to init
char camStatusHex[33];
sprintf(camStatusHex,"0x%02x", camStatus);
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Camera init failed (" + std::string(camStatusHex) + "), retrying...");
PowerResetCamera();
camStatus = Camera.InitCam();
Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
if (camStatus != ESP_OK) { // Camera init failed again
sprintf(camStatusHex,"0x%02x", camStatus);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed (" + std::string(camStatusHex) +
")! Check camera module and/or proper electrical connection");
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
StatusLED(CAM_INIT, 1, true);
}
}
else { // ESP_OK -> Camera init OK --> continue to perform camera framebuffer check
// Camera framebuffer check
// ********************************************
if (!Camera.testCamera()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera framebuffer check failed");
// Easiest would be to simply restart here and try again,
// how ever there seem to be systems where it fails at startup but still work correctly later.
// Therefore we treat it still as successed! */
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
StatusLED(CAM_INIT, 2, false);
}
Camera.LightOnOff(false); // make sure flashlight is off before start of flow
// Print camera infos
// ********************************************
char caminfo[50];
sensor_t * s = esp_camera_sensor_get();
sprintf(caminfo, "PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x", s->id.PID, s->id.VER, s->id.MIDH, s->id.MIDL);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Camera info: " + std::string(caminfo));
}
}
}
}
}
// SD card: basic R/W check // SD card: basic R/W check
// ******************************************** // ********************************************
int iSDCardStatus = SDCardCheckRW(); int iSDCardStatus = SDCardCheckRW();
@@ -374,84 +468,7 @@ extern "C" void app_main(void)
#endif #endif
#endif #endif
// Init external PSRAM
// ********************************************
esp_err_t PSRAMStatus = esp_psram_init();
if (PSRAMStatus == ESP_FAIL) { // ESP_FAIL -> Failed to init PSRAM
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM init failed (" + std::to_string(PSRAMStatus) + ")! PSRAM not found or defective");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
StatusLED(PSRAM_INIT, 1, true);
}
else { // ESP_OK -> PSRAM init OK --> continue to check PSRAM size
size_t psram_size = esp_psram_get_size(); // size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "PSRAM size: " + std::to_string(psram_size) + " byte (" + std::to_string(psram_size/1024/1024) +
"MB / " + std::to_string(psram_size/1024/1024*8) + "MBit)");
// Check PSRAM size
// ********************************************
if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes (32Mbit)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "PSRAM size >= 4MB (32Mbit) is mandatory to run this application");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
StatusLED(PSRAM_INIT, 2, true);
}
else { // PSRAM size OK --> continue to check heap size
size_t _hsize = getESPHeapSize();
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Total heap: " + std::to_string(_hsize) + " byte");
// Check heap memory
// ********************************************
if (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Total heap >= 4000000 byte is mandatory to run this application");
setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL);
StatusLED(PSRAM_INIT, 3, true);
}
else { // HEAP size OK --> continue to check camera init
// Check camera init
// ********************************************
if (camStatus != ESP_OK) { // Camera init failed, retry to init
char camStatusHex[33];
sprintf(camStatusHex,"0x%02x", camStatus);
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Camera init failed (" + std::string(camStatusHex) + "), retrying...");
PowerResetCamera();
camStatus = Camera.InitCam();
Camera.LightOnOff(false);
xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay * CONFIG_FREERTOS_HZ/portTICK_PERIOD_MS);
vTaskDelay( xDelay );
if (camStatus != ESP_OK) { // Camera init failed again
sprintf(camStatusHex,"0x%02x", camStatus);
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera init failed (" + std::string(camStatusHex) +
")! Check camera module and/or proper electrical connection");
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
StatusLED(CAM_INIT, 1, true);
}
}
else { // ESP_OK -> Camera init OK --> continue to perform camera framebuffer check
// Camera framebuffer check
// ********************************************
if (!Camera.testCamera()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera framebuffer check failed");
// Easiest would be to simply restart here and try again,
// how ever there seem to be systems where it fails at startup but still work correctly later.
// Therefore we treat it still as successed! */
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
StatusLED(CAM_INIT, 2, false);
}
Camera.LightOnOff(false); // make sure flashlight is off before start of flow
// Print camera infos
// ********************************************
char caminfo[50];
sensor_t * s = esp_camera_sensor_get();
sprintf(caminfo, "PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x", s->id.PID, s->id.VER, s->id.MIDH, s->id.MIDL);
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Camera info: " + std::string(caminfo));
}
}
}
}
// Print Device info // Print Device info
// ******************************************** // ********************************************

View File

@@ -101,8 +101,9 @@ CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=40960 CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=40960
CONFIG_SPIRAM_CACHE_WORKAROUND=y CONFIG_SPIRAM_CACHE_WORKAROUND=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y CONFIG_SPIRAM_IGNORE_NOTFOUND=y
#CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y => Leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200
#CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y => Leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200 CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
@@ -124,7 +125,7 @@ CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED=y
CONFIG_MQTT_USE_CORE_0=y CONFIG_MQTT_USE_CORE_0=y
CONFIG_MQTT_USE_CUSTOM_CONFIG=y CONFIG_MQTT_USE_CUSTOM_CONFIG=y
#CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS=5000 #CONFIG_MQTT_OUTBOX_EXPIRED_TIMEOUT_MS=5000
#CONFIG_MQTT_CUSTOM_OUTBOX=y # -> Use custom outbox in components/jomjol_mqtt/mqtt_outbox.h/cpp. If USE_PSRAM is enabled in there, it will save 10 kBytes of internal RAM. How ever it also leads to memory fragmentation, see https://github.com/jomjol/AI-on-the-edge-device/issues/2200 CONFIG_MQTT_CUSTOM_OUTBOX=y
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n