diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb859cc2..17fb77879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Command ``SetSensor1..127 0|1`` to globally disable individual sensor driver - Support for CAN bus and Freedom Won Battery Management System by Marius Bezuidenhout (#12651) +- Disable PSRAM on unsupported hardware ## [9.5.0.2] 20210714 ### Added diff --git a/lib/lib_display/UDisplay/uDisplay.cpp b/lib/lib_display/UDisplay/uDisplay.cpp index 7e28086db..0a089b6f1 100755 --- a/lib/lib_display/UDisplay/uDisplay.cpp +++ b/lib/lib_display/UDisplay/uDisplay.cpp @@ -380,6 +380,7 @@ uDisplay::uDisplay(char *lp) : Renderer(800, 600) { Renderer *uDisplay::Init(void) { + extern bool UsePSRAM(void); // for any bpp below native 16 bits, we allocate a local framebuffer to copy into if (ep_mode || bpp < 16) { @@ -387,7 +388,7 @@ Renderer *uDisplay::Init(void) { #ifdef ESP8266 framebuffer = (uint8_t*)calloc((gxs * gys * bpp) / 8, 1); #else - if (psramFound()) { + if (UsePSRAM()) { framebuffer = (uint8_t*)heap_caps_malloc((gxs * gys * bpp) / 8, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { framebuffer = (uint8_t*)calloc((gxs * gys * bpp) / 8, 1); diff --git a/tasmota/support_esp.ino b/tasmota/support_esp.ino index 9ec26b785..babda7bef 100644 --- a/tasmota/support_esp.ino +++ b/tasmota/support_esp.ino @@ -464,22 +464,28 @@ uint8_t* FlashDirectAccess(void) { return data; } +// new function to check whether PSRAM is present and supported (i.e. required pacthes are present) +bool UsePSRAM(void) { + static bool can_use_psram = CanUsePSRAM(); + return psramFound() && can_use_psram; +} + void *special_malloc(uint32_t size) { - if (psramFound()) { + if (UsePSRAM()) { return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { return malloc(size); } } void *special_realloc(void *ptr, size_t size) { - if (psramFound()) { + if (UsePSRAM()) { return heap_caps_realloc(ptr, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { return realloc(ptr, size); } } void *special_calloc(size_t num, size_t size) { - if (psramFound()) { + if (UsePSRAM()) { return heap_caps_calloc(num, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { return calloc(num, size); @@ -675,6 +681,36 @@ typedef struct { return F("ESP32"); } +/* + * ESP32 v1 and v2 needs some special patches to use PSRAM. + * Standard Tasmota 32 do not include those patches. + * If using ESP32 v1, please add: `-mfix-esp32-psram-cache-issue -lc-psram-workaround -lm-psram-workaround` + * + * This function returns true if the chip supports PSRAM natively (v3) or if the + * patches are present. + */ +bool CanUsePSRAM(void) { +#ifdef HAS_PSRAM_FIX + return true; +#endif +#ifdef CONFIG_IDF_TARGET_ESP32 + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + if ((CHIP_ESP32 == chip_info.model) && (chip_info.revision < 3)) { + return false; + } +#if ESP_IDF_VERSION_MAJOR < 4 + uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); + uint32_t pkg_version = chip_ver & 0x7; + if ((CHIP_ESP32 == chip_info.model) && (pkg_version >= 6)) { + return false; // support for embedded PSRAM of ESP32-PICO-V3-02 requires esp-idf 4.4 + } +#endif // ESP_IDF_VERSION_MAJOR < 4 + +#endif // CONFIG_IDF_TARGET_ESP32 + return true; +} + #endif // ESP32 /*********************************************************************************************\ diff --git a/tasmota/tasmota.ino b/tasmota/tasmota.ino index 52dad8f3e..721770637 100644 --- a/tasmota/tasmota.ino +++ b/tasmota/tasmota.ino @@ -276,6 +276,14 @@ void setup(void) { // AddLog(LOG_LEVEL_INFO, PSTR("ADR: Settings %p, Log %p"), Settings, TasmotaGlobal.log_buffer); AddLog(LOG_LEVEL_INFO, PSTR("HDW: %s"), GetDeviceHardware().c_str()); +#ifdef ESP32 + AddLog(LOG_LEVEL_DEBUG, PSTR("HDW: psramFound=%i CanUsePSRAM=%i"), psramFound(), CanUsePSRAM()); +#endif // ESP32 +#if defined(ESP32) && !defined(HAS_PSRAM_FIX) + if (psramFound() && !CanUsePSRAM()) { + AddLog(LOG_LEVEL_INFO, PSTR("HDW: PSRAM is disabled, requires specific compilation on this hardware (see doc)")); + } +#endif // ESP32 #ifdef USE_UFILESYS UfsInit(); // xdrv_50_filesystem.ino diff --git a/tasmota/xdrv_01_webserver.ino b/tasmota/xdrv_01_webserver.ino index 181240b01..2705db6ab 100644 --- a/tasmota/xdrv_01_webserver.ino +++ b/tasmota/xdrv_01_webserver.ino @@ -2372,7 +2372,7 @@ void HandleInformation(void) #ifdef ESP32 int32_t freeMaxMem = 100 - (int32_t)(ESP_getMaxAllocHeap() * 100 / ESP_getFreeHeap()); WSContentSend_PD(PSTR("}1" D_FREE_MEMORY "}2%1_f kB (" D_FRAGMENTATION " %d%%)"), &freemem, freeMaxMem); - if (psramFound()) { + if (UsePSRAM()) { WSContentSend_P(PSTR("}1" D_PSR_MAX_MEMORY "}2%d kB"), ESP.getPsramSize() / 1024); WSContentSend_P(PSTR("}1" D_PSR_FREE_MEMORY "}2%d kB"), ESP.getFreePsram() / 1024); } diff --git a/tasmota/xdrv_42_i2s_audio.ino b/tasmota/xdrv_42_i2s_audio.ino index 1ab15e4ee..c7b0c460b 100644 --- a/tasmota/xdrv_42_i2s_audio.ino +++ b/tasmota/xdrv_42_i2s_audio.ino @@ -280,12 +280,12 @@ void I2S_Init(void) { mp3ram = nullptr; #ifdef ESP32 - if (psramFound()) { + if (UsePSRAM()) { mp3ram = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } #ifdef USE_I2S_WEBRADIO - if (psramFound()) { + if (UsePSRAM()) { preallocateBuffer = heap_caps_malloc(preallocateBufferSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); preallocateCodec = heap_caps_malloc(preallocateCodecSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } else { diff --git a/tasmota/xdrv_52_3_berry_tasmota.ino b/tasmota/xdrv_52_3_berry_tasmota.ino index 60293d201..a35319ca7 100644 --- a/tasmota/xdrv_52_3_berry_tasmota.ino +++ b/tasmota/xdrv_52_3_berry_tasmota.ino @@ -181,7 +181,7 @@ extern "C" { map_insert_int(vm, "heap_free", ESP_getFreeHeap() / 1024); int32_t freeMaxMem = 100 - (int32_t)(ESP_getMaxAllocHeap() * 100 / ESP_getFreeHeap()); map_insert_int(vm, "frag", freeMaxMem); - if (psramFound()) { + if (UsePSRAM()) { map_insert_int(vm, "psram", ESP.getPsramSize() / 1024); map_insert_int(vm, "psram_free", ESP.getFreePsram() / 1024); } diff --git a/tasmota/xdrv_54_lvgl.ino b/tasmota/xdrv_54_lvgl.ino index 68522a823..72242d4a3 100644 --- a/tasmota/xdrv_54_lvgl.ino +++ b/tasmota/xdrv_54_lvgl.ino @@ -442,13 +442,13 @@ void start_lvgl(const char * uconfig) { // initialize the FreeType renderer lv_freetype_init(USE_LVGL_FREETYPE_MAX_FACES, USE_LVGL_FREETYPE_MAX_SIZES, - psramFound() ? USE_LVGL_FREETYPE_MAX_BYTES_PSRAM : USE_LVGL_FREETYPE_MAX_BYTES); + UsePSRAM() ? USE_LVGL_FREETYPE_MAX_BYTES_PSRAM : USE_LVGL_FREETYPE_MAX_BYTES); #endif #ifdef USE_LVGL_PNG_DECODER lv_png_init(); #endif // USE_LVGL_PNG_DECODER - if (psramFound()) { + if (UsePSRAM()) { lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE_PSRAM); } diff --git a/tasmota/xdrv_81_esp32_webcam.ino b/tasmota/xdrv_81_esp32_webcam.ino index e3b15fd3c..617af46fb 100644 --- a/tasmota/xdrv_81_esp32_webcam.ino +++ b/tasmota/xdrv_81_esp32_webcam.ino @@ -252,7 +252,7 @@ uint32_t WcSetup(int32_t fsiz) { // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. - bool psram = psramFound(); + bool psram = UsePSRAM(); if (psram) { config.frame_size = FRAMESIZE_UXGA; config.jpeg_quality = 10; diff --git a/tasmota/xsns_75_prometheus.ino b/tasmota/xsns_75_prometheus.ino index d997016b5..f15c569f6 100644 --- a/tasmota/xsns_75_prometheus.ino +++ b/tasmota/xsns_75_prometheus.ino @@ -125,7 +125,7 @@ void HandleMetrics(void) { int32_t freeMaxMem = 100 - (int32_t)(ESP_getMaxAllocHeap() * 100 / ESP_getFreeHeap()); WSContentSend_PD(PSTR("# TYPE tasmota_memory_bytes gauge\ntasmota_memory_bytes{memory=\"Ram\"} %d\n"), ESP_getFreeHeap()); WSContentSend_PD(PSTR("# TYPE tasmota_memory_ratio gauge\ntasmota_memory_ratio{memory=\"Fragmentation\"} %d)"), freeMaxMem / 100); - if (psramFound()) { + if (UsePSRAM()) { WSContentSend_P(PSTR("# TYPE tasmota_memory_bytes gauge\ntasmota_memory_bytes{memory=\"Psram\"} %d\n"), ESP.getFreePsram() ); } #else // ESP32