From 9536577c0214d6f59e9589fce75f295755fa9f6c Mon Sep 17 00:00:00 2001 From: dbrownell Date: Thu, 17 Sep 2009 18:56:17 +0000 Subject: 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 --- src/flash/nand.c | 68 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 25 deletions(-) (limited to 'src/flash') 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) { -- cgit v1.2.3