From 50b94628aec9b94e2aa6d326c48c896c718d7e46 Mon Sep 17 00:00:00 2001 From: dbrownell Date: Tue, 22 Sep 2009 05:39:06 +0000 Subject: [PATCH] Make it easier to erase or protect through to the end of a (NOR) flash chip: allow passing "last" as an alias for the number of the last sector. Improve several aspects of error checking while we're at it. From: Johnny Halfmoon git-svn-id: svn://svn.berlios.de/openocd/trunk@2746 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- doc/openocd.texi | 18 ++++--- src/flash/flash.c | 135 +++++++++++++++++++++++++++++----------------- 2 files changed, 99 insertions(+), 54 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 32501ca6a..893d738c9 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3187,8 +3187,11 @@ and AT91SAM7 on-chip flash. @anchor{flash erase_sector} @deffn Command {flash erase_sector} num first last -Erase sectors in bank @var{num}, starting at sector @var{first} up to and including -@var{last}. Sector numbering starts at 0. +Erase sectors in bank @var{num}, starting at sector @var{first} +up to and including @var{last}. +Sector numbering starts at 0. +Providing a @var{last} sector of @option{last} +specifies "to the end of the flash bank". The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @@ -3247,7 +3250,7 @@ and display that status. The @var{num} parameter is a value shown by @command{flash banks}. This is the only operation that updates the erase state information displayed by @option{flash info}. That means you have -to issue an @command{flash erase_check} command after erasing or programming the device +to issue a @command{flash erase_check} command after erasing or programming the device to get updated information. (Code execution may have invalidated any state records kept by OpenOCD.) @end deffn @@ -3259,9 +3262,12 @@ The information includes per-sector protect status. @end deffn @anchor{flash protect} -@deffn Command {flash protect} num first last (on|off) -Enable (@var{on}) or disable (@var{off}) protection of flash sectors -@var{first} to @var{last} of flash bank @var{num}. +@deffn Command {flash protect} num first last (@option{on}|@option{off}) +Enable (@option{on}) or disable (@option{off}) protection of flash sectors +in flash bank @var{num}, starting at sector @var{first} +and continuing up to and including @var{last}. +Providing a @var{last} sector of @option{last} +specifies "to the end of the flash bank". The @var{num} parameter is a value shown by @command{flash banks}. @end deffn diff --git a/src/flash/flash.c b/src/flash/flash.c index e73dfa701..ef4f342c6 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -559,82 +559,121 @@ static int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, return ERROR_OK; } -static int handle_flash_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int flash_check_sector_parameters(struct command_context_s *cmd_ctx, + uint32_t first, uint32_t last, uint num_sectors) { - if (argc > 2) - { - int first = strtoul(args[1], NULL, 0); - int last = strtoul(args[2], NULL, 0); - int retval; - flash_bank_t *p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); - duration_t duration; - char *duration_text; - - duration_start_measure(&duration); - - if (!p) - { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - if ((retval = flash_driver_erase(p, first, last)) == ERROR_OK) - { - if ((retval = duration_stop_measure(&duration, &duration_text)) != ERROR_OK) - { - return retval; - } - - command_print(cmd_ctx, "erased sectors %i through %i on flash bank %li in %s", - first, last, strtoul(args[0], 0, 0), duration_text); - free(duration_text); - } + if (!(first <= last)) { + command_print(cmd_ctx, "ERROR: " + "first sector must be <= last sector"); + return ERROR_FAIL; } - else - { - return ERROR_COMMAND_SYNTAX_ERROR; + + if (!(last <= (num_sectors - 1))) { + command_print(cmd_ctx, "ERROR: " + "last sector must be <= %d", num_sectors - 1); + return ERROR_FAIL; } return ERROR_OK; } -static int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int handle_flash_erase_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) +{ + if (argc > 2) + { + uint32_t bank_nr; + uint32_t first; + uint32_t last; + int retval; + + if ((retval = parse_u32(args[0], &bank_nr)) != ERROR_OK) + return retval; + + flash_bank_t *p = get_flash_bank_by_num(bank_nr); + if (!p) + return ERROR_OK; + + if ((retval = parse_u32(args[1], &first)) != ERROR_OK) + return retval; + if (strcmp(args[2], "last") == 0) + last = p->num_sectors - 1; + else + if ((retval = parse_u32(args[2], &last)) != ERROR_OK) + return retval; + + if ((retval = flash_check_sector_parameters(cmd_ctx, + first, last, p->num_sectors)) != ERROR_OK) + return retval; + + duration_t duration; + char *duration_text; + duration_start_measure(&duration); + + if ((retval = flash_driver_erase(p, first, last)) == ERROR_OK) { + if ((retval = duration_stop_measure(&duration, + &duration_text)) != ERROR_OK) + return retval; + command_print(cmd_ctx, "erased sectors %i through %i " + "on flash bank %i in %s", + first, last, bank_nr, duration_text); + free(duration_text); + } + } + else + return ERROR_COMMAND_SYNTAX_ERROR; + + return ERROR_OK; +} + +static int handle_flash_protect_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) { if (argc > 3) { - int first = strtoul(args[1], NULL, 0); - int last = strtoul(args[2], NULL, 0); - int set; + uint32_t bank_nr; + uint32_t first; + uint32_t last; int retval; - flash_bank_t *p = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + int set; + + if ((retval = parse_u32(args[0], &bank_nr)) != ERROR_OK) + return retval; + + flash_bank_t *p = get_flash_bank_by_num(bank_nr); if (!p) - { - command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); return ERROR_OK; - } + + if ((retval = parse_u32(args[1], &first)) != ERROR_OK) + return retval; + if (strcmp(args[2], "last") == 0) + last = p->num_sectors - 1; + else + if ((retval = parse_u32(args[2], &last)) != ERROR_OK) + return retval; if (strcmp(args[3], "on") == 0) set = 1; else if (strcmp(args[3], "off") == 0) set = 0; else - { return ERROR_COMMAND_SYNTAX_ERROR; - } + + if ((retval = flash_check_sector_parameters(cmd_ctx, + first, last, p->num_sectors)) != ERROR_OK) + return retval; retval = flash_driver_protect(p, set, first, last); - if (retval == ERROR_OK) - { - command_print(cmd_ctx, "%s protection for sectors %i through %i on flash bank %li", + if (retval == ERROR_OK) { + command_print(cmd_ctx, "%s protection for sectors %i " + "through %i on flash bank %i", (set) ? "set" : "cleared", first, - last, strtoul(args[0], 0, 0)); + last, bank_nr); } } else - { return ERROR_COMMAND_SYNTAX_ERROR; - } - return ERROR_OK; }