mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-08 20:46:52 +03:00
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:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 ////
|
||||||
/////////////////////////////////////////////
|
/////////////////////////////////////////////
|
||||||
|
|||||||
@@ -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
|
||||||
// ********************************************
|
// ********************************************
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user