From: dbrownell Date: Thu, 17 Sep 2009 18:56:17 +0000 (+0000) Subject: Minor fixes to NAND code and docs X-Git-Tag: v0.3.0-rc0~227 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=9536577c0214d6f59e9589fce75f295755fa9f6c;p=openocd 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 --- diff --git a/doc/openocd.texi b/doc/openocd.texi index 9f7314b0..4db8698b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -3898,9 +3898,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 @@ -3950,13 +3958,15 @@ spare areas associated with each data page. @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 @@ -4079,7 +4089,8 @@ This driver handles the NAND controllers found on DaVinci family 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 diff --git a/src/flash/nand.c b/src/flash/nand.c index 84ed0a47..6e450758 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -309,8 +309,9 @@ int nand_init(struct command_context_s *cmd_ctx) "identify NAND flash device "); register_command(cmd_ctx, nand_cmd, "check_bad_blocks", handle_nand_check_bad_blocks_command, COMMAND_EXEC, "check NAND flash device for bad blocks [ ]"); - register_command(cmd_ctx, nand_cmd, "erase", handle_nand_erase_command, COMMAND_EXEC, - "erase blocks on NAND flash device "); + register_command(cmd_ctx, nand_cmd, "erase", + handle_nand_erase_command, COMMAND_EXEC, + "erase blocks on NAND flash device [ ]"); register_command(cmd_ctx, nand_cmd, "dump", handle_nand_dump_command, COMMAND_EXEC, "dump from NAND flash device " " [oob_raw | oob_only]"); @@ -637,7 +638,7 @@ int nand_probe(struct nand_device_s *device) 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 *device, int first_block, int last_block) 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 command_context_s *cmd_ctx, char *cmd, char 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(struct command_context_s *cmd_ctx, char *cm 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(struct command_context_s *cmd_ctx, char *cm 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; - - length = strtoul(args[2], &cp, 0); - if (*cp || length == ULONG_MAX || length % p->erase_size) - { - return ERROR_INVALID_ARGUMENTS; + /* erase specified part of the chip; or else everything */ + if (argc == 3) { + unsigned long size = p->erase_size * p->num_blocks; + + 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) {