diff --git a/src/target/lpc546xx.c b/src/target/lpc546xx.c index 20d7b63..3ac4a5f 100644 --- a/src/target/lpc546xx.c +++ b/src/target/lpc546xx.c @@ -45,7 +45,6 @@ #define IAP_PGM_CHUNKSIZE 4096 -static bool lpc546xx_cmd_erase_mass(target *t, int argc, const char *argv[]); static bool lpc546xx_cmd_erase_sector(target *t, int argc, const char *argv[]); static bool lpc546xx_cmd_read_partid(target *t, int argc, const char *argv[]); static bool lpc546xx_cmd_read_uid(target *t, int argc, const char *argv[]); @@ -56,15 +55,13 @@ static bool lpc546xx_cmd_write_sector(target *t, int argc, const char *argv[]); static void lpc546xx_reset_attach(target *t); static int lpc546xx_flash_init(target *t); static int lpc546xx_flash_erase(struct target_flash *f, target_addr addr, size_t len); +static bool lpc546xx_mass_erase(target *t); static void lpc546xx_wdt_set_period(target *t); static void lpc546xx_wdt_pet(target *t); const struct command_s lpc546xx_cmd_list[] = { - { "erase_mass", lpc546xx_cmd_erase_mass, "Erase entire flash memory" }, - { "erase_sector", lpc546xx_cmd_erase_sector, - "Erase a sector by number" }, - { "read_partid", lpc546xx_cmd_read_partid, - "Read out the 32-bit part ID using IAP." }, + { "erase_sector", lpc546xx_cmd_erase_sector, "Erase a sector by number" }, + { "read_partid", lpc546xx_cmd_read_partid, "Read out the 32-bit part ID using IAP." }, { "read_uid", lpc546xx_cmd_read_uid, "Read out the 16-byte UID." }, { "reset_attach", lpc546xx_cmd_reset_attach, "Reset target. Reset debug registers. Re-attach debugger. This restores " @@ -153,8 +150,8 @@ bool lpc546xx_probe(target *t) return false; } - lpc546xx_add_flash(t, IAP_ENTRYPOINT_LOCATION, 0, 0x0, flash_size, - 0x8000); + t->mass_erase = lpc546xx_mass_erase; + lpc546xx_add_flash(t, IAP_ENTRYPOINT_LOCATION, 0, 0x0, flash_size, 0x8000); /* Note: upper 96kB is only usable after enabling the appropriate control register bits, see LPC546xx User Manual: 7.5.19 AHB Clock Control register 0 @@ -178,22 +175,12 @@ static void lpc546xx_reset_attach(target *t) cortexm_attach(t); } -static bool lpc546xx_cmd_erase_mass(target *t, int argc, const char *argv[]) +static bool lpc546xx_mass_erase(target *t) { - (void)argc; - (void)argv; - - int result = lpc546xx_flash_erase(t->flash, t->flash->start, - t->flash->length); - - if (result != 0) { + const int result = lpc546xx_flash_erase(t->flash, t->flash->start, t->flash->length); + if (result != 0) tc_printf(t, "Error erasing flash: %d\n", result); - return false; - } - - tc_printf(t, "Erase OK.\n"); - - return true; + return result == 0; } static bool lpc546xx_cmd_erase_sector(target *t, int argc, const char *argv[]) diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index 1b787ac..c82cbd8 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -93,6 +93,18 @@ struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length) return lf; } +static uint8_t lpc_sector_for_addr(struct lpc_flash *f, uint32_t addr) +{ + return f->base_sector + (addr - f->f.start) / f->f.blocksize; +} + +static inline bool lpc_is_full_erase(struct lpc_flash *f, const uint32_t begin, const uint32_t end) +{ + const target_addr addr = f->f.start; + const size_t len = f->f.length; + return begin == lpc_sector_for_addr(f, addr) && end == lpc_sector_for_addr(f, addr + len - 1U); +} + enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd, ...) { target *t = f->f.t; @@ -133,10 +145,15 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd regs[REG_PC] = f->iap_entry; target_regs_write(t, regs); + platform_timeout timeout; + platform_timeout_set(&timeout, 500); + const bool full_erase = cmd == IAP_CMD_ERASE && lpc_is_full_erase(f, param.words[0], param.words[1]); /* start the target and wait for it to halt again */ target_halt_resume(t, false); - while (!target_halt_poll(t, NULL)) - continue; + while (!target_halt_poll(t, NULL)) { + if (full_erase) + target_print_progress(&timeout); + } /* copy back just the parameters structure */ target_mem_read(t, ¶m, f->iap_ram, sizeof(param)); @@ -163,28 +180,23 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd return param.status; } -static uint8_t lpc_sector_for_addr(struct lpc_flash *f, uint32_t addr) -{ - return f->base_sector + (addr - f->f.start) / f->f.blocksize; -} - #define LPX80X_SECTOR_SIZE 0x400 #define LPX80X_PAGE_SIZE 0x40 int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len) { struct lpc_flash *f = (struct lpc_flash *)tf; - uint32_t start = lpc_sector_for_addr(f, addr); - uint32_t end = lpc_sector_for_addr(f, addr + len - 1); + const uint32_t start = lpc_sector_for_addr(f, addr); + const uint32_t end = lpc_sector_for_addr(f, addr + len - 1U); uint32_t last_full_sector = end; if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, start, end, f->bank)) return -1; /* Only LPC80x has reserved pages!*/ - if (f->reserved_pages && ((addr + len) >= tf->length - 0x400) ) { - last_full_sector -= 1; - } + if (f->reserved_pages && addr + len >= tf->length - 0x400U) + --last_full_sector; + if (start <= last_full_sector) { /* Sector erase */ if (lpc_iap_call(f, NULL, IAP_CMD_ERASE, start, last_full_sector, CPU_CLK_KHZ, f->bank)) @@ -194,9 +206,11 @@ int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len) if (lpc_iap_call(f, NULL, IAP_CMD_BLANKCHECK, start, last_full_sector, f->bank)) return -3; } + if (last_full_sector != end) { - uint32_t page_start = (addr + len - LPX80X_SECTOR_SIZE) / LPX80X_PAGE_SIZE; - uint32_t page_end = page_start + LPX80X_SECTOR_SIZE/LPX80X_PAGE_SIZE - 1 - f->reserved_pages; + const uint32_t page_start = (addr + len - LPX80X_SECTOR_SIZE) / LPX80X_PAGE_SIZE; + const uint32_t page_end = page_start + LPX80X_SECTOR_SIZE / LPX80X_PAGE_SIZE - 1 - f->reserved_pages; + if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, end, end, f->bank)) return -1;