diff --git a/src/st-flash/flash.c b/src/st-flash/flash.c index 56556ee2..521cd2b4 100644 --- a/src/st-flash/flash.c +++ b/src/st-flash/flash.c @@ -119,6 +119,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); @@ -139,6 +140,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); @@ -150,9 +159,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) { @@ -207,7 +216,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"); @@ -222,16 +231,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 9fe35cad..96955693 100644 --- a/src/st-flash/flash_opts.c +++ b/src/st-flash/flash_opts.c @@ -104,6 +104,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 0c0083db..ae21f324 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 bc24591e..61c7eaa1 100644 --- a/src/stlink-gui/gui.c +++ b/src/stlink-gui/gui.c @@ -593,8 +593,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 663dd813..0446abdf 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; @@ -1373,8 +1376,8 @@ int32_t stlink_fwrite_flash(stlink_t *sl, const char *path, stm32_addr_t addr) { (num_empty == mf.len) ? (uint32_t) mf.len : (uint32_t) mf.len - num_empty); } 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) ? (uint32_t) mf.len : (uint32_t)mf.len - num_empty, + 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 238f0403..a85e5439 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 7c54221f..2665d8cd 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 } },