// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "esp32-hal.h" #if CONFIG_SPIRAM_SUPPORT || CONFIG_SPIRAM #include "soc/efuse_reg.h" #include "esp_heap_caps.h" #include "esp_system.h" #ifdef ESP_IDF_VERSION_MAJOR // IDF 4+ #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 #include "esp32/spiram.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/spiram.h" #include "esp32s2/rom/cache.h" #else #error Target CONFIG_IDF_TARGET is not supported #endif #else // ESP32 Before IDF 4.0 #include "esp_spiram.h" #endif static volatile bool spiramDetected = false; static volatile bool spiramFailed = false; bool psramInit(){ if (spiramDetected) { return true; } #ifndef CONFIG_SPIRAM_BOOT_INIT if (spiramFailed) { return false; } #if CONFIG_IDF_TARGET_ESP32 uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t pkg_ver = chip_ver & 0x7; if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { spiramFailed = true; log_w("PSRAM not supported!"); return false; } #elif CONFIG_IDF_TARGET_ESP32S2 extern void esp_config_data_cache_mode(void); esp_config_data_cache_mode(); Cache_Enable_DCache(0); #endif if (esp_spiram_init() != ESP_OK) { spiramFailed = true; log_w("PSRAM init failed!"); #if CONFIG_IDF_TARGET_ESP32 pinMatrixOutDetach(16, false, false); pinMatrixOutDetach(17, false, false); #endif return false; } esp_spiram_init_cache(); if (!esp_spiram_test()) { spiramFailed = true; log_e("PSRAM test failed!"); return false; } if (esp_spiram_add_to_heapalloc() != ESP_OK) { spiramFailed = true; log_e("PSRAM could not be added to the heap!"); return false; } #if CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL && !CONFIG_ARDUINO_ISR_IRAM heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL); #endif #endif spiramDetected = true; log_d("PSRAM enabled"); return true; } bool ARDUINO_ISR_ATTR psramFound(){ return spiramDetected; } void ARDUINO_ISR_ATTR *ps_malloc(size_t size){ if(!spiramDetected){ return NULL; } return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){ if(!spiramDetected){ return NULL; } return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){ if(!spiramDetected){ return NULL; } return heap_caps_realloc(ptr, size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } #else bool psramInit(){ return false; } bool ARDUINO_ISR_ATTR psramFound(){ return false; } void ARDUINO_ISR_ATTR *ps_malloc(size_t size){ return NULL; } void ARDUINO_ISR_ATTR *ps_calloc(size_t n, size_t size){ return NULL; } void ARDUINO_ISR_ATTR *ps_realloc(void *ptr, size_t size){ return NULL; } #endif