diff --git a/components/esp32s2beta/test/test_spiram_cache_flush.c b/components/esp32s2beta/test/test_spiram_cache_flush.c index e525d21770..fe89a7f52f 100644 --- a/components/esp32s2beta/test/test_spiram_cache_flush.c +++ b/components/esp32s2beta/test/test_spiram_cache_flush.c @@ -4,23 +4,22 @@ This code tests the interaction between PSRAM and SPI flash routines. #include #include -#include "esp32/rom/ets_sys.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" #include "freertos/xtensa_api.h" #include "unity.h" +#include "soc/dport_reg.h" +#include "soc/io_mux_reg.h" #include #include #include #include -#include "esp32/rom/ets_sys.h" #include "esp_heap_caps.h" #include "esp_spi_flash.h" #include "esp_partition.h" #include "test_utils.h" -#include "soc/soc.h" #if CONFIG_SPIRAM diff --git a/components/spi_flash/flash_mmap.c b/components/spi_flash/flash_mmap.c index 011dab9ef8..f2ede57daa 100644 --- a/components/spi_flash/flash_mmap.c +++ b/components/spi_flash/flash_mmap.c @@ -53,12 +53,18 @@ #define IROM0_PAGES_END 256 #define DROM0_PAGES_START 0 #define DROM0_PAGES_END 64 + +#define PAGE_IN_FLASH(page) (page) + #elif CONFIG_IDF_TARGET_ESP32S2BETA #define REGIONS_COUNT 8 #define IROM0_PAGES_START (PRO_CACHE_IBUS0_MMU_START / sizeof(uint32_t)) #define IROM0_PAGES_END (PRO_CACHE_IBUS2_MMU_END / sizeof(uint32_t)) #define DROM0_PAGES_START (Cache_Drom0_Using_ICache()? PRO_CACHE_IBUS3_MMU_START / sizeof(uint32_t) : PRO_CACHE_DBUS3_MMU_START /sizeof(uint32_t)) #define DROM0_PAGES_END (Cache_Drom0_Using_ICache()? PRO_CACHE_IBUS3_MMU_END / sizeof(uint32_t) : PRO_CACHE_DBUS3_MMU_END / sizeof(uint32_t)) + +#define PAGE_IN_FLASH(page) ((page) | DPORT_MMU_ACCESS_FLASH) + #endif #define MMU_ADDR_MASK DPORT_MMU_ADDRESS_MASK #define IROM0_PAGES_NUM (IROM0_PAGES_END - IROM0_PAGES_START) @@ -86,7 +92,7 @@ static uint32_t s_mmap_last_handle = 0; static void IRAM_ATTR spi_flash_mmap_init(void) { - if (s_mmap_page_refcnt[0] != 0) { + if (s_mmap_page_refcnt[DROM0_PAGES_START] != 0) { return; /* mmap data already initialised */ } DPORT_INTERRUPT_DISABLE(); @@ -148,9 +154,6 @@ esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_ } for (int i = 0; i < page_count; i++) { pages[i] = (phys_page+i); -#if CONFIG_IDF_TARGET_ESP32S2BETA - pages[i] |= DPORT_MMU_ACCESS_FLASH; -#endif } ret = spi_flash_mmap_pages(pages, page_count, memory, out_ptr, out_handle); free(pages); @@ -169,7 +172,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp return ESP_ERR_INVALID_ARG; } for (int i = 0; i < page_count; i++) { - if (pages[i] < 0 || (pages[i] & MMU_ADDR_MASK)*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) { + if (pages[i] < 0 || pages[i]*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) { return ESP_ERR_INVALID_ARG; } } @@ -203,7 +206,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp for (pos = start; pos < start + page_count; ++pos, ++pageno) { int table_val = (int) DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[pos]); uint8_t refcnt = s_mmap_page_refcnt[pos]; - if (refcnt != 0 && table_val != pages[pageno]) { + if (refcnt != 0 && table_val != PAGE_IN_FLASH(pages[pageno])) { break; } } @@ -229,21 +232,25 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]); #endif assert(s_mmap_page_refcnt[i] == 0 || - (entry_pro == pages[pageno] + (entry_pro == PAGE_IN_FLASH(pages[pageno]) #if !CONFIG_FREERTOS_UNICORE - && entry_app == pages[pageno] + && entry_app == PAGE_IN_FLASH(pages[pageno]) #endif )); if (s_mmap_page_refcnt[i] == 0) { - if (entry_pro != pages[pageno] + if (entry_pro != PAGE_IN_FLASH(pages[pageno]) #if !CONFIG_FREERTOS_UNICORE - || entry_app != pages[pageno] + || entry_app != PAGE_IN_FLASH(pages[pageno]) #endif ) { - DPORT_PRO_FLASH_MMU_TABLE[i] = pages[pageno]; + DPORT_PRO_FLASH_MMU_TABLE[i] = PAGE_IN_FLASH(pages[pageno]); #if !CONFIG_FREERTOS_UNICORE DPORT_APP_FLASH_MMU_TABLE[i] = pages[pageno]; #endif + +#if CONFIG_IDF_TARGET_ESP32S2BETA + Cache_Invalidate_Addr(region_addr + (i - region_begin) * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMU_PAGE_SIZE); +#endif need_flush = true; } } @@ -266,22 +273,14 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp entire cache. */ if (need_flush) { -#if CONFIG_SPIRAM - esp_spiram_writeback_cache(); -#endif #if CONFIG_IDF_TARGET_ESP32 +# if CONFIG_SPIRAM + esp_spiram_writeback_cache(); +# endif Cache_Flush(0); -#elif CONFIG_IDF_TARGET_ESP32S2BETA - Cache_Invalidate_ICache_All(); - if (!Cache_Drom0_Using_ICache()) { -#if CONFIG_SPIRAM_SUPPORT - Cache_WriteBack_All(); -#endif - Cache_Invalidate_DCache_All(); - } -#endif -#if !CONFIG_FREERTOS_UNICORE +# if !CONFIG_FREERTOS_UNICORE Cache_Flush(1); +# endif #endif } @@ -422,7 +421,7 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me spi_flash_disable_interrupts_caches_and_other_cpu(); DPORT_INTERRUPT_DISABLE(); for (int i = start; i < end; i++) { - if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == phys_page) { + if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) { i -= page_delta; intptr_t cache_page = base + (SPI_FLASH_MMU_PAGE_SIZE * i); DPORT_INTERRUPT_RESTORE(); @@ -435,22 +434,31 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me return NULL; } -static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page) +static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page, const void **out_ptr) { int start[2], end[2]; + *out_ptr = NULL; + /* SPI_FLASH_MMAP_DATA */ - start[0] = 0; - end[0] = 64; + start[0] = DROM0_PAGES_START; + end[0] = DROM0_PAGES_END; /* SPI_FLASH_MMAP_INST */ start[1] = PRO_IRAM0_FIRST_USABLE_PAGE; - end[1] = 256; + end[1] = IROM0_PAGES_END; DPORT_INTERRUPT_DISABLE(); for (int j = 0; j < 2; j++) { for (int i = start[j]; i < end[j]; i++) { - if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == phys_page) { + if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) { +#if CONFIG_IDF_TARGET_ESP32S2BETA + if (j == 0) { /* SPI_FLASH_MMAP_DATA */ + *out_ptr = (const void *)(VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0])); + } else { /* SPI_FLASH_MMAP_INST */ + *out_ptr = (const void *)(VADDR1_FIRST_USABLE_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[1])); + } +#endif DPORT_INTERRUPT_RESTORE(); return true; } @@ -463,6 +471,7 @@ static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page) /* Validates if given flash address has corresponding cache mapping, if yes, flushes cache memories */ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length) { + bool ret = false; /* align start_addr & length to full MMU pages */ uint32_t page_start_addr = start_addr & ~(SPI_FLASH_MMU_PAGE_SIZE-1); length += (start_addr - page_start_addr); @@ -473,7 +482,8 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length) return false; /* invalid address */ } - if (is_page_mapped_in_cache(page)) { + const void *vaddr = NULL; + if (is_page_mapped_in_cache(page, &vaddr)) { #if CONFIG_IDF_TARGET_ESP32 #if CONFIG_SPIRAM esp_spiram_writeback_cache(); @@ -481,10 +491,16 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length) Cache_Flush(0); #ifndef CONFIG_FREERTOS_UNICORE Cache_Flush(1); -#endif #endif return true; +#elif CONFIG_IDF_TARGET_ESP32S2BETA + if (vaddr != NULL) { + Cache_Invalidate_Addr((uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE); + ret = true; + } +#endif + } } - return false; + return ret; } diff --git a/components/spi_flash/test/test_cache_disabled.c b/components/spi_flash/test/test_cache_disabled.c index 747ccdf3ab..aae44bd431 100644 --- a/components/spi_flash/test/test_cache_disabled.c +++ b/components/spi_flash/test/test_cache_disabled.c @@ -73,8 +73,12 @@ TEST_CASE("invalid access to cache raises panic (PRO CPU)", "[spi_flash][ignore] vTaskDelay(1000/portTICK_PERIOD_MS); } +#ifndef CONFIG_FREERTOS_UNICORE + TEST_CASE("invalid access to cache raises panic (APP CPU)", "[spi_flash][ignore]") { xTaskCreatePinnedToCore(&cache_access_test_func, "ia", 2048, NULL, 5, NULL, 1); vTaskDelay(1000/portTICK_PERIOD_MS); } + +#endif diff --git a/components/spi_flash/test/test_mmap.c b/components/spi_flash/test/test_mmap.c index 4b8841e960..d0efe3d749 100644 --- a/components/spi_flash/test/test_mmap.c +++ b/components/spi_flash/test/test_mmap.c @@ -159,15 +159,23 @@ TEST_CASE_ESP32("Can mmap into instruction address space", "[mmap]") printf("Mapping %x (+%x)\n", start - 0x10000, 0x20000); spi_flash_mmap_handle_t handle2; const void *ptr2; - ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_DATA, &ptr2, &handle2) ); + ESP_ERROR_CHECK( spi_flash_mmap(start - 0x10000, 0x20000, SPI_FLASH_MMAP_INST, &ptr2, &handle2) ); printf("mmap_res: handle=%d ptr=%p\n", handle2, ptr2); + + TEST_ASSERT_EQUAL_HEX32(start - 0x10000, spi_flash_cache2phys(ptr2)); + TEST_ASSERT_EQUAL_PTR(ptr2, spi_flash_phys2cache(start - 0x10000, SPI_FLASH_MMAP_INST)); + spi_flash_mmap_dump(); printf("Mapping %x (+%x)\n", start, 0x10000); spi_flash_mmap_handle_t handle3; const void *ptr3; - ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_DATA, &ptr3, &handle3) ); + ESP_ERROR_CHECK( spi_flash_mmap(start, 0x10000, SPI_FLASH_MMAP_INST, &ptr3, &handle3) ); printf("mmap_res: handle=%d ptr=%p\n", handle3, ptr3); + + TEST_ASSERT_EQUAL_HEX32(start, spi_flash_cache2phys(ptr3)); + TEST_ASSERT_EQUAL_PTR(ptr3, spi_flash_phys2cache(start, SPI_FLASH_MMAP_INST)); + spi_flash_mmap_dump(); printf("Unmapping handle1\n"); diff --git a/components/spi_flash/test/test_read_write.c b/components/spi_flash/test/test_read_write.c index 00732f1abd..57af4af74c 100644 --- a/components/spi_flash/test/test_read_write.c +++ b/components/spi_flash/test/test_read_write.c @@ -214,10 +214,29 @@ TEST_CASE_ESP32("Test spi_flash_write", "[spi_flash][esp_flash]") * NB: At the moment these only support aligned addresses, because memcpy * is not aware of the 32-but load requirements for these regions. */ +#ifdef CONFIG_IDF_TARGET_ESP32S2BETA +#define TEST_SOC_IROM_ADDR (SOC_IROM_LOW) +#define TEST_SOC_CACHE_RAM_BANK0_ADDR (SOC_IRAM_LOW) +#define TEST_SOC_CACHE_RAM_BANK1_ADDR (SOC_IRAM_LOW + 0x2000) +#define TEST_SOC_CACHE_RAM_BANK2_ADDR (SOC_IRAM_LOW + 0x4000) +#define TEST_SOC_CACHE_RAM_BANK3_ADDR (SOC_IRAM_LOW + 0x6000) +#define TEST_SOC_IRAM_ADDR (SOC_IRAM_LOW + 0x8000) +#define TEST_SOC_RTC_IRAM_ADDR (SOC_RTC_IRAM_LOW) +#define TEST_SOC_RTC_DRAM_ADDR (SOC_RTC_DRAM_LOW) + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_IROM_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_IRAM_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK0_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK1_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK2_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_CACHE_RAM_BANK3_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_RTC_IRAM_ADDR, 16)); + ESP_ERROR_CHECK(spi_flash_write(start, (char *) TEST_SOC_RTC_DRAM_ADDR, 16)); +#else ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40000000, 16)); ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40070000, 16)); ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40078000, 16)); ESP_ERROR_CHECK(spi_flash_write(start, (char *) 0x40080000, 16)); +#endif } #ifdef CONFIG_SPIRAM diff --git a/components/spi_flash/test/test_spi_flash.c b/components/spi_flash/test/test_spi_flash.c index a9ba4e3107..db1cc14210 100644 --- a/components/spi_flash/test/test_spi_flash.c +++ b/components/spi_flash/test/test_spi_flash.c @@ -16,11 +16,23 @@ struct flash_test_ctx { SemaphoreHandle_t done; }; +/* Base offset in flash for tests. */ +static size_t start; + +static void setup_tests() +{ + if (start == 0) { + const esp_partition_t *part = get_test_data_partition(); + start = part->address; + printf("Test data partition @ 0x%x\n", start); + } +} + static void flash_test_task(void *arg) { struct flash_test_ctx *ctx = (struct flash_test_ctx *) arg; vTaskDelay(100 / portTICK_PERIOD_MS); - const uint32_t sector = ctx->offset; + const uint32_t sector = start / SPI_FLASH_SEC_SIZE + ctx->offset; printf("t%d\n", sector); printf("es%d\n", sector); if (spi_flash_erase_sector(sector) != ESP_OK) { @@ -65,13 +77,15 @@ static void flash_test_task(void *arg) TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_flash][ignore]") { + setup_tests(); + SemaphoreHandle_t done = xSemaphoreCreateCounting(4, 0); struct flash_test_ctx ctx[] = { - { .offset = 0x100 + 6, .done = done }, - { .offset = 0x100 + 7, .done = done }, - { .offset = 0x100 + 8, .done = done }, + { .offset = 0x10 + 6, .done = done }, + { .offset = 0x10 + 7, .done = done }, + { .offset = 0x10 + 8, .done = done }, #ifndef CONFIG_FREERTOS_UNICORE - { .offset = 0x100 + 9, .done = done } + { .offset = 0x10 + 9, .done = done } #endif };