X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fflash.c;h=2e7cc4537e2f7e41421bbe6b8536d71d22ef5217;hp=2271f603cc74bf92eaf81d6ffca8886822898e79;hb=1796e1602e9ffe1cbf35f1b001cb6a534bb2f738;hpb=f328fb8a6ce37c2af441d08d41d683d70454334a diff --git a/src/flash/flash.c b/src/flash/flash.c index 2271f603cc..2e7cc4537e 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -43,6 +43,7 @@ int handle_flash_banks_command(struct command_context_s *cmd_ctx, char *cmd, cha int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_probe_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); @@ -50,6 +51,7 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr); /* flash drivers */ @@ -61,6 +63,7 @@ extern flash_driver_t str9x_flash; extern flash_driver_t stellaris_flash; extern flash_driver_t str9xpec_flash; extern flash_driver_t stm32x_flash; +extern flash_driver_t tms470_flash; flash_driver_t *flash_drivers[] = { @@ -72,6 +75,7 @@ flash_driver_t *flash_drivers[] = &stellaris_flash, &str9xpec_flash, &stm32x_flash, + &tms470_flash, NULL, }; @@ -88,7 +92,7 @@ int flash_register_commands(struct command_context_s *cmd_ctx) return ERROR_OK; } -int flash_init(struct command_context_s *cmd_ctx) +int flash_init_drivers(struct command_context_s *cmd_ctx) { if (flash_banks) { @@ -103,13 +107,17 @@ int flash_init(struct command_context_s *cmd_ctx) register_command(cmd_ctx, flash_cmd, "protect_check", handle_flash_protect_check_command, COMMAND_EXEC, "check protection state of sectors in flash bank "); register_command(cmd_ctx, flash_cmd, "erase", handle_flash_erase_command, COMMAND_EXEC, + "DEPRECATED, use 'erase_sector' instead"); + register_command(cmd_ctx, flash_cmd, "erase_sector", handle_flash_erase_command, COMMAND_EXEC, "erase sectors at "); + register_command(cmd_ctx, flash_cmd, "erase_address", handle_flash_erase_address_command, COMMAND_EXEC, + "erase address range
"); register_command(cmd_ctx, flash_cmd, "write", handle_flash_write_binary_command, COMMAND_EXEC, - "DEPRECATED, use 'write_binary' or 'write_image' instead"); + "DEPRECATED, use 'write_binary' instead"); register_command(cmd_ctx, flash_cmd, "write_binary", handle_flash_write_binary_command, COMMAND_EXEC, "write binary "); register_command(cmd_ctx, flash_cmd, "write_image", handle_flash_write_image_command, COMMAND_EXEC, - "write image [offset] [type]"); + "write_image [offset] [type]"); register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC, "set protection of sectors at "); register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_EXEC, @@ -176,8 +184,8 @@ int handle_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char c->base = strtoul(args[1], NULL, 0); c->size = strtoul(args[2], NULL, 0); c->chip_width = strtoul(args[3], NULL, 0); - c->bus_width = strtoul(args[4], NULL, 0); - c->num_sectors = 0; + c->bus_width = strtoul(args[4], NULL, 0); + c->num_sectors = 0; c->sectors = NULL; c->next = NULL; @@ -355,6 +363,76 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm return ERROR_OK; } +int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *p; + int retval; + int address; + int length; + duration_t duration; + char *duration_text; + + target_t *target = get_current_target(cmd_ctx); + + if (argc != 2) + { + command_print(cmd_ctx, "usage: flash erase_address
"); + return ERROR_OK; + } + + address = strtoul(args[0], NULL, 0); + length = strtoul(args[1], NULL, 0); + if (length <= 0) + { + command_print(cmd_ctx, "Length must be >0"); + return ERROR_INVALID_ARGUMENTS; + } + + p = get_flash_bank_by_addr(target, address); + if (p == NULL) + { + command_print(cmd_ctx, "No flash at that address"); + return ERROR_INVALID_ARGUMENTS; + } + + /* We can't know if we did a resume + halt, in which case we no longer know the erased state */ + flash_set_dirty(); + + duration_start_measure(&duration); + + if ((retval = flash_erase_address_range(target, address, length)) != ERROR_OK) + { + switch (retval) + { + case ERROR_TARGET_NOT_HALTED: + command_print(cmd_ctx, "can't work with this flash while target is running"); + break; + case ERROR_INVALID_ARGUMENTS: + command_print(cmd_ctx, "usage: flash erase_address
"); + break; + case ERROR_FLASH_BANK_INVALID: + command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base); + break; + case ERROR_FLASH_OPERATION_FAILED: + command_print(cmd_ctx, "flash erase error"); + break; + case ERROR_FLASH_SECTOR_INVALID: + command_print(cmd_ctx, "sector number(s) invalid"); + break; + default: + command_print(cmd_ctx, "unknown error"); + } + } + else + { + duration_stop_measure(&duration, &duration_text); + command_print(cmd_ctx, "erased address 0x%8.8x length %i in %s", address, length, duration_text); + free(duration_text); + } + + return retval; +} + int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) { flash_bank_t *p; @@ -530,17 +608,11 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm char *duration_text; int retval; - - if (!strcmp(cmd, "write")) - { - command_print(cmd_ctx, "'flash write' has been deprecated in favor of 'flash write_binary' and 'flash write_image'"); - DEBUG("'flash write' has been deprecated in favor of 'flash write_binary' and 'flash write_image'"); - } if (argc < 1) { - command_print(cmd_ctx, "usage: flash write [offset] [type]"); - return ERROR_OK; + command_print(cmd_ctx, "usage: flash %s [offset] [type]", cmd); + return ERROR_INVALID_ARGUMENTS; } if (!target) @@ -563,8 +635,8 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm } image.start_address_set = 0; - - retval = image_open(&image, args[0], (argc == 4) ? args[2] : NULL); + + retval = image_open(&image, args[0], (argc == 3) ? args[2] : NULL); if (retval != ERROR_OK) { command_print(cmd_ctx, "image_open error: %s", image.error_str); @@ -573,7 +645,8 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm failed = malloc(sizeof(int) * image.num_sections); - error_str=NULL; + error_str = NULL; + retval = flash_write(target, &image, &written, &error_str, failed, auto_erase); if (retval != ERROR_OK) @@ -601,7 +674,6 @@ int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cm command_print(cmd_ctx, "wrote %u byte from file %s in %s (%f kb/s)", written, args[0], duration_text, (float)written / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0))); - free(duration_text); free(failed); @@ -626,7 +698,7 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c if (argc < 3) { - command_print(cmd_ctx, "usage: flash write "); + command_print(cmd_ctx, "usage: flash write_binary "); return ERROR_OK; } @@ -642,14 +714,14 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) { - command_print(cmd_ctx, "flash write error: %s", fileio.error_str); + command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str); return ERROR_OK; } buffer = malloc(fileio.size); if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK) { - command_print(cmd_ctx, "flash write error: %s", fileio.error_str); + command_print(cmd_ctx, "flash write_binary error: %s", fileio.error_str); return ERROR_OK; } @@ -657,6 +729,7 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c { command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x", args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0)); + switch (retval) { case ERROR_TARGET_NOT_HALTED: @@ -698,6 +771,21 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c return ERROR_OK; } +void flash_set_dirty(void) +{ + flash_bank_t *c; + int i; + + /* set all flash to require erasing */ + for (c = flash_banks; c; c = c->next) + { + for (i = 0; i < c->num_sectors; i++) + { + c->sectors[i].is_erased = 0; + } + } +} + /* lookup flash bank by address */ flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr) { @@ -715,7 +803,7 @@ flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr) } /* erase given flash region, selects proper bank according to target and address */ -int flash_erase(target_t *target, u32 addr, u32 length) +int flash_erase_address_range(target_t *target, u32 addr, u32 length) { flash_bank_t *c; int first = -1; @@ -760,7 +848,7 @@ int flash_erase(target_t *target, u32 addr, u32 length) return c->driver->erase(c, first, last); } -/* write an image to flash memory of the given target */ +/* write (optional verify) an image to flash memory of the given target */ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str, int *failed, int erase) { int retval; @@ -768,7 +856,8 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str int section; u32 section_offset; - + flash_bank_t *c; + section = 0; section_offset = 0; @@ -778,17 +867,24 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str if (failed != NULL) for (i = 0; i < image->num_sections; i++) failed[i] = 0; - + + if (erase) + { + /* assume all sectors need erasing - stops any problems + * when flash_write is called multiple times */ + + flash_set_dirty(); + } + /* loop until we reach end of the image */ while (section < image->num_sections) { - flash_bank_t *c; u32 buffer_size; u8 *buffer; int section_first; int section_last; - u32 run_address = image->sections[section].base_address+section_offset; - u32 run_size = image->sections[section].size-section_offset; + u32 run_address = image->sections[section].base_address + section_offset; + u32 run_size = image->sections[section].size - section_offset; if (image->sections[section].size == 0) { @@ -823,7 +919,7 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str { if (image->sections[section_last + 1].base_address < (run_address + run_size)) { - WARNING("section %d out of order", section_last + 1); + DEBUG("section %d out of order(very slightly surprising, but supported)", section_last + 1); break; } if (image->sections[section_last + 1].base_address != (run_address + run_size)) @@ -883,7 +979,7 @@ int flash_write(target_t *target, image_t *image, u32 *written, char **error_str if (erase) { /* calculate and erase sectors */ - retval = flash_erase( target, run_address, run_size ); + retval = flash_erase_address_range( target, run_address, run_size ); } if (retval == ERROR_OK) @@ -949,5 +1045,3 @@ int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd return ERROR_OK; } - -