rp: Flush cache after erase and write

The RP2040 datasheet suggests that _flash_flush_cache and _flash_enter_cmd_xip
should be called after erasing and writing to flash.
This commit is contained in:
James Turton 2021-05-11 09:17:09 +02:00 committed by UweBonnes
parent f880734050
commit 67c9003522
1 changed files with 27 additions and 7 deletions

View File

@ -164,6 +164,18 @@ static void rp_flash_prepare(target *t)
} }
} }
static void rp_flash_resume(target *t)
{
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
if (ps->is_prepared) {
/* flush */
rp_rom_call(t, ps->regs, ps->_flash_flush_cache,100);
/* enter_cmd_xip */
rp_rom_call(t, ps->regs, ps->_flash_enter_cmd_xip, 100);
ps->is_prepared = false;
}
}
/* FLASHCMD_SECTOR_ERASE 45/ 400 ms /* FLASHCMD_SECTOR_ERASE 45/ 400 ms
* 32k block erase 120/ 1600 ms * 32k block erase 120/ 1600 ms
* 64k block erase 150/ 2000 ms * 64k block erase 150/ 2000 ms
@ -195,6 +207,7 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
addr -= XIP_FLASH_START; addr -= XIP_FLASH_START;
if (len > MAX_FLASH) if (len > MAX_FLASH)
len = MAX_FLASH; len = MAX_FLASH;
bool ret = 0;
while (len) { while (len) {
ps->regs[0] = addr; ps->regs[0] = addr;
ps->regs[2] = -1; ps->regs[2] = -1;
@ -202,14 +215,14 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
ps->regs[1] = MAX_FLASH; ps->regs[1] = MAX_FLASH;
ps->regs[3] = FLASHCMD_CHIP_ERASE; ps->regs[3] = FLASHCMD_CHIP_ERASE;
DEBUG_WARN("BULK_ERASE\n"); DEBUG_WARN("BULK_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 25100); ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 25100);
len = 0; len = 0;
} else if (len >= (64 * 1024)) { } else if (len >= (64 * 1024)) {
uint32_t chunk = len & ~((1 << 16) - 1); uint32_t chunk = len & ~((1 << 16) - 1);
ps->regs[1] = chunk; ps->regs[1] = chunk;
ps->regs[3] = FLASHCMD_BLOCK64K_ERASE; ps->regs[3] = FLASHCMD_BLOCK64K_ERASE;
DEBUG_WARN("64k_ERASE\n"); DEBUG_WARN("64k_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 2100); ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 2100);
len -= chunk ; len -= chunk ;
addr += chunk; addr += chunk;
} else if (len >= (32 * 1024)) { } else if (len >= (32 * 1024)) {
@ -217,7 +230,7 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
ps->regs[1] = chunk; ps->regs[1] = chunk;
ps->regs[3] = FLASHCMD_BLOCK32K_ERASE; ps->regs[3] = FLASHCMD_BLOCK32K_ERASE;
DEBUG_WARN("32k_ERASE\n"); DEBUG_WARN("32k_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 1700); ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 1700);
len -= chunk; len -= chunk;
addr += chunk; addr += chunk;
} else { } else {
@ -225,12 +238,15 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
ps->regs[2] = MAX_FLASH; ps->regs[2] = MAX_FLASH;
ps->regs[3] = FLASHCMD_SECTOR_ERASE; ps->regs[3] = FLASHCMD_SECTOR_ERASE;
DEBUG_WARN("Sector_ERASE\n"); DEBUG_WARN("Sector_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 410); ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 410);
len = 0; len = 0;
} }
if (ret)
break;
} }
rp_flash_resume(t);
DEBUG_INFO("\nErase done!\n"); DEBUG_INFO("\nErase done!\n");
return 0; return ret;
} }
int rp_flash_write(struct target_flash *f, int rp_flash_write(struct target_flash *f,
@ -246,6 +262,7 @@ int rp_flash_write(struct target_flash *f,
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage; struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
/* Write payload to target ram */ /* Write payload to target ram */
dest -= XIP_FLASH_START; dest -= XIP_FLASH_START;
bool ret = 0;
#define MAX_WRITE_CHUNK 0x1000 #define MAX_WRITE_CHUNK 0x1000
while (len) { while (len) {
uint32_t chunksize = (len <= MAX_WRITE_CHUNK) ? len : MAX_WRITE_CHUNK; uint32_t chunksize = (len <= MAX_WRITE_CHUNK) ? len : MAX_WRITE_CHUNK;
@ -254,13 +271,16 @@ int rp_flash_write(struct target_flash *f,
ps->regs[0] = dest; ps->regs[0] = dest;
ps->regs[1] = SRAM_START; ps->regs[1] = SRAM_START;
ps->regs[2] = chunksize; ps->regs[2] = chunksize;
rp_rom_call(t, ps->regs, ps->flash_range_program, ret = rp_rom_call(t, ps->regs, ps->flash_range_program,
(3 * chunksize) >> 8); /* 3 ms per 256 byte page */ (3 * chunksize) >> 8); /* 3 ms per 256 byte page */
if (ret)
break;
len -= chunksize; len -= chunksize;
src += chunksize; src += chunksize;
dest += chunksize; dest += chunksize;
} }
return 0; rp_flash_resume(t);
return ret;
} }
static bool rp_cmd_reset_usb_boot(target *t, int argc, const char *argv[]) static bool rp_cmd_reset_usb_boot(target *t, int argc, const char *argv[])