From 1fbf1d956322dc10ad13c717bd6c8d80529e0c87 Mon Sep 17 00:00:00 2001 From: Hannes Weisbach Date: Tue, 14 May 2024 13:46:00 +0200 Subject: [PATCH] feat: --mass-erase for st-flash write commands Force a flash mass erase instead a flash sector erase when programming the flash by providing a '--mass-erase' flag for the 'write' and 'erase' commands. Signed-off-by: Hannes Weisbach --- src/st-flash/flash.c | 36 ++++++++++++++++++++++++----------- src/st-flash/flash_opts.c | 2 ++ src/st-flash/flash_opts.h | 3 ++- src/stlink-gui/gui.c | 5 +++-- src/stlink-lib/common_flash.c | 18 ++++++++++++------ src/stlink-lib/common_flash.h | 19 ++++++++++++++---- tests/flash.c | 16 +++++++++++++++- 7 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index 0b7c0cfca..cd27cebee 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -100,6 +100,7 @@ int32_t main(int32_t ac, char** av) { sl->verbose = o.log_level; sl->opt = o.opt; + const enum erase_type_t erase_type = o.mass_erase ? MASS_ERASE : SECTION_ERASE; connected_stlink = sl; signal(SIGINT, &cleanup); @@ -120,6 +121,14 @@ int32_t main(int32_t ac, char** av) { if (o.cmd == FLASH_CMD_WRITE) { uint32_t size = 0; + if (erase_type == MASS_ERASE) { + err = stlink_erase_flash_mass(sl); + if (err == -1) { + printf("stlink_erase_flash_mass() == -1\n"); + goto on_error; + } + } + // write if (o.format == FLASH_FORMAT_IHEX) { err = stlink_parse_ihex(o.filename, stlink_get_erased_pattern(sl), &mem, &size, &o.addr); @@ -131,9 +140,9 @@ int32_t main(int32_t ac, char** av) { } if ((o.addr >= sl->flash_base) && (o.addr < sl->flash_base + sl->flash_size)) { if (o.format == FLASH_FORMAT_IHEX) { - err = stlink_mwrite_flash(sl, mem, size, o.addr); + err = stlink_mwrite_flash(sl, mem, size, o.addr, erase_type); } else { - err = stlink_fwrite_flash(sl, o.filename, o.addr); + err = stlink_fwrite_flash(sl, o.filename, o.addr, erase_type); } if (err == -1) { @@ -188,7 +197,7 @@ int32_t main(int32_t ac, char** av) { printf("OTP Write NOT implemented\n"); goto on_error; } - err = stlink_fwrite_flash(sl, o.filename, o.addr); + err = stlink_fwrite_flash(sl, o.filename, o.addr, NO_ERASE); if (err == -1) { printf("stlink_fwrite_flash() == -1\n"); @@ -203,16 +212,21 @@ int32_t main(int32_t ac, char** av) { } else if (o.cmd == FLASH_CMD_ERASE) { // erase - if (o.size > 0 && o.addr > 0) { - err = stlink_erase_flash_section(sl, o.addr, o.size, false); + if ((erase_type == MASS_ERASE) || (o.size == 0 || o.addr == 0)) { + err = stlink_erase_flash_mass(sl); + if (err == -1) { + printf("stlink_erase_flash_mass() == -1\n"); + goto on_error; + } + printf("Mass erase completed successfully.\n"); } else { - err = stlink_erase_flash_mass(sl); - } - if (err == -1) { - printf("stlink_erase_flash_mass() == -1\n"); - goto on_error; + err = stlink_erase_flash_section(sl, o.addr, o.size, false); + if (err == -1) { + printf("stlink_erase_flash_section() == -1\n"); + goto on_error; + } + printf("Section erase completed successfully.\n"); } - printf("Mass erase completed successfully.\n"); // reset after erase if (stlink_reset(sl, RESET_AUTO)) { diff --git a/src/st-flash/flash_opts.c b/src/st-flash/flash_opts.c index e2d4154fe..bdb718b09 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -102,6 +102,8 @@ int32_t flash_get_opts(struct flash_opts* o, int32_t ac, char** av) { o->log_level = DEBUG_LOG_LEVEL; } else if (strcmp(av[0], "--opt") == 0) { o->opt = ENABLE_OPT; + } else if (strcmp(av[0], "--mass-erase") == 0) { + o->mass_erase = ENABLE_OPT; } else if (strcmp(av[0], "--reset") == 0) { o->reset = 1; } else if (strcmp(av[0], "--serial") == 0 || starts_with(av[0], "--serial=")) { diff --git a/src/st-flash/flash_opts.h b/src/st-flash/flash_opts.h index 0c0083db6..ae21f3244 100644 --- a/src/st-flash/flash_opts.h +++ b/src/st-flash/flash_opts.h @@ -7,7 +7,7 @@ #ifndef FLASH_OPTS_H #define FLASH_OPTS_H -#define FLASH_OPTS_INITIALIZER {0, { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define FLASH_OPTS_INITIALIZER {0, { 0 }, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} enum flash_cmd {FLASH_CMD_NONE = 0, FLASH_CMD_WRITE = 1, FLASH_CMD_READ = 2, FLASH_CMD_ERASE = 3, CMD_RESET = 4}; enum flash_format {FLASH_FORMAT_BINARY = 0, FLASH_FORMAT_IHEX = 1}; @@ -26,6 +26,7 @@ struct flash_opts { uint32_t val; uint32_t flash_size; // --flash=n[k, M] int32_t opt; // enable empty tail data drop optimization + int32_t mass_erase; // Use mass-erase when programming flash instead of sector-erase int32_t freq; // --freq=n[k, M] frequency of JTAG/SWD enum connect_type connect; }; diff --git a/src/stlink-gui/gui.c b/src/stlink-gui/gui.c index 51ee293e8..7e1d27d33 100644 --- a/src/stlink-gui/gui.c +++ b/src/stlink-gui/gui.c @@ -596,8 +596,9 @@ static gpointer stlink_gui_write_flash(gpointer data) { g_return_val_if_fail((gui->sl != NULL), NULL); g_return_val_if_fail((gui->filename != NULL), NULL); - if (stlink_mwrite_flash( - gui->sl, gui->file_mem.memory, (uint32_t)gui->file_mem.size, gui->sl->flash_base) < 0) { + if (stlink_mwrite_flash(gui->sl, gui->file_mem.memory, + (uint32_t)gui->file_mem.size, gui->sl->flash_base, + SECTION_ERASE) < 0) { stlink_gui_set_info_error_message(gui, "Failed to write to flash"); } diff --git a/src/stlink-lib/common_flash.c b/src/stlink-lib/common_flash.c index aa8db5bfd..8142c82f3 100644 --- a/src/stlink-lib/common_flash.c +++ b/src/stlink-lib/common_flash.c @@ -1281,7 +1281,9 @@ int32_t stlink_erase_flash_mass(stlink_t *sl) { return (err); } -int32_t stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, stm32_addr_t addr) { +int32_t stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, + stm32_addr_t addr, + const enum erase_type_t erase_type) { /* Write the block in flash at addr */ int32_t err; uint32_t num_empty, idx; @@ -1315,7 +1317,7 @@ int32_t stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, stm32_ */ err = stlink_write_flash(sl, addr, data, (num_empty == length) ? length : length - num_empty, - num_empty == length); + num_empty == length, erase_type); stlink_fwrite_finalize(sl, addr); return (err); } @@ -1327,7 +1329,8 @@ int32_t stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, stm32_ * @param addr where to start writing * @return 0 on success, -ve on failure. */ -int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { +int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr, + const enum erase_type_t erase_type) { /* Write the file in flash at addr */ int32_t err; uint32_t num_empty, idx; @@ -1374,7 +1377,7 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { } else { err = stlink_write_flash(sl, addr, mf.base, (num_empty == mf.len) ? (uint32_t)mf.len : (uint32_t)mf.len - num_empty, - num_empty == mf.len); + num_empty == mf.len, erase_type); } stlink_fwrite_finalize(sl, addr); unmap_file(&mf); @@ -1483,7 +1486,9 @@ int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr) { return 0; } -int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len, uint8_t eraseonly) { +int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, + uint32_t len, uint8_t eraseonly, + const enum erase_type_t erase_type) { int32_t ret; flash_loader_t fl; ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n", len, len, addr, addr); @@ -1509,7 +1514,8 @@ int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint3 stlink_core_id(sl); // Erase this section of the flash - if (stlink_erase_flash_section(sl, addr, len, true) < 0) { + if ((erase_type == SECTION_ERASE) && + stlink_erase_flash_section(sl, addr, len, true) < 0) { ELOG("Failed to erase the flash prior to writing\n"); return (-1); } diff --git a/src/stlink-lib/common_flash.h b/src/stlink-lib/common_flash.h index 238f0403e..a85e54394 100644 --- a/src/stlink-lib/common_flash.h +++ b/src/stlink-lib/common_flash.h @@ -10,6 +10,12 @@ #define BANK_1 0 #define BANK_2 1 +enum erase_type_t { + NO_ERASE = 0, + SECTION_ERASE = 1, + MASS_ERASE = 2, +}; + uint32_t get_stm32l0_flash_base(stlink_t *); uint32_t read_flash_cr(stlink_t *, uint32_t); void lock_flash(stlink_t *); @@ -39,15 +45,20 @@ void clear_flash_cr_pg(stlink_t *, uint32_t); int32_t stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr); int32_t stlink_erase_flash_section(stlink_t *sl, stm32_addr_t base_addr, uint32_t size, bool align_size); int32_t stlink_erase_flash_mass(stlink_t *sl); -int32_t stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, stm32_addr_t addr); -int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr); +int32_t stlink_mwrite_flash(stlink_t *sl, uint8_t *data, uint32_t length, + stm32_addr_t addr, const enum erase_type_t erase); +int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr, + const enum erase_type_t erase); int32_t stlink_fcheck_flash(stlink_t *sl, const char *path, stm32_addr_t addr); int32_t stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, uint32_t length); int32_t stlink_check_address_range_validity(stlink_t *sl, stm32_addr_t addr, uint32_t size); int32_t stlink_check_address_range_validity_otp(stlink_t *sl, stm32_addr_t addr, uint32_t size); int32_t stlink_check_address_alignment(stlink_t *sl, stm32_addr_t addr); -int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len, uint8_t eraseonly); -int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, uint32_t len); +int32_t stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t *base, + uint32_t len, uint8_t erase_only, + const enum erase_type_t erase); +int32_t stlink_write_otp(stlink_t *sl, stm32_addr_t addr, uint8_t *base, + uint32_t len); void stlink_fwrite_finalize(stlink_t *, stm32_addr_t); #endif // COMMON_FLASH_H diff --git a/tests/flash.c b/tests/flash.c index 4d9ac5185..14405f300 100644 --- a/tests/flash.c +++ b/tests/flash.c @@ -91,7 +91,7 @@ static struct Test tests[] = { .freq = 0, .format = FLASH_FORMAT_BINARY } }, - { "--debug --reset write test.bin 0x80000000", 0, + { "--debug --mass-erase --reset write test.bin 0x80000000", 0, { .cmd = FLASH_CMD_WRITE, .serial = { 0 }, .filename = "test.bin", @@ -99,6 +99,7 @@ static struct Test tests[] = { .size = 0, .reset = 1, .log_level = DEBUG_LOG_LEVEL, + .mass_erase = 1, .freq = 0, .format = FLASH_FORMAT_BINARY } }, @@ -187,6 +188,19 @@ static struct Test tests[] = { .size = 0, .reset = 0, .log_level = STND_LOG_LEVEL, + .mass_erase = 1, + .freq = 0, + .format = FLASH_FORMAT_BINARY } + }, + { "--mass-erase erase", 0, + { .cmd = FLASH_CMD_ERASE, + .serial = { 0 }, + .filename = NULL, + .addr = 0, + .size = 0, + .reset = 0, + .log_level = STND_LOG_LEVEL, + .mass_erase = 1, .freq = 0, .format = FLASH_FORMAT_BINARY } },