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 <jhalfmoon@milksnot.com>


git-svn-id: svn://svn.berlios.de/openocd/trunk@2746 b42882b7-edfa-0310-969c-e2dbd0fdcd60
__archive__
dbrownell 2009-09-22 05:39:06 +00:00
parent 6cba486356
commit 50b94628ae
2 changed files with 99 additions and 54 deletions

View File

@ -3187,8 +3187,11 @@ and AT91SAM7 on-chip flash.
@anchor{flash erase_sector} @anchor{flash erase_sector}
@deffn Command {flash erase_sector} num first last @deffn Command {flash erase_sector} num first last
Erase sectors in bank @var{num}, starting at sector @var{first} up to and including Erase sectors in bank @var{num}, starting at sector @var{first}
@var{last}. Sector numbering starts at 0. 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}. The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn @end deffn
@ -3247,7 +3250,7 @@ and display that status.
The @var{num} parameter is a value shown by @command{flash banks}. The @var{num} parameter is a value shown by @command{flash banks}.
This is the only operation that This is the only operation that
updates the erase state information displayed by @option{flash info}. That means you have 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. to get updated information.
(Code execution may have invalidated any state records kept by OpenOCD.) (Code execution may have invalidated any state records kept by OpenOCD.)
@end deffn @end deffn
@ -3259,9 +3262,12 @@ The information includes per-sector protect status.
@end deffn @end deffn
@anchor{flash protect} @anchor{flash protect}
@deffn Command {flash protect} num first last (on|off) @deffn Command {flash protect} num first last (@option{on}|@option{off})
Enable (@var{on}) or disable (@var{off}) protection of flash sectors Enable (@option{on}) or disable (@option{off}) protection of flash sectors
@var{first} to @var{last} of flash bank @var{num}. 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}. The @var{num} parameter is a value shown by @command{flash banks}.
@end deffn @end deffn

View File

@ -559,82 +559,121 @@ static int handle_flash_protect_check_command(struct command_context_s *cmd_ctx,
return ERROR_OK; 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) if (!(first <= last)) {
{ command_print(cmd_ctx, "ERROR: "
int first = strtoul(args[1], NULL, 0); "first sector must be <= last sector");
int last = strtoul(args[2], NULL, 0); return ERROR_FAIL;
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);
}
} }
else
{ if (!(last <= (num_sectors - 1))) {
return ERROR_COMMAND_SYNTAX_ERROR; command_print(cmd_ctx, "ERROR: "
"last sector must be <= %d", num_sectors - 1);
return ERROR_FAIL;
} }
return ERROR_OK; 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) if (argc > 3)
{ {
int first = strtoul(args[1], NULL, 0); uint32_t bank_nr;
int last = strtoul(args[2], NULL, 0); uint32_t first;
int set; uint32_t last;
int retval; 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) if (!p)
{
command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
return ERROR_OK; 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) if (strcmp(args[3], "on") == 0)
set = 1; set = 1;
else if (strcmp(args[3], "off") == 0) else if (strcmp(args[3], "off") == 0)
set = 0; set = 0;
else else
{
return ERROR_COMMAND_SYNTAX_ERROR; 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); retval = flash_driver_protect(p, set, first, last);
if (retval == ERROR_OK) if (retval == ERROR_OK) {
{ command_print(cmd_ctx, "%s protection for sectors %i "
command_print(cmd_ctx, "%s protection for sectors %i through %i on flash bank %li", "through %i on flash bank %i",
(set) ? "set" : "cleared", first, (set) ? "set" : "cleared", first,
last, strtoul(args[0], 0, 0)); last, bank_nr);
} }
} }
else else
{
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
}
return ERROR_OK; return ERROR_OK;
} }