After rebasing, it was found out that flushing the cache drops the writeback-pending psram cache lines on the ground. We now evict these by reading 64/128K of memory before flushing the cache. Also fixes a snafu in psram cache mode (inverted hi/lo and even/odd selectors) as well as an option to not let the heap allocator touch the psram.
This commit is contained in:
parent
e51f5399db
commit
15514b804d
6 changed files with 85 additions and 8 deletions
|
@ -124,8 +124,17 @@ config MEMMAP_SPIRAM_SIZE
|
||||||
help
|
help
|
||||||
Size of external SPI RAM
|
Size of external SPI RAM
|
||||||
|
|
||||||
|
config MEMMAP_SPIRAM_NO_HEAPALLOC
|
||||||
|
bool "Initialize PSRAM memory but do not add to heap allocator"
|
||||||
|
default "n"
|
||||||
|
help
|
||||||
|
This initializes the PSRAM as normal, but does not make the heap allocator aware of the
|
||||||
|
memory region. You can use the memory region from 0x3F800000-0x3FBFFFFF freely, but
|
||||||
|
need to do your own memory management there.
|
||||||
|
|
||||||
config MEMMAP_SPIRAM_TEST
|
config MEMMAP_SPIRAM_TEST
|
||||||
bool "On SPI RAM init, do a quick memory test"
|
bool "On SPI RAM init, do a quick memory test"
|
||||||
|
depends on !MEMMAP_SPIRAM_NO_HEAPALLOC
|
||||||
default "n"
|
default "n"
|
||||||
help
|
help
|
||||||
This does a quick memory test on boot-up. This takes about a second for 4MiB of SPI RAM.
|
This does a quick memory test on boot-up. This takes about a second for 4MiB of SPI RAM.
|
||||||
|
@ -142,7 +151,13 @@ config MEMMAP_SPIRAM_ENABLE_MALLOC
|
||||||
config MEMMAP_SPIRAM_ALLOC_LIMIT_INTERNAL
|
config MEMMAP_SPIRAM_ALLOC_LIMIT_INTERNAL
|
||||||
int "Always put malloc()s smaller than this size, in bytes, in internal RAM"
|
int "Always put malloc()s smaller than this size, in bytes, in internal RAM"
|
||||||
depends on MEMMAP_SPIRAM_ENABLE_MALLOC
|
depends on MEMMAP_SPIRAM_ENABLE_MALLOC
|
||||||
default 1024
|
range 4096 4194304
|
||||||
|
default 4096
|
||||||
|
help
|
||||||
|
Always tries to allocate heap allocation requests smaller than defined here in
|
||||||
|
internal RAM instead of PSRAM; allocations larger than this will initially
|
||||||
|
go to PSRAM. If either of these initial allocations fails, allocation in the
|
||||||
|
other memory region will be attempted as a backup option.
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -88,10 +88,10 @@ extern volatile int port_xSchedulerRunning[2];
|
||||||
static const char* TAG = "cpu_start";
|
static const char* TAG = "cpu_start";
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_MEMMAP_SMP
|
#if CONFIG_FREERTOS_UNICORE
|
||||||
#define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
|
|
||||||
#else
|
|
||||||
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
||||||
|
#else
|
||||||
|
#define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -119,6 +119,8 @@ void IRAM_ATTR call_start_cpu0()
|
||||||
if ( psram_enable(PSRAM_CACHE_F40M_S40M, PSRAM_MODE) != ESP_OK) {
|
if ( psram_enable(PSRAM_CACHE_F40M_S40M, PSRAM_MODE) != ESP_OK) {
|
||||||
ESP_EARLY_LOGE(TAG, "PSRAM enabled but initialization failed. Bailing out.");
|
ESP_EARLY_LOGE(TAG, "PSRAM enabled but initialization failed. Bailing out.");
|
||||||
abort();
|
abort();
|
||||||
|
} else {
|
||||||
|
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", (PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)":"normal (1-core");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -272,7 +272,7 @@ void heap_alloc_caps_init() {
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CONFIG_MEMMAP_SPIRAM_ENABLE
|
#if CONFIG_MEMMAP_SPIRAM_ENABLE && !CONFIG_MEMMAP_SPIRAM_NO_HEAPALLOC
|
||||||
if (CONFIG_MEMMAP_SPIRAM_SIZE < 0x400000) {
|
if (CONFIG_MEMMAP_SPIRAM_SIZE < 0x400000) {
|
||||||
disable_mem_region((void*)0x3f800000+CONFIG_MEMMAP_SPIRAM_SIZE, (void*)0x3fc00000); //Disable unused SPI SRAM region
|
disable_mem_region((void*)0x3f800000+CONFIG_MEMMAP_SPIRAM_SIZE, (void*)0x3fc00000); //Disable unused SPI SRAM region
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,4 +51,14 @@ typedef enum {
|
||||||
*/
|
*/
|
||||||
esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
|
esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Write back all psram data contained in the cache
|
||||||
|
*
|
||||||
|
* Before the flash/psram cache is flushed (=invalidated on esp32), the psram
|
||||||
|
* data that resides there needs to be written back This routine does that.
|
||||||
|
*/
|
||||||
|
void esp_psram_writeback_cache();
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -550,11 +550,11 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
|
||||||
CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL|DPORT_PRO_DRAM_SPLIT);
|
CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL|DPORT_PRO_DRAM_SPLIT);
|
||||||
CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL|DPORT_APP_DRAM_SPLIT);
|
CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL|DPORT_APP_DRAM_SPLIT);
|
||||||
if (vaddrmode == PSRAM_VADDR_MODE_LOWHIGH) {
|
if (vaddrmode == PSRAM_VADDR_MODE_LOWHIGH) {
|
||||||
SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_SPLIT);
|
|
||||||
SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_SPLIT);
|
|
||||||
} else if (vaddrmode == PSRAM_VADDR_MODE_EVENODD) {
|
|
||||||
SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL);
|
SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL);
|
||||||
SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL);
|
SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL);
|
||||||
|
} else if (vaddrmode == PSRAM_VADDR_MODE_EVENODD) {
|
||||||
|
SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_SPLIT);
|
||||||
|
SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_SPLIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DRAM1|DPORT_PRO_CACHE_MASK_OPSDRAM); //use Dram1 to visit ext sram.
|
CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DRAM1|DPORT_PRO_CACHE_MASK_OPSDRAM); //use Dram1 to visit ext sram.
|
||||||
|
@ -566,3 +566,46 @@ static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psra
|
||||||
CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
|
CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Before flushing the cache, if psram is enabled, we need to write back the data in the cache to the psram first,
|
||||||
|
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this. Yes, we should be
|
||||||
|
able to optimize this. Later.
|
||||||
|
*/
|
||||||
|
void IRAM_ATTR esp_psram_writeback_cache()
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
volatile int i=0;
|
||||||
|
volatile uint8_t *psram=(volatile uint8_t*)0x3F800000;
|
||||||
|
int cacheWasDisabled=0;
|
||||||
|
|
||||||
|
//We need cache enabled for this to work. Re-enable it if needed; make sure we
|
||||||
|
//disable it again on exit as well.
|
||||||
|
if (REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
|
||||||
|
cacheWasDisabled|=(1<<0);
|
||||||
|
SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
|
||||||
|
}
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
if (REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
|
||||||
|
cacheWasDisabled|=(1<<1);
|
||||||
|
SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_FREERTOS_UNICORE
|
||||||
|
for (x=0; x<1024*64; x+=32) {
|
||||||
|
i+=psram[x];
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for (x=0; x<1024*64; x+=32) {
|
||||||
|
i+=psram[x];
|
||||||
|
i+=psram[x+(1024*1024*2)+(1024*64)]; //address picked to also clear cache of app cpu in low/high mode
|
||||||
|
}
|
||||||
|
ets_printf("%x\n", i);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cacheWasDisabled&(1<<0)) SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
|
||||||
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
|
if (cacheWasDisabled&(1<<1)) SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "esp_flash_encrypt.h"
|
#include "esp_flash_encrypt.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "cache_utils.h"
|
#include "cache_utils.h"
|
||||||
|
#include "esp_psram.h"
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Enable built-in checks in queue.h in debug builds
|
// Enable built-in checks in queue.h in debug builds
|
||||||
|
@ -193,6 +194,9 @@ esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_
|
||||||
entire cache.
|
entire cache.
|
||||||
*/
|
*/
|
||||||
if (!did_flush && need_flush) {
|
if (!did_flush && need_flush) {
|
||||||
|
#if CONFIG_MEMMAP_SPIRAM_ENABLE
|
||||||
|
esp_psram_writeback_cache();
|
||||||
|
#endif
|
||||||
Cache_Flush(0);
|
Cache_Flush(0);
|
||||||
Cache_Flush(1);
|
Cache_Flush(1);
|
||||||
}
|
}
|
||||||
|
@ -298,6 +302,9 @@ static inline IRAM_ATTR bool update_written_pages(size_t start_addr, size_t leng
|
||||||
tricky because mmaped memory can be used on un-pinned
|
tricky because mmaped memory can be used on un-pinned
|
||||||
cores, or the pointer passed between CPUs.
|
cores, or the pointer passed between CPUs.
|
||||||
*/
|
*/
|
||||||
|
#if CONFIG_MEMMAP_SPIRAM_ENABLE
|
||||||
|
esp_psram_writeback_cache();
|
||||||
|
#endif
|
||||||
Cache_Flush(0);
|
Cache_Flush(0);
|
||||||
#ifndef CONFIG_FREERTOS_UNICORE
|
#ifndef CONFIG_FREERTOS_UNICORE
|
||||||
Cache_Flush(1);
|
Cache_Flush(1);
|
||||||
|
|
Loading…
Reference in a new issue