From 75aa80dba8d9668cbb2b662dc96b9b128ac0379b Mon Sep 17 00:00:00 2001 From: Filipe Cavalcanti Date: Mon, 23 Dec 2024 11:53:30 -0300 Subject: [PATCH] arch/xtensa: enable SPIRAM test during boot of ESP32|S3 --- arch/xtensa/src/esp32/esp32_spiram.c | 56 ++++++++++++++++++++++++ arch/xtensa/src/esp32/esp32_spiram.h | 4 +- arch/xtensa/src/esp32/esp32_start.c | 5 +++ arch/xtensa/src/esp32s3/esp32s3_spiram.c | 13 ++++-- arch/xtensa/src/esp32s3/esp32s3_spiram.h | 4 +- arch/xtensa/src/esp32s3/esp32s3_start.c | 13 +++++- 6 files changed, 85 insertions(+), 10 deletions(-) diff --git a/arch/xtensa/src/esp32/esp32_spiram.c b/arch/xtensa/src/esp32/esp32_spiram.c index 7f4ead9c1f..2e9f6d6a85 100644 --- a/arch/xtensa/src/esp32/esp32_spiram.c +++ b/arch/xtensa/src/esp32/esp32_spiram.c @@ -282,6 +282,62 @@ void IRAM_ATTR esp_spiram_init_cache(void) #endif } +/* Simple RAM test. Writes a word every 32 bytes. Takes about a second + * to complete for 4MiB. Returns OK when RAM seems OK, ERROR when test + * fails. WARNING: Do not run this before the 2nd cpu has been initialized + * (in a two-core system) or after the heap allocator has taken ownership + * of the memory. + */ + +int esp_spiram_test(void) +{ + volatile int *spiram = (volatile int *)PRO_DRAM1_START_ADDR; + + /* Set size value to 4 MB which is related to psize argument on + * cache_sram_mmu_set() calls. In this SoC, psize is 32 Mbit. + */ + + size_t s = 4 * 1024 * 1024; + size_t p; + int errct = 0; + int initial_err = -1; + + for (p = 0; p < (s / sizeof(int)); p += 8) + { + spiram[p] = p ^ 0xaaaaaaaa; + } + + for (p = 0; p < (s / sizeof(int)); p += 8) + { + if (spiram[p] != (p ^ 0xaaaaaaaa)) + { + errct++; + if (errct == 1) + { + initial_err = p * sizeof(int); + } + + if (errct < 4) + { + merr("SPI SRAM error@%p:%08x/%08x \n", &spiram[p], spiram[p], + p ^ 0xaaaaaaaa); + } + } + } + + if (errct != 0) + { + merr("SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", + errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW); + return ERROR; + } + else + { + minfo("SPI SRAM memory test OK!"); + return OK; + } +} + int esp_spiram_get_chip_size(void) { int psram_size; diff --git a/arch/xtensa/src/esp32/esp32_spiram.h b/arch/xtensa/src/esp32/esp32_spiram.h index 3ae3e27aa8..4d2b2b863b 100644 --- a/arch/xtensa/src/esp32/esp32_spiram.h +++ b/arch/xtensa/src/esp32/esp32_spiram.h @@ -118,10 +118,10 @@ void esp_spiram_init_cache(void); * stuff in SPI RAM. * * return: - * true on success, false on failed memory test + * OK on success, ERROR on failed memory test */ -bool esp_spiram_test(void); +int esp_spiram_test(void); /* Description Add the initialized SPI RAM to the heap allocator. */ diff --git a/arch/xtensa/src/esp32/esp32_start.c b/arch/xtensa/src/esp32/esp32_start.c index 584f687572..8b0cf31a08 100644 --- a/arch/xtensa/src/esp32/esp32_start.c +++ b/arch/xtensa/src/esp32/esp32_start.c @@ -257,6 +257,11 @@ static noreturn_function void __esp32_start(void) else { esp_spiram_init_cache(); + if (esp_spiram_test() != OK) + { + ets_printf("SPIRAM test failed\n"); + PANIC(); + } } /* Set external memory bss section to zero */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiram.c b/arch/xtensa/src/esp32s3/esp32s3_spiram.c index 72f8c321bf..c8ee1c57a8 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_spiram.c +++ b/arch/xtensa/src/esp32s3/esp32s3_spiram.c @@ -387,7 +387,7 @@ int IRAM_ATTR cache_dbus_mmu_map(int vaddr, int paddr, int num) * map the virtual address range. */ -void IRAM_ATTR esp_spiram_init_cache(void) +int IRAM_ATTR esp_spiram_init_cache(void) { uint32_t regval; uint32_t psram_size; @@ -417,6 +417,7 @@ void IRAM_ATTR esp_spiram_init_cache(void) mwarn("Invalid target vaddr = 0x%x, change vaddr to: 0x%x\n", target_mapped_vaddr_start, g_mapped_vaddr_start); target_mapped_vaddr_start = g_mapped_vaddr_start; + ret = ERROR; } if (target_mapped_vaddr_end > @@ -426,6 +427,7 @@ void IRAM_ATTR esp_spiram_init_cache(void) SPIRAM_VADDR_MAP_SIZE, g_mapped_vaddr_start + mapped_vaddr_size); target_mapped_vaddr_end = g_mapped_vaddr_start + mapped_vaddr_size; + ret = ERROR; } ASSERT(target_mapped_vaddr_end > target_mapped_vaddr_start); @@ -442,6 +444,7 @@ void IRAM_ATTR esp_spiram_init_cache(void) g_mapped_size = mapped_vaddr_size; mwarn("Virtual address not enough for PSRAM, only %d size is mapped!", g_mapped_size); + ret = ERROR; } else { @@ -475,6 +478,8 @@ void IRAM_ATTR esp_spiram_init_cache(void) g_allocable_vaddr_start = g_mapped_vaddr_start; g_allocable_vaddr_end = g_mapped_vaddr_start + g_mapped_size; + + return ret; } /* Simple RAM test. Writes a word every 32 bytes. Takes about a second @@ -484,7 +489,7 @@ void IRAM_ATTR esp_spiram_init_cache(void) * of the memory. */ -bool esp_spiram_test(void) +int esp_spiram_test(void) { volatile int *spiram = (volatile int *)g_mapped_vaddr_start; @@ -520,12 +525,12 @@ bool esp_spiram_test(void) { merr("SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW); - return false; + return ERROR; } else { minfo("SPI SRAM memory test OK!"); - return true; + return OK; } } diff --git a/arch/xtensa/src/esp32s3/esp32s3_spiram.h b/arch/xtensa/src/esp32s3/esp32s3_spiram.h index 6bd24ec7cc..043398788d 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_spiram.h +++ b/arch/xtensa/src/esp32s3/esp32s3_spiram.h @@ -70,7 +70,7 @@ int esp_spiram_init(void); * Attention this function must be called with flash cache disabled. */ -void esp_spiram_init_cache(void); +int esp_spiram_init_cache(void); /* Memory test for SPI RAM. Should be called after SPI RAM is * initialized and (in case of a dual-core system) the app CPU is online. @@ -80,7 +80,7 @@ void esp_spiram_init_cache(void); * Return true on success, false on failed memory test */ -bool esp_spiram_test(void); +int esp_spiram_test(void); /* Add the initialized SPI RAM to the heap allocator. */ diff --git a/arch/xtensa/src/esp32s3/esp32s3_start.c b/arch/xtensa/src/esp32s3/esp32s3_start.c index 19e77a9f89..ac5bd5cbc5 100644 --- a/arch/xtensa/src/esp32s3/esp32s3_start.c +++ b/arch/xtensa/src/esp32s3/esp32s3_start.c @@ -401,8 +401,17 @@ noinstrument_function void noreturn_function IRAM_ATTR __esp32s3_start(void) } else { - esp_spiram_init_cache(); - esp_spiram_test(); + if (esp_spiram_init_cache() != OK) + { + ets_printf("SPIRAM init cache failed\n"); + PANIC(); + } + + if (esp_spiram_test() != OK) + { + ets_printf("SPIRAM test failed\n"); + PANIC(); + } } #endif