Minor fixes to NAND code and docs
Erase logic: - command invocation + treat "nand erase N" (no offset/length) as "erase whole chip N" + catch a few more bogus parameter cases, like length == 0 (sigh) - nand_erase() should be static - on error + say which block failed, and if it was a bad block + don't give up after the first error; try to erase the rest - on success, say which nand device was erased (name isn't unique) Device list ("nand list"): - say how many blocks there are - split summary into two lines - give example in the docs Doc tweaks: - Use @option{...} for DaVinci's supported hardware ECC options For the record, I've observed that _sometimes_ erasing bad blocks causes failure reports, and that manufacturer bad block markers aren't always erasable (even when erasing their blocks doesn't trigger an error report). git-svn-id: svn://svn.berlios.de/openocd/trunk@2724 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
parent
9655c5b093
commit
9536577c02
|
@ -3898,9 +3898,17 @@ for more information.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {nand list}
|
@deffn Command {nand list}
|
||||||
Prints a one-line summary of each device declared
|
Prints a summary of each device declared
|
||||||
using @command{nand device}, numbered from zero.
|
using @command{nand device}, numbered from zero.
|
||||||
Note that un-probed devices show no details.
|
Note that un-probed devices show no details.
|
||||||
|
@example
|
||||||
|
> nand list
|
||||||
|
#0: NAND 1GiB 3,3V 8-bit (Micron) pagesize: 2048, buswidth: 8,
|
||||||
|
blocksize: 131072, blocks: 8192
|
||||||
|
#1: NAND 1GiB 3,3V 8-bit (Micron) pagesize: 2048, buswidth: 8,
|
||||||
|
blocksize: 131072, blocks: 8192
|
||||||
|
>
|
||||||
|
@end example
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {nand probe} num
|
@deffn Command {nand probe} num
|
||||||
|
@ -3950,13 +3958,15 @@ spare areas associated with each data page.
|
||||||
@end itemize
|
@end itemize
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn Command {nand erase} num offset length
|
@deffn Command {nand erase} num [offset length]
|
||||||
@cindex NAND erasing
|
@cindex NAND erasing
|
||||||
@cindex NAND programming
|
@cindex NAND programming
|
||||||
Erases blocks on the specified NAND device, starting at the
|
Erases blocks on the specified NAND device, starting at the
|
||||||
specified @var{offset} and continuing for @var{length} bytes.
|
specified @var{offset} and continuing for @var{length} bytes.
|
||||||
Both of those values must be exact multiples of the device's
|
Both of those values must be exact multiples of the device's
|
||||||
block size, and the region they specify must fit entirely in the chip.
|
block size, and the region they specify must fit entirely in the chip.
|
||||||
|
If those parameters are not specified,
|
||||||
|
the whole NAND chip will be erased.
|
||||||
The @var{num} parameter is the value shown by @command{nand list}.
|
The @var{num} parameter is the value shown by @command{nand list}.
|
||||||
|
|
||||||
@b{NOTE:} This command will try to erase bad blocks, when told
|
@b{NOTE:} This command will try to erase bad blocks, when told
|
||||||
|
@ -4079,7 +4089,8 @@ This driver handles the NAND controllers found on DaVinci family
|
||||||
chips from Texas Instruments.
|
chips from Texas Instruments.
|
||||||
It takes three extra parameters:
|
It takes three extra parameters:
|
||||||
address of the NAND chip;
|
address of the NAND chip;
|
||||||
hardware ECC mode to use (hwecc1, hwecc4, hwecc4_infix);
|
hardware ECC mode to use (@option{hwecc1},
|
||||||
|
@option{hwecc4}, @option{hwecc4_infix});
|
||||||
address of the AEMIF controller on this processor.
|
address of the AEMIF controller on this processor.
|
||||||
@example
|
@example
|
||||||
nand device davinci dm355.arm 0x02000000 hwecc4 0x01e10000
|
nand device davinci dm355.arm 0x02000000 hwecc4 0x01e10000
|
||||||
|
|
|
@ -309,8 +309,9 @@ int nand_init(struct command_context_s *cmd_ctx)
|
||||||
"identify NAND flash device <num>");
|
"identify NAND flash device <num>");
|
||||||
register_command(cmd_ctx, nand_cmd, "check_bad_blocks", handle_nand_check_bad_blocks_command, COMMAND_EXEC,
|
register_command(cmd_ctx, nand_cmd, "check_bad_blocks", handle_nand_check_bad_blocks_command, COMMAND_EXEC,
|
||||||
"check NAND flash device <num> for bad blocks [<offset> <length>]");
|
"check NAND flash device <num> for bad blocks [<offset> <length>]");
|
||||||
register_command(cmd_ctx, nand_cmd, "erase", handle_nand_erase_command, COMMAND_EXEC,
|
register_command(cmd_ctx, nand_cmd, "erase",
|
||||||
"erase blocks on NAND flash device <num> <offset> <length>");
|
handle_nand_erase_command, COMMAND_EXEC,
|
||||||
|
"erase blocks on NAND flash device <num> [<offset> <length>]");
|
||||||
register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC,
|
register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC,
|
||||||
"dump from NAND flash device <num> <filename> "
|
"dump from NAND flash device <num> <filename> "
|
||||||
"<offset> <length> [oob_raw | oob_only]");
|
"<offset> <length> [oob_raw | oob_only]");
|
||||||
|
@ -637,7 +638,7 @@ int nand_probe(struct nand_device_s *device)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nand_erase(struct nand_device_s *device, int first_block, int last_block)
|
static int nand_erase(struct nand_device_s *device, int first_block, int last_block)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32_t page;
|
uint32_t page;
|
||||||
|
@ -712,8 +713,11 @@ int nand_erase(struct nand_device_s *device, int first_block, int last_block)
|
||||||
|
|
||||||
if (status & 0x1)
|
if (status & 0x1)
|
||||||
{
|
{
|
||||||
LOG_ERROR("erase operation didn't pass, status: 0x%2.2x", status);
|
LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
|
||||||
return ERROR_NAND_OPERATION_FAILED;
|
(device->blocks[i].is_bad == 1)
|
||||||
|
? "bad " : "",
|
||||||
|
i, status);
|
||||||
|
/* continue; other blocks might still be erasable */
|
||||||
}
|
}
|
||||||
|
|
||||||
device->blocks[i].is_erased = 1;
|
device->blocks[i].is_erased = 1;
|
||||||
|
@ -1075,8 +1079,12 @@ int handle_nand_list_command(struct command_context_s *cmd_ctx, char *cmd, char
|
||||||
for (p = nand_devices, i = 0; p; p = p->next, i++)
|
for (p = nand_devices, i = 0; p; p = p->next, i++)
|
||||||
{
|
{
|
||||||
if (p->device)
|
if (p->device)
|
||||||
command_print(cmd_ctx, "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
|
command_print(cmd_ctx, "#%i: %s (%s) "
|
||||||
i, p->device->name, p->manufacturer->name, p->page_size, p->bus_width, p->erase_size);
|
"pagesize: %i, buswidth: %i,\n\t"
|
||||||
|
"blocksize: %i, blocks: %i",
|
||||||
|
i, p->device->name, p->manufacturer->name,
|
||||||
|
p->page_size, p->bus_width,
|
||||||
|
p->erase_size, p->num_blocks);
|
||||||
else
|
else
|
||||||
command_print(cmd_ctx, "#%i: not probed", i);
|
command_print(cmd_ctx, "#%i: not probed", i);
|
||||||
}
|
}
|
||||||
|
@ -1197,7 +1205,7 @@ static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cm
|
||||||
nand_device_t *p;
|
nand_device_t *p;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
if (argc != 3)
|
if (argc != 1 && argc != 3)
|
||||||
{
|
{
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
|
@ -1210,27 +1218,37 @@ static int handle_nand_erase_command(struct command_context_s *cmd_ctx, char *cm
|
||||||
unsigned long offset;
|
unsigned long offset;
|
||||||
unsigned long length;
|
unsigned long length;
|
||||||
|
|
||||||
offset = strtoul(args[1], &cp, 0);
|
/* erase specified part of the chip; or else everything */
|
||||||
if (*cp || offset == ULONG_MAX || offset % p->erase_size)
|
if (argc == 3) {
|
||||||
{
|
unsigned long size = p->erase_size * p->num_blocks;
|
||||||
return ERROR_INVALID_ARGUMENTS;
|
|
||||||
}
|
|
||||||
offset /= p->erase_size;
|
|
||||||
|
|
||||||
length = strtoul(args[2], &cp, 0);
|
offset = strtoul(args[1], &cp, 0);
|
||||||
if (*cp || length == ULONG_MAX || length % p->erase_size)
|
if (*cp || (offset == ULONG_MAX)
|
||||||
{
|
|| (offset % p->erase_size) != 0
|
||||||
return ERROR_INVALID_ARGUMENTS;
|
|| offset >= size)
|
||||||
}
|
return ERROR_INVALID_ARGUMENTS;
|
||||||
length -= 1;
|
|
||||||
length /= p->erase_size;
|
|
||||||
|
|
||||||
retval = nand_erase(p, offset, offset + length);
|
length = strtoul(args[2], &cp, 0);
|
||||||
|
if (*cp || (length == ULONG_MAX)
|
||||||
|
|| (length == 0)
|
||||||
|
|| (length % p->erase_size) != 0
|
||||||
|
|| (length + offset) > size)
|
||||||
|
return ERROR_INVALID_ARGUMENTS;
|
||||||
|
|
||||||
|
offset /= p->erase_size;
|
||||||
|
length /= p->erase_size;
|
||||||
|
} else {
|
||||||
|
offset = 0;
|
||||||
|
length = p->num_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = nand_erase(p, offset, offset + length - 1);
|
||||||
if (retval == ERROR_OK)
|
if (retval == ERROR_OK)
|
||||||
{
|
{
|
||||||
command_print(cmd_ctx, "successfully erased blocks "
|
command_print(cmd_ctx, "erased blocks %lu to %lu "
|
||||||
"%lu to %lu on NAND flash device '%s'",
|
"on NAND flash device #%s '%s'",
|
||||||
offset, offset + length, p->device->name);
|
offset, offset + length,
|
||||||
|
args[0], p->device->name);
|
||||||
}
|
}
|
||||||
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
else if (retval == ERROR_NAND_OPERATION_FAILED)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue