Continue boot on bad PSRAM (#1558)

* add sensor status, show special index/setup page in case of a critical error

* continue booting on PSRAM error

* Update main.cpp

added log messages

* init PSRAM and add more log messages

* cleanup of init checks

* .

* .

* .

Co-authored-by: CaCO3 <caco@ruinelli.ch>
This commit is contained in:
CaCO3
2022-12-12 16:57:14 +01:00
committed by GitHub
parent 6863e637aa
commit 24f10b4683
6 changed files with 133 additions and 29 deletions

View File

@@ -36,6 +36,8 @@ static const char* TAG = "HELPER";
using namespace std; using namespace std;
unsigned int systemStatus = 0;
sdmmc_cid_t SDCardCid; sdmmc_cid_t SDCardCid;
sdmmc_csd_t SDCardCsd; sdmmc_csd_t SDCardCsd;
@@ -771,6 +773,38 @@ string getMac(void) {
return macFormated; return macFormated;
} }
void setSystemStatusFlag(SystemStatusFlag_t flag) {
systemStatus = systemStatus | flag; // set bit
char buf[20];
snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
}
void clearSystemStatusFlag(SystemStatusFlag_t flag) {
systemStatus = systemStatus | ~flag; // clear bit
char buf[20];
snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
}
int getSystemStatus(void) {
return systemStatus;
}
bool isSetSystemStatusFlag(SystemStatusFlag_t flag) {
//ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
if ((systemStatus & flag) == flag) {
return true;
}
else {
return false;
}
}
string getResetReason(void) { string getResetReason(void) {
std::string reasonText; std::string reasonText;

View File

@@ -63,6 +63,27 @@ string getSDCardCapacity();
string getSDCardSectorSize(); string getSDCardSectorSize();
string getMac(void); string getMac(void);
/* Error bit fields
One bit per error
Make sure it matches https://github.com/jomjol/AI-on-the-edge-device/wiki/Error-Codes */
enum SystemStatusFlag_t { // One bit per error
// First Byte
SYSTEM_STATUS_PSRAM_BAD = 1 << 0, // 4, Critical Error
SYSTEM_STATUS_HEAP_TOO_SMALL = 1 << 1, // 8, Critical Error
SYSTEM_STATUS_CAM_BAD = 1 << 2, // 1, Critical Error
// Second Byte
SYSTEM_STATUS_CAM_FB_BAD = 1 << (0+8), // 2, Flow still might work
SYSTEM_STATUS_NTP_BAD = 1 << (1+8), // 16, Flow will work but time will be wrong
};
void setSystemStatusFlag(SystemStatusFlag_t flag);
void clearSystemStatusFlag(SystemStatusFlag_t flag);
int getSystemStatus(void);
bool isSetSystemStatusFlag(SystemStatusFlag_t flag);
string getResetReason(void); string getResetReason(void);
std::string getFormatedUptime(bool compact); std::string getFormatedUptime(bool compact);

View File

@@ -65,5 +65,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*)
# idf_component_register(SRCS ${app_sources}) # idf_component_register(SRCS ${app_sources})
idf_component_register(SRCS ${app_sources} idf_component_register(SRCS ${app_sources}
INCLUDE_DIRS ".") INCLUDE_DIRS "."
# REQUIRES esp_psram) # comming in IDF 5.0
)

View File

@@ -5,6 +5,9 @@
#include "driver/gpio.h" #include "driver/gpio.h"
#include "sdkconfig.h" #include "sdkconfig.h"
//#include "esp_psram.h" // Comming in IDF 5.0, see https://docs.espressif.com/projects/esp-idf/en/v5.0-beta1/esp32/migration-guides/release-5.x/system.html?highlight=esp_psram_get_size
#include "spiram.h"
#include "esp_spiram.h"
// SD-Card //////////////////// // SD-Card ////////////////////
#include "nvs_flash.h" #include "nvs_flash.h"
@@ -122,7 +125,7 @@ bool Init_NVS_SDCard()
return true; return true;
} }
void task_NoSDBlink(void *pvParameter) void task_MainInitError_blink(void *pvParameter)
{ {
gpio_pad_select_gpio(BLINK_GPIO); gpio_pad_select_gpio(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
@@ -147,7 +150,6 @@ void task_NoSDBlink(void *pvParameter)
extern "C" void app_main(void) extern "C" void app_main(void)
{ {
TickType_t xDelay; TickType_t xDelay;
bool initSucessful = true;
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
@@ -160,9 +162,9 @@ extern "C" void app_main(void)
if (!Init_NVS_SDCard()) if (!Init_NVS_SDCard())
{ {
xTaskCreate(&task_NoSDBlink, "task_NoSDBlink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL); xTaskCreate(&task_MainInitError_blink, "task_MainInitError_blink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL);
return; return; // No way to continue without SD-Card!
}; }
string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + \ string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + \
"', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME) + \ "', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME) + \
@@ -216,6 +218,7 @@ extern "C" void app_main(void)
if (!setup_time()) { if (!setup_time()) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "NTP Initialization failed!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "NTP Initialization failed!");
setSystemStatusFlag(SYSTEM_STATUS_NTP_BAD);
} }
setBootTime(); setBootTime();
@@ -231,13 +234,32 @@ extern "C" void app_main(void)
std::string zw = gettimestring("%Y%m%d-%H%M%S"); std::string zw = gettimestring("%Y%m%d-%H%M%S");
ESP_LOGD(TAG, "time %s", zw.c_str()); ESP_LOGD(TAG, "time %s", zw.c_str());
/* Check if PSRAM can be initalized */
esp_err_t ret;
ret = esp_spiram_init();
if (ret == ESP_FAIL) { // Failed to init PSRAM, most likely not available or broken
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize PSRAM (" + std::to_string(ret) + ")!");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Either your device misses the PSRAM chip or it is broken!");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
}
else { // PSRAM init ok
/* Check if PSRAM provides at least 4 MB */
size_t psram_size = esp_spiram_get_size();
// size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "The device has " + std::to_string(psram_size/1024/1024) + " MBytes of PSRAM");
if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "At least 4 MBytes are required!");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Does the device really have a 4 Mbytes PSRAM?");
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
}
}
/* Check available Heap memory */
size_t _hsize = getESPHeapSize(); size_t _hsize = getESPHeapSize();
if (_hsize < 4000000) // Check for a bit less than 4 MB (but clearly over 2 MB) 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, "Not enough Heap memory available. Expected around 4 MBytes, but only " + std::to_string(_hsize) + " Bytes are available! That is not enough for this firmware!");
std::string _zws = "Not enough PSRAM available. Expected around 4 MBytes - available: " + std::to_string((float)_hsize/1024/1024) + " MBytes!"; setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL);
_zws = _zws + "\nEither not initialized, too small (2 MByte only) or not present at all. Firmware cannot start!!"; } else { // Heap memory is ok
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zws);
} else { // Bad Camera Status, retry init
if (camStatus != ESP_OK) { if (camStatus != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to initialize camera module, retrying..."); LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to initialize camera module, retrying...");
@@ -251,7 +273,7 @@ extern "C" void app_main(void)
if (camStatus != ESP_OK) { if (camStatus != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize camera module!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize camera module!");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!");
initSucessful = false; setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
} }
} else { // Test Camera } else { // Test Camera
camera_fb_t * fb = esp_camera_fb_get(); camera_fb_t * fb = esp_camera_fb_get();
@@ -259,8 +281,8 @@ extern "C" void app_main(void)
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!"); LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!");
/* Easiest would be to simply restart here and try again, /* 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 corectly later. how ever there seem to be systems where it fails at startup but still work corectly later.
Therefore we treat it still as successed! Therefore we treat it still as successed! */
//initSucessful = false; */ setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
} }
else { else {
esp_camera_fb_return(fb); esp_camera_fb_return(fb);
@@ -269,8 +291,6 @@ extern "C" void app_main(void)
} }
} }
xDelay = 2000 / portTICK_PERIOD_MS; xDelay = 2000 / portTICK_PERIOD_MS;
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay*10); ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay*10);
vTaskDelay( xDelay ); vTaskDelay( xDelay );
@@ -291,17 +311,24 @@ extern "C" void app_main(void)
ESP_LOGD(TAG, "vor reg server main"); ESP_LOGD(TAG, "vor reg server main");
register_server_main_uri(server, "/sdcard"); register_server_main_uri(server, "/sdcard");
if (initSucessful) {
/* Testing */
//setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
//setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
/* Main Init has successed or only an error which allows to continue operation */
if (getSystemStatus() == 0) { // No error flag is set
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!");
ESP_LOGD(TAG, "vor do autostart"); ESP_LOGD(TAG, "vor do autostart");
TFliteDoAutoStart(); TFliteDoAutoStart();
} }
else { // Initialization failed else if (isSetSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD) || // Non critical errors occured, we try to continue...
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart in 5 minutes!"); isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) {
vTaskDelay(60*4000 / portTICK_RATE_MS); // Wait 4 minutes to give time to do an OTA or fetch the log LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with errors, but trying to continue...");
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart in 1 minute!"); ESP_LOGD(TAG, "vor do autostart");
vTaskDelay(60*1000 / portTICK_RATE_MS); // Wait 1 minute to give time to do an OTA or fetch the log TFliteDoAutoStart();
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart now!"); }
doReboot(); else { // Any other error is critical and makes running the flow impossible.
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Not starting flows!");
} }
} }

