diff --git a/cpu/esp32/include/cpu_conf.h b/cpu/esp32/include/cpu_conf.h index 1ee5a1c1c1..01493d8207 100644 --- a/cpu/esp32/include/cpu_conf.h +++ b/cpu/esp32/include/cpu_conf.h @@ -79,7 +79,7 @@ */ #if !DOXYGEN && !defined(__ASSEMBLER__) /* start address of flash pages in CPU address space as determined by the linker */ -extern uint8_t _fp_mem_start; +extern uint8_t _fp_mmu_start; #endif #define FLASHPAGE_SIZE (4096U) /**< Size of pages (flash sectors) in bytes */ @@ -94,7 +94,7 @@ extern uint8_t _fp_mem_start; /** * @brief CPU base address for flash page access as determined by the linker */ -#define CPU_FLASH_BASE ((uint32_t)&_fp_mem_start) +#define CPU_FLASH_BASE ((uint32_t)&_fp_mmu_start) /** @} */ diff --git a/cpu/esp32/periph/flashpage.c b/cpu/esp32/periph/flashpage.c index 99bb2fea9c..bff983d097 100644 --- a/cpu/esp32/periph/flashpage.c +++ b/cpu/esp32/periph/flashpage.c @@ -27,12 +27,16 @@ #include "irq.h" #include "log.h" -#include "esp_flash_partitions.h" -#include "esp_spi_flash.h" +#include "esp_private/cache_utils.h" +#include "esp_flash.h" +#include "esp_flash_internal.h" +#include "hal/cache_hal.h" +#include "hal/mmu_hal.h" #include "rom/cache.h" #include "rom/spi_flash.h" -#include "soc/mmu.h" #include "soc/soc.h" +#include "soc/ext_mem_defs.h" +#include "spi_flash_mmap.h" #define ENABLE_DEBUG 0 #include "debug.h" @@ -42,16 +46,35 @@ #define ESP_PART_ENTRY_SIZE 0x20 #define ESP_PART_ENTRY_MAGIC ESP_PARTITION_MAGIC +extern uint8_t _fp_mmu_start; +extern uint8_t _fp_mmu_end; extern uint8_t _fp_mem_start; /* start address in CPU address space */ extern uint8_t _fp_mem_end; extern uint8_t _end_fw; static uint32_t _fp_flash_start; /* start address in flash */ +void IRAM_ATTR esp_sync_cache(uint32_t target_addr, size_t len) +{ + DEBUG("%s sync cache from @0x%08"PRIx32" for %u\n", + __func__, target_addr, len); + + for (uint32_t addr = target_addr; addr < (target_addr + len); + addr += SPI_FLASH_MMU_PAGE_SIZE) { +#if defined(CPU_FAM_ESP32) + extern void cache_sync(void); + cache_sync(); +#else + cache_hal_invalidate_addr((uint32_t)addr, SPI_FLASH_MMU_PAGE_SIZE); +#endif + } +} + void IRAM_ATTR esp_flashpage_init(void) { /* CONFIG_ESP_FLASHPAGE_CAPACITY has to be a multiple of SPI_FLASH_MMU_PAGE_SIZE */ assert((CONFIG_ESP_FLASHPAGE_CAPACITY % SPI_FLASH_MMU_PAGE_SIZE) == 0); + assert((FLASHPAGE_ADDR_START % SPI_FLASH_MMU_PAGE_SIZE) == 0); DEBUG("%s pages in CPU address space @0x%08"PRIx32"...0x%08"PRIx32"\n", __func__, CPU_FLASH_BASE, CPU_FLASH_BASE + CONFIG_ESP_FLASHPAGE_CAPACITY - 1); @@ -65,47 +88,43 @@ void IRAM_ATTR esp_flashpage_init(void) uint32_t p_numof = CONFIG_ESP_FLASHPAGE_CAPACITY / SPI_FLASH_MMU_PAGE_SIZE; uint32_t p_addr = FLASHPAGE_ADDR_START; - -#if CPU_FAM_ESP32S2 - /* ESP32-S2 requires special handling to enable the MMU pages in Cache - * explicitly */ - - uint32_t autoload = Cache_Suspend_ICache(); - Cache_Invalidate_ICache_All(); - int res = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, (uint32_t)&_fp_mem_start, - p_addr, 64, p_numof, 0); - Cache_Resume_ICache(autoload); - - DEBUG("%s DCache MMU set paddr=%08"PRIx32" vaddr=%08"PRIx32" size=%d n=%"PRIu32"\n", - __func__, p_addr, (uint32_t)&_fp_mem_start, CONFIG_ESP_FLASHPAGE_CAPACITY, - p_numof); - - if (res != ESP_OK) { - LOG_TAG_ERROR("flashpage", - "Could not map MMU pages in DCache, error: %d\n", res); - } -#else - uint32_t p_mmu = ((uint32_t)&_fp_mem_start - SOC_DROM_LOW) / SPI_FLASH_MMU_PAGE_SIZE; + uint32_t p_mmu = ((uint32_t)&_fp_mmu_start - SOC_DROM_LOW) / SPI_FLASH_MMU_PAGE_SIZE; while (p_numof--) { uint32_t p_flash = p_addr / SPI_FLASH_MMU_PAGE_SIZE; + uint32_t mmu_addr = SOC_DROM_LOW + (p_mmu * SPI_FLASH_MMU_PAGE_SIZE); + DEBUG("%s map MMU page %"PRIu32" @0x%08"PRIx32" to " "flash page %"PRIu32" @0x%08"PRIx32"\n", __func__, - p_mmu, (p_mmu * SPI_FLASH_MMU_PAGE_SIZE) + SOC_DROM_LOW, + p_mmu, mmu_addr, p_flash, p_flash * SPI_FLASH_MMU_PAGE_SIZE); - SOC_MMU_DPORT_PRO_FLASH_MMU_TABLE[p_mmu] = SOC_MMU_PAGE_IN_FLASH(p_flash); + + spi_flash_mmap_handle_t t_handle; + const void *t_mem; + esp_err_t res; + + res = spi_flash_mmap(p_addr, SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMAP_DATA, + &t_mem, &t_handle); + + assert((uint32_t)t_mem == mmu_addr); + DEBUG("%s map MMU page %"PRIu32" @0x%08"PRIx32" to " + "flash page %"PRIu32" @0x%08"PRIx32" %s\n", __func__, + p_mmu, (uint32_t)t_mem, + p_flash, p_flash * SPI_FLASH_MMU_PAGE_SIZE, + res == ESP_OK ? "OK" : "NOK"); + p_addr += SPI_FLASH_MMU_PAGE_SIZE; p_mmu++; } -#endif + irq_restore(state); - if (IS_ACTIVE(ENABLE_DEBUG)) { + if (ENABLE_DEBUG) { spi_flash_mmap_dump(); } } -void flashpage_erase(unsigned page) +void IRAM_ATTR flashpage_erase(unsigned page) { assert(page < FLASHPAGE_NUMOF); @@ -113,14 +132,20 @@ void flashpage_erase(unsigned page) DEBUG("%s erase page in flash @0x%08"PRIx32"\n", __func__, flash_addr); - int res = spi_flash_erase_range(flash_addr, FLASHPAGE_SIZE); + uint32_t state = irq_disable(); + + int res = esp_flash_erase_region(esp_flash_default_chip, flash_addr, FLASHPAGE_SIZE); + esp_sync_cache((uint32_t)&_fp_mmu_start + (page * FLASHPAGE_SIZE), FLASHPAGE_SIZE); + + irq_restore(state); + if (res != ESP_OK) { LOG_TAG_ERROR("flashpage", "Could not erase page %u, error %d\n", page, res); } } -void flashpage_write(void *target_addr, const void *data, size_t len) +void IRAM_ATTR flashpage_write(void *target_addr, const void *data, size_t len) { DEBUG("%s write %u byte from @%p to @%p\n", __func__, len, data, target_addr); @@ -135,12 +160,18 @@ void flashpage_write(void *target_addr, const void *data, size_t len) assert(((unsigned)target_addr + len) <= (CPU_FLASH_BASE + (FLASHPAGE_SIZE * FLASHPAGE_NUMOF))); - uint32_t flash_addr = ((uint32_t)target_addr - (uint32_t)&_fp_mem_start) + _fp_flash_start; + uint32_t flash_addr = ((uint32_t)target_addr - (uint32_t)&_fp_mmu_start) + _fp_flash_start; DEBUG("%s write to CPU address @%p (flash @0x%08"PRIx32")\n", __func__, target_addr, flash_addr); - int res = spi_flash_write(flash_addr, data, len); + uint32_t state = irq_disable(); + + int res = esp_flash_write(esp_flash_default_chip, data, flash_addr, len); + esp_sync_cache((uint32_t)target_addr, len); + + irq_restore(state); + if (res != ESP_OK) { LOG_TAG_ERROR("flashpage", "Could not write to CPU address @%p " "(flash @0x%08"PRIx32"), error %d\n", @@ -148,14 +179,13 @@ void flashpage_write(void *target_addr, const void *data, size_t len) } } -unsigned flashpage_first_free(void) +unsigned IRAM_ATTR flashpage_first_free(void) { /* _end_fw is page aligned */ return flashpage_page(&_end_fw); } -unsigned flashpage_last_free(void) +unsigned IRAM_ATTR flashpage_last_free(void) { -// return flashpage_page((const void *)SOC_DROM_HIGH) - 1; return flashpage_page((void *)(CPU_FLASH_BASE + CONFIG_ESP_FLASHPAGE_CAPACITY)) - 1; }