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).
---
Comments anyone?
doc/openocd.texi | 17 +++++++++++--
src/flash/nand.c | 66 +++++++++++++++++++++++++++++++++--------------------
2 files changed, 56 insertions(+), 27 deletions(-)
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -3894,9 +3894,17 @@ for more information.
@end deffn
@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.
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
@deffn Command {nand probe} num
@@ -3946,13 +3954,15 @@ spare areas associated with each data pa
@end itemize
@end deffn
-...@deffn Command {nand erase} num offset length
+...@deffn Command {nand erase} num [offset length]
@cindex NAND erasing
@cindex NAND programming
Erases blocks on the specified NAND device, starting at the
specified @var{offset} and continuing for @var{length} bytes.
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.
+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}.
@b{NOTE:} This command will try to erase bad blocks, when told
@@ -4075,7 +4085,8 @@ This driver handles the NAND controllers
chips from Texas Instruments.
It takes three extra parameters:
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.
@example
nand device davinci dm355.arm 0x02000000 hwecc4 0x01e10000
--- a/src/flash/nand.c
+++ b/src/flash/nand.c
@@ -309,8 +309,9 @@ int nand_init(struct command_context_s *
"identify NAND flash device
<num>");
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>]");
- register_command(cmd_ctx, nand_cmd, "erase",
handle_nand_erase_command, COMMAND_EXEC,
- "erase blocks on NAND flash
device <num> <offset> <length>");
+ register_command(cmd_ctx, nand_cmd, "erase",
+ 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,
"dump from NAND flash device
<num> <filename> "
"<offset> <length> [oob_raw |
oob_only]");
@@ -637,7 +638,7 @@ int nand_probe(struct nand_device_s *dev
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;
uint32_t page;
@@ -712,8 +713,11 @@ int nand_erase(struct nand_device_s *dev
if (status & 0x1)
{
- LOG_ERROR("erase operation didn't pass, status:
0x%2.2x", status);
- return ERROR_NAND_OPERATION_FAILED;
+ LOG_ERROR("didn't erase %sblock %d; status: 0x%2.2x",
+ (device->blocks[i].is_bad == 1)
+ ? "bad " : "",
+ i, status);
+ /* continue; other blocks might still be erasable */
}
device->blocks[i].is_erased = 1;
@@ -1075,8 +1079,12 @@ int handle_nand_list_command(struct comm
for (p = nand_devices, i = 0; p; p = p->next, i++)
{
if (p->device)
- command_print(cmd_ctx, "#%i: %s (%s) pagesize: %i,
buswidth: %i, erasesize: %i",
- i, p->device->name, p->manufacturer->name,
p->page_size, p->bus_width, p->erase_size);
+ command_print(cmd_ctx, "#%i: %s (%s) "
+ "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
command_print(cmd_ctx, "#%i: not probed", i);
}
@@ -1197,7 +1205,7 @@ static int handle_nand_erase_command(str
nand_device_t *p;
int retval;
- if (argc != 3)
+ if (argc != 1 && argc != 3)
{
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1210,27 +1218,37 @@ static int handle_nand_erase_command(str
unsigned long offset;
unsigned long length;
- offset = strtoul(args[1], &cp, 0);
- if (*cp || offset == ULONG_MAX || offset % p->erase_size)
- {
- return ERROR_INVALID_ARGUMENTS;
- }
- offset /= p->erase_size;
+ /* erase specified part of the chip; or else everything */
+ if (argc == 3) {
+ unsigned long size = p->erase_size * p->num_blocks;
- length = strtoul(args[2], &cp, 0);
- if (*cp || length == ULONG_MAX || length % p->erase_size)
- {
- return ERROR_INVALID_ARGUMENTS;
+ offset = strtoul(args[1], &cp, 0);
+ if (*cp || (offset == ULONG_MAX)
+ || (offset % p->erase_size) != 0
+ || offset >= size)
+ return ERROR_INVALID_ARGUMENTS;
+
+ 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;
}
- length -= 1;
- length /= p->erase_size;
- retval = nand_erase(p, offset, offset + length);
+ retval = nand_erase(p, offset, offset + length - 1);
if (retval == ERROR_OK)
{
- command_print(cmd_ctx, "successfully erased blocks "
- "%lu to %lu on NAND flash device '%s'",
- offset, offset + length,
p->device->name);
+ command_print(cmd_ctx, "erased blocks %lu to %lu "
+ "on NAND flash device #%s '%s'",
+ offset, offset + length,
+ args[0], p->device->name);
}
else if (retval == ERROR_NAND_OPERATION_FAILED)
{
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development