diff --git a/src/target/esp32c3.c b/src/target/esp32c3.c index 539f4afb87a..d6bf4162197 100644 --- a/src/target/esp32c3.c +++ b/src/target/esp32c3.c @@ -109,8 +109,22 @@ #define ESP32_C3_TIMG1_WDT_FEED (ESP32_C3_TIMG1_BASE + 0x060U) #define ESP32_C3_TIMG1_WDT_WRITE_PROT (ESP32_C3_TIMG1_BASE + 0x064U) +#define ESP32_C3_EXTMEM_BASE 0x600c4000U +#define ESP32_C3_EXTMEM_ICACHE_SYNC_CTRL (ESP32_C3_EXTMEM_BASE + 0x028U) +#define ESP32_C3_EXTMEM_ICACHE_SYNC_ADDR (ESP32_C3_EXTMEM_BASE + 0x02cU) +#define ESP32_C3_EXTMEM_ICACHE_SYNC_SIZE (ESP32_C3_EXTMEM_BASE + 0x030U) +#define ESP32_C3_EXTMEM_ICACHE_PRELOAD_CTRL (ESP32_C3_EXTMEM_BASE + 0x034U) +#define ESP32_C3_EXTMEM_ICACHE_PRELOAD_ADDR (ESP32_C3_EXTMEM_BASE + 0x038U) +#define ESP32_C3_EXTMEM_ICACHE_PRELOAD_SIZE (ESP32_C3_EXTMEM_BASE + 0x03cU) + +#define ESP32_C3_EXTMEM_ICACHE_INVALIDATE 0x00000001U +#define ESP32_C3_EXTMEM_ICACHE_SYNC_DONE 0x00000002U +#define ESP32_C3_EXTMEM_ICACHE_PRELOAD 0x00000001U +#define ESP32_C3_EXTMEM_ICACHE_PRELOAD_DONE 0x00000002U + typedef struct esp32c3_priv { uint32_t wdt_config[4]; + target_addr_t last_invalidated_sector; } esp32c3_priv_s; static void esp32c3_disable_wdts(target_s *target); @@ -125,6 +139,7 @@ static void esp32c3_spi_write( static void esp32c3_spi_run_command(target_s *target, uint16_t command, target_addr_t address); static bool esp32c3_enter_flash_mode(target_s *target); +static bool esp32c3_exit_flash_mode(target_s *target); static bool esp32c3_spi_flash_erase(target_flash_s *flash, target_addr_t addr, size_t length); static bool esp32c3_spi_flash_write(target_flash_s *flash, target_addr_t dest, const void *src, size_t length); @@ -169,6 +184,7 @@ bool esp32c3_probe(target_s *const target) target->mass_erase = bmp_spi_mass_erase; /* Special care must be taken during Flash programming */ target->enter_flash_mode = esp32c3_enter_flash_mode; + target->exit_flash_mode = esp32c3_exit_flash_mode; /* Establish the target RAM mappings */ target_add_ram(target, ESP32_C3_IBUS_SRAM0_BASE, ESP32_C3_IBUS_SRAM0_SIZE); @@ -393,6 +409,20 @@ static bool esp32c3_enter_flash_mode(target_s *const target) return true; } +static bool esp32c3_exit_flash_mode(target_s *const target) +{ + esp32c3_priv_s *const priv = (esp32c3_priv_s *)target->target_storage; + /* Invalidate the i-cache for the required length */ + target_mem_write32(target, ESP32_C3_EXTMEM_ICACHE_SYNC_ADDR, ESP32_C3_IBUS_FLASH_BASE); + target_mem_write32(target, ESP32_C3_EXTMEM_ICACHE_SYNC_SIZE, priv->last_invalidated_sector); + target_mem_write32(target, ESP32_C3_EXTMEM_ICACHE_SYNC_CTRL, ESP32_C3_EXTMEM_ICACHE_INVALIDATE); + /* Wait for invalidation to complete */ + while (!(target_mem_read32(target, ESP32_C3_EXTMEM_ICACHE_SYNC_CTRL) & ESP32_C3_EXTMEM_ICACHE_SYNC_DONE)) + continue; + target_reset(target); + return true; +} + static bool esp32c3_spi_flash_erase(target_flash_s *const flash, const target_addr_t addr, const size_t length) { (void)length; @@ -406,6 +436,9 @@ static bool esp32c3_spi_flash_erase(target_flash_s *const flash, const target_ad target, SPI_FLASH_CMD_SECTOR_ERASE | SPI_FLASH_OPCODE(spi_flash->sector_erase_opcode), addr - flash->start); while (esp32c3_spi_read_status(target) & SPI_FLASH_STATUS_BUSY) continue; + /* Update the address of the last invalidated sector so we can correctly invalidate the i-cache and reload it */ + esp32c3_priv_s *const priv = (esp32c3_priv_s *)target->target_storage; + priv->last_invalidated_sector = (addr - flash->start) + length; return true; }