flash: erase_address now has an unlock option
Quite useful to be able to unlock the flash, just like in the flash write_image cmd. Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>__archive__
parent
3077f5845f
commit
f7e0f3c285
|
@ -21,7 +21,7 @@ of the Open On-Chip Debugger (OpenOCD).
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item Copyright @copyright{} 2008 The OpenOCD Project
|
@item Copyright @copyright{} 2008 The OpenOCD Project
|
||||||
@item Copyright @copyright{} 2007-2008 Spencer Oliver @email{spen@@spen-soft.co.uk}
|
@item Copyright @copyright{} 2007-2008 Spencer Oliver @email{spen@@spen-soft.co.uk}
|
||||||
@item Copyright @copyright{} 2008 Oyvind Harboe @email{oyvind.harboe@@zylin.com}
|
@item Copyright @copyright{} 2008-2010 Oyvind Harboe @email{oyvind.harboe@@zylin.com}
|
||||||
@item Copyright @copyright{} 2008 Duane Ellis @email{openocd@@duaneellis.com}
|
@item Copyright @copyright{} 2008 Duane Ellis @email{openocd@@duaneellis.com}
|
||||||
@item Copyright @copyright{} 2009-2010 David Brownell
|
@item Copyright @copyright{} 2009-2010 David Brownell
|
||||||
@end itemize
|
@end itemize
|
||||||
|
@ -4043,7 +4043,7 @@ 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
|
||||||
|
|
||||||
@deffn Command {flash erase_address} [@option{pad}] address length
|
@deffn Command {flash erase_address} [@option{pad}] [@option{unlock}] address length
|
||||||
Erase sectors starting at @var{address} for @var{length} bytes.
|
Erase sectors starting at @var{address} for @var{length} bytes.
|
||||||
Unless @option{pad} is specified, @math{address} must begin a
|
Unless @option{pad} is specified, @math{address} must begin a
|
||||||
flash sector, and @math{address + length - 1} must end a sector.
|
flash sector, and @math{address + length - 1} must end a sector.
|
||||||
|
@ -4053,6 +4053,8 @@ The flash bank to use is inferred from the @var{address}, and
|
||||||
the specified length must stay within that bank.
|
the specified length must stay within that bank.
|
||||||
As a special case, when @var{length} is zero and @var{address} is
|
As a special case, when @var{length} is zero and @var{address} is
|
||||||
the start of the bank, the whole flash is erased.
|
the start of the bank, the whole flash is erased.
|
||||||
|
If @option{unlock} is specified, then the flash is unprotected
|
||||||
|
before erase starts.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {flash fillw} address word length
|
@deffn Command {flash fillw} address word length
|
||||||
|
|
|
@ -502,7 +502,7 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
|
||||||
return flash_driver_protect(bank, 0, first, last);
|
return flash_driver_protect(bank, 0, first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
|
int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
|
||||||
{
|
{
|
||||||
/* By default, pad to sector boundaries ... the real issue here
|
/* By default, pad to sector boundaries ... the real issue here
|
||||||
* is that our (only) caller *permanently* removes protection,
|
* is that our (only) caller *permanently* removes protection,
|
||||||
|
|
|
@ -108,6 +108,9 @@ int flash_register_commands(struct command_context *cmd_ctx);
|
||||||
int flash_erase_address_range(struct target *target,
|
int flash_erase_address_range(struct target *target,
|
||||||
bool pad, uint32_t addr, uint32_t length);
|
bool pad, uint32_t addr, uint32_t length);
|
||||||
|
|
||||||
|
int flash_unlock_address_range(struct target *target, uint32_t addr,
|
||||||
|
uint32_t length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes @a image into the @a target flash. The @a written parameter
|
* Writes @a image into the @a target flash. The @a written parameter
|
||||||
* will contain the
|
* will contain the
|
||||||
|
|
|
@ -194,32 +194,40 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
|
||||||
COMMAND_HANDLER(handle_flash_erase_address_command)
|
COMMAND_HANDLER(handle_flash_erase_address_command)
|
||||||
{
|
{
|
||||||
struct flash_bank *p;
|
struct flash_bank *p;
|
||||||
int retval;
|
int retval = ERROR_OK;
|
||||||
int address;
|
int address;
|
||||||
int length;
|
int length;
|
||||||
bool do_pad = false;
|
bool do_pad = false;
|
||||||
|
bool do_unlock = false;
|
||||||
struct target *target = get_current_target(CMD_CTX);
|
struct target *target = get_current_target(CMD_CTX);
|
||||||
|
|
||||||
switch (CMD_ARGC) {
|
while (CMD_ARGC >= 3)
|
||||||
case 3:
|
{
|
||||||
/* Optionally pad out the address range to block/sector
|
/* Optionally pad out the address range to block/sector
|
||||||
* boundaries. We can't know if there's data in that part
|
* boundaries. We can't know if there's data in that part
|
||||||
* of the flash; only do padding if we're told to.
|
* of the flash; only do padding if we're told to.
|
||||||
*/
|
*/
|
||||||
if (strcmp("pad", CMD_ARGV[0]) != 0)
|
if (strcmp("pad", CMD_ARGV[0]) == 0)
|
||||||
|
{
|
||||||
|
do_pad = true;
|
||||||
|
} else if (strcmp("unlock", CMD_ARGV[0]) == 0)
|
||||||
|
{
|
||||||
|
do_unlock = true;
|
||||||
|
} else
|
||||||
|
{
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
do_pad = true;
|
}
|
||||||
CMD_ARGC--;
|
CMD_ARGC--;
|
||||||
CMD_ARGV++;
|
CMD_ARGV++;
|
||||||
/* FALL THROUGH */
|
}
|
||||||
case 2:
|
if (CMD_ARGC != 2)
|
||||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
|
{
|
||||||
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
|
||||||
|
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length);
|
||||||
|
|
||||||
if (length <= 0)
|
if (length <= 0)
|
||||||
{
|
{
|
||||||
command_print(CMD_CTX, "Length must be >0");
|
command_print(CMD_CTX, "Length must be >0");
|
||||||
|
@ -238,7 +246,15 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
|
||||||
struct duration bench;
|
struct duration bench;
|
||||||
duration_start(&bench);
|
duration_start(&bench);
|
||||||
|
|
||||||
retval = flash_erase_address_range(target, do_pad, address, length);
|
if (do_unlock)
|
||||||
|
{
|
||||||
|
retval = flash_unlock_address_range(target, address, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == ERROR_OK)
|
||||||
|
{
|
||||||
|
retval = flash_erase_address_range(target, do_pad, address, length);
|
||||||
|
}
|
||||||
|
|
||||||
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
|
||||||
{
|
{
|
||||||
|
@ -709,12 +725,15 @@ static const struct command_registration flash_exec_command_handlers[] = {
|
||||||
.name = "erase_address",
|
.name = "erase_address",
|
||||||
.handler = handle_flash_erase_address_command,
|
.handler = handle_flash_erase_address_command,
|
||||||
.mode = COMMAND_EXEC,
|
.mode = COMMAND_EXEC,
|
||||||
.usage = "['pad'] address length",
|
.usage = "['pad'] ['unlock'] address length",
|
||||||
.help = "Erase flash sectors starting at address and "
|
.help = "Erase flash sectors starting at address and "
|
||||||
"continuing for length bytes. If 'pad' is specified, "
|
"continuing for length bytes. If 'pad' is specified, "
|
||||||
"data outside that range may also be erased: the start "
|
"data outside that range may also be erased: the start "
|
||||||
"address may be decreased, and length increased, so "
|
"address may be decreased, and length increased, so "
|
||||||
"that all of the first and last sectors are erased.",
|
"that all of the first and last sectors are erased. "
|
||||||
|
"If 'unlock' is specified, then the flash is unprotected "
|
||||||
|
"before erasing.",
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = "fillw",
|
.name = "fillw",
|
||||||
|
|
Loading…
Reference in New Issue