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:
Jeroen Domburg 2017-03-07 18:38:27 +08:00
parent 96be5f3700
commit 671787a966
6 changed files with 85 additions and 8 deletions

View file

@ -173,8 +173,17 @@ config MEMMAP_SPIRAM_SIZE
help
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
bool "On SPI RAM init, do a quick memory test"
depends on !MEMMAP_SPIRAM_NO_HEAPALLOC
default "n"
help
This does a quick memory test on boot-up. This takes about a second for 4MiB of SPI RAM.
@ -191,7 +200,13 @@ config MEMMAP_SPIRAM_ENABLE_MALLOC
config MEMMAP_SPIRAM_ALLOC_LIMIT_INTERNAL
int "Always put malloc()s smaller than this size, in bytes, in internal RAM"
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

View file

@ -95,10 +95,10 @@ extern volatile int port_xSchedulerRunning[2];
static const char* TAG = "cpu_start";
#if CONFIG_MEMMAP_SMP
#define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
#else
#if CONFIG_FREERTOS_UNICORE
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
#else
#define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
#endif
/*
@ -147,6 +147,8 @@ void IRAM_ATTR call_start_cpu0()
if ( psram_enable(PSRAM_CACHE_F40M_S40M, PSRAM_MODE) != ESP_OK) {
ESP_EARLY_LOGE(TAG, "PSRAM enabled but initialization failed. Bailing out.");
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

View file

@ -272,7 +272,7 @@ void heap_alloc_caps_init() {
#endif
#endif
#if CONFIG_MEMMAP_SPIRAM_ENABLE
#if CONFIG_MEMMAP_SPIRAM_ENABLE && !CONFIG_MEMMAP_SPIRAM_NO_HEAPALLOC
if (CONFIG_MEMMAP_SPIRAM_SIZE < 0x400000) {
disable_mem_region((void*)0x3f800000+CONFIG_MEMMAP_SPIRAM_SIZE, (void*)0x3fc00000); //Disable unused SPI SRAM region
}

View file

@ -51,4 +51,14 @@ typedef enum {
*/
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

View file

@ -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_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL|DPORT_APP_DRAM_SPLIT);
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_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.
@ -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)
}
/*
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
}

View file

@ -31,6 +31,7 @@
#include "esp_flash_encrypt.h"
#include "esp_log.h"
#include "cache_utils.h"
#include "esp_psram.h"
#ifndef NDEBUG
// 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.
*/
if (!did_flush && need_flush) {
#if CONFIG_MEMMAP_SPIRAM_ENABLE
esp_psram_writeback_cache();
#endif
Cache_Flush(0);
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
cores, or the pointer passed between CPUs.
*/
#if CONFIG_MEMMAP_SPIRAM_ENABLE
esp_psram_writeback_cache();
#endif
Cache_Flush(0);
#ifndef CONFIG_FREERTOS_UNICORE
Cache_Flush(1);