View File

@@ -230,10 +230,30 @@ esp_err_t hello_main_handler(httpd_req_t *req)
} }
} }
if (filetosend == "/sdcard/html/index.html" && isSetupModusActive()) { if (filetosend == "/sdcard/html/index.html") {
if (isSetSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD) || // Initialization failed with crritical errors!
isSetSystemStatusFlag(SYSTEM_STATUS_CAM_BAD)) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "We have a critical error, not serving main page!");
char buf[20];
std::string message = "<h1>AI on the Edge Device</h1><b>We have one or more critical errors:</b><br>";
for (int i = 0; i < 32; i++) {
if (isSetSystemStatusFlag((SystemStatusFlag_t)(1<<i))) {
snprintf(buf, sizeof(buf), "0x%08X", 1<<i);
message += std::string(buf) + "<br>";
}
}
message += "<br>Please check <a href=\"https://github.com/jomjol/AI-on-the-edge-device/wiki/Error-Codes\" target=_blank>github.com/jomjol/AI-on-the-edge-device/wiki/Error-Codes</a> for more information!";
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, message.c_str());
return ESP_FAIL;
}
else if (isSetupModusActive()) {
ESP_LOGD(TAG, "System is in setup mode --> index.html --> setup.html"); ESP_LOGD(TAG, "System is in setup mode --> index.html --> setup.html");
filetosend = "/sdcard/html/setup.html"; filetosend = "/sdcard/html/setup.html";
} }
}
ESP_LOGD(TAG, "Filename: %s", filename); ESP_LOGD(TAG, "Filename: %s", filename);

View File

@@ -36,6 +36,7 @@ CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384 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_ESP_INT_WDT_TIMEOUT_MS=300 CONFIG_ESP_INT_WDT_TIMEOUT_MS=300