rp: Define enter_flash_mode and exit_flash_mode

Defining these methods highly accelerates the flash loading time as we
no longer return the flash to XIP mode after each buffered write,
instead we wait until the entire transaction has finished before
returning to XIP mode.
This commit is contained in:
James Turton 2022-09-04 10:33:56 +02:00 committed by Rachel Mant
parent 481aaee3a3
commit 4cc3eee154
1 changed files with 25 additions and 19 deletions

View File

@ -157,8 +157,8 @@ static bool rp_flash_write(target_flash_s *f, target_addr_t dest, const void *sr
static bool rp_read_rom_func_table(target *t); static bool rp_read_rom_func_table(target *t);
static bool rp_attach(target *t); static bool rp_attach(target *t);
static void rp_flash_prepare(target *t); static bool rp_flash_prepare(target *t);
static void rp_flash_resume(target *t); static bool rp_flash_resume(target *t);
static void rp_spi_read(target *t, uint16_t command, target_addr_t address, void *buffer, size_t length); static void rp_spi_read(target *t, uint16_t command, target_addr_t address, void *buffer, size_t length);
static uint32_t rp_get_flash_length(target *t, rp_flash_s *flash); static uint32_t rp_get_flash_length(target *t, rp_flash_s *flash);
static bool rp_mass_erase(target *t); static bool rp_mass_erase(target *t);
@ -221,6 +221,8 @@ bool rp_probe(target *t)
t->driver = RP_ID; t->driver = RP_ID;
t->target_options |= CORTEXM_TOPT_INHIBIT_NRST; t->target_options |= CORTEXM_TOPT_INHIBIT_NRST;
t->attach = rp_attach; t->attach = rp_attach;
t->enter_flash_mode = rp_flash_prepare;
t->exit_flash_mode = rp_flash_resume;
target_add_commands(t, rp_cmd_list, RP_ID); target_add_commands(t, rp_cmd_list, RP_ID);
return true; return true;
} }
@ -345,30 +347,34 @@ static bool rp_rom_call(target *t, uint32_t *regs, uint32_t cmd, uint32_t timeou
return ret; return ret;
} }
static void rp_flash_prepare(target *t) static bool rp_flash_prepare(target *t)
{ {
rp_priv_s *ps = (rp_priv_s *)t->target_storage; rp_priv_s *ps = (rp_priv_s *)t->target_storage;
bool ret = true; /* catch false returns with &= */
if (!ps->is_prepared) { if (!ps->is_prepared) {
DEBUG_INFO("rp_flash_prepare\n"); DEBUG_INFO("rp_flash_prepare\n");
/* connect*/ /* connect*/
rp_rom_call(t, ps->regs, ps->rom_connect_internal_flash, 100); ret &= rp_rom_call(t, ps->regs, ps->rom_connect_internal_flash, 100);
/* exit_xip */ /* exit_xip */
rp_rom_call(t, ps->regs, ps->rom_flash_exit_xip, 100); ret &= rp_rom_call(t, ps->regs, ps->rom_flash_exit_xip, 100);
ps->is_prepared = true; ps->is_prepared = true;
} }
return ret;
} }
static void rp_flash_resume(target *t) static bool rp_flash_resume(target *t)
{ {
rp_priv_s *ps = (rp_priv_s *)t->target_storage; rp_priv_s *ps = (rp_priv_s *)t->target_storage;
bool ret = true; /* catch false returns with &= */
if (ps->is_prepared) { if (ps->is_prepared) {
DEBUG_INFO("rp_flash_resume\n"); DEBUG_INFO("rp_flash_resume\n");
/* flush */ /* flush */
rp_rom_call(t, ps->regs, ps->rom_flash_flush_cache, 100); ret &= rp_rom_call(t, ps->regs, ps->rom_flash_flush_cache, 100);
/* enter_cmd_xip */ /* enter_cmd_xip */
rp_rom_call(t, ps->regs, ps->rom_flash_enter_xip, 100); ret &= rp_rom_call(t, ps->regs, ps->rom_flash_enter_xip, 100);
ps->is_prepared = false; ps->is_prepared = false;
} }
return ret;
} }
/* /*
@ -384,7 +390,6 @@ static bool rp_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
target *t = f->t; target *t = f->t;
/* Update our assumptions with the SFDP params */ /* Update our assumptions with the SFDP params */
rp_flash_prepare(t);
spi_parameters_s spi_parameters; spi_parameters_s spi_parameters;
rp_flash_s *flash = (rp_flash_s *)f; rp_flash_s *flash = (rp_flash_s *)f;
if (!(flash->table_has_been_read) && sfdp_read_parameters(t, &spi_parameters, rp_spi_read_sfdp)) { if (!(flash->table_has_been_read) && sfdp_read_parameters(t, &spi_parameters, rp_spi_read_sfdp)) {
@ -396,12 +401,10 @@ static bool rp_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
if (addr & (f->blocksize - 1)) { if (addr & (f->blocksize - 1)) {
DEBUG_WARN("Unaligned erase\n"); DEBUG_WARN("Unaligned erase\n");
rp_flash_resume(t);
return false; return false;
} }
if ((addr < f->start) || (addr >= f->start + f->length)) { if ((addr < f->start) || (addr >= f->start + f->length)) {
DEBUG_WARN("Address is invalid\n"); DEBUG_WARN("Address is invalid\n");
rp_flash_resume(t);
return false; return false;
} }
addr -= f->start; addr -= f->start;
@ -451,7 +454,6 @@ static bool rp_flash_erase(target_flash_s *f, target_addr_t addr, size_t len)
if (full_erase) if (full_erase)
target_print_progress(&timeout); target_print_progress(&timeout);
} }
rp_flash_resume(t);
DEBUG_INFO("Erase done!\n"); DEBUG_INFO("Erase done!\n");
return ret; return ret;
} }
@ -467,7 +469,6 @@ static bool rp_flash_write(target_flash_s *f, target_addr_t dest, const void *sr
dest -= f->start; dest -= f->start;
rp_priv_s *ps = (rp_priv_s *)t->target_storage; rp_priv_s *ps = (rp_priv_s *)t->target_storage;
/* Write payload to target ram */ /* Write payload to target ram */
rp_flash_prepare(t);
bool ret = true; bool ret = true;
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;
@ -489,7 +490,6 @@ static bool rp_flash_write(target_flash_s *f, target_addr_t dest, const void *sr
src += chunksize; src += chunksize;
dest += chunksize; dest += chunksize;
} }
rp_flash_resume(t);
DEBUG_INFO("Write done!\n"); DEBUG_INFO("Write done!\n");
return ret; return ret;
} }
@ -498,9 +498,12 @@ static bool rp_mass_erase(target *t)
{ {
rp_priv_s *ps = (rp_priv_s *)t->target_storage; rp_priv_s *ps = (rp_priv_s *)t->target_storage;
ps->is_monitor = true; ps->is_monitor = true;
const bool result = rp_flash_erase(t->flash, t->flash->start, t->flash->length); bool ret = true; /* catch false returns with &= */
ret &= rp_flash_prepare(t);
ret &= rp_flash_erase(t->flash, t->flash->start, t->flash->length);
ret &= rp_flash_resume(t);
ps->is_monitor = false; ps->is_monitor = false;
return result; return ret;
} }
static void rp_spi_chip_select(target *const t, const bool active) static void rp_spi_chip_select(target *const t, const bool active)
@ -638,13 +641,16 @@ static bool rp_cmd_erase_sector(target *t, int argc, const char **argv)
} else if (argc == 2) } else if (argc == 2)
length = strtoul(argv[1], NULL, 0); length = strtoul(argv[1], NULL, 0);
else else
return -1; return false;
rp_priv_s *ps = (rp_priv_s *)t->target_storage; rp_priv_s *ps = (rp_priv_s *)t->target_storage;
ps->is_monitor = true; ps->is_monitor = true;
const bool result = rp_flash_erase(t->flash, start, length); bool ret = true; /* catch false returns with &= */
ret &= rp_flash_prepare(t);
ret &= rp_flash_erase(t->flash, start, length);
ret &= rp_flash_resume(t);
ps->is_monitor = false; ps->is_monitor = false;
return result; 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)