NAND: Misleading report of erased blocks
[openocd.git] / src / flash / nand / tcl.c
index 75a416f1986c367ecb24c355c1f50399ba262684..c52c347fd59d7b1df61fa6c6a89967199b6beeec 100644 (file)
 #include "config.h"
 #endif
 
-#include <flash/nand.h>
+#include "core.h"
 #include "imp.h"
 #include "fileio.h"
+#include <target/target.h>
 
 // to be removed
 extern struct nand_device *nand_devices;
@@ -147,18 +148,11 @@ COMMAND_HANDLER(handle_nand_probe_command)
 
        if ((retval = nand_probe(p)) == ERROR_OK)
        {
-               command_print(CMD_CTX, "NAND flash device '%s' found", p->device->name);
-       }
-       else if (retval == ERROR_NAND_OPERATION_FAILED)
-       {
-               command_print(CMD_CTX, "probing failed for NAND flash device");
-       }
-       else
-       {
-               command_print(CMD_CTX, "unknown error when probing NAND flash device");
+               command_print(CMD_CTX, "NAND flash device '%s (%s)' found",
+                               p->device->name, p->manufacturer->name);
        }
 
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_nand_erase_command)
@@ -183,12 +177,12 @@ COMMAND_HANDLER(handle_nand_erase_command)
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
                if ((offset % p->erase_size) != 0 || offset >= size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
                if ((length == 0) || (length % p->erase_size) != 0
                                || (length + offset) > size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                offset /= p->erase_size;
                length /= p->erase_size;
@@ -202,19 +196,11 @@ COMMAND_HANDLER(handle_nand_erase_command)
        {
                command_print(CMD_CTX, "erased blocks %lu to %lu "
                                "on NAND flash device #%s '%s'",
-                               offset, offset + length,
+                               offset, offset + length - 1,
                                CMD_ARGV[0], p->device->name);
        }
-       else if (retval == ERROR_NAND_OPERATION_FAILED)
-       {
-               command_print(CMD_CTX, "erase failed");
-       }
-       else
-       {
-               command_print(CMD_CTX, "unknown error when erasing NAND flash device");
-       }
 
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
@@ -240,12 +226,12 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], offset);
                if (offset % p->erase_size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                offset /= p->erase_size;
 
                COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[2], length);
                if (length % p->erase_size)
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                length -= 1;
                length /= p->erase_size;
@@ -260,18 +246,8 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
                command_print(CMD_CTX, "checked NAND flash device for bad blocks, "
                                "use \"nand info\" command to list blocks");
        }
-       else if (retval == ERROR_NAND_OPERATION_FAILED)
-       {
-               command_print(CMD_CTX, "error when checking for bad blocks on "
-                               "NAND flash device");
-       }
-       else
-       {
-               command_print(CMD_CTX, "unknown error when checking for bad "
-                               "blocks on NAND flash device");
-       }
 
-       return ERROR_OK;
+       return retval;
 }
 
 COMMAND_HANDLER(handle_nand_write_command)
@@ -309,7 +285,7 @@ COMMAND_HANDLER(handle_nand_write_command)
        if (nand_fileio_finish(&s))
        {
                command_print(CMD_CTX, "wrote file %s to NAND flash %s up to "
-                               "offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
+                               "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
                                CMD_ARGV[1], CMD_ARGV[0], s.address, duration_elapsed(&s.bench),
                                duration_kbps(&s.bench, total_bytes));
        }
@@ -336,13 +312,14 @@ COMMAND_HANDLER(handle_nand_verify_command)
 
        while (file.size > 0)
        {
-               int retval = nand_read_page(nand, dev.address / dev.page_size,
+               retval = nand_read_page(nand, dev.address / dev.page_size,
                                dev.page, dev.page_size, dev.oob, dev.oob_size);
                if (ERROR_OK != retval)
                {
                        command_print(CMD_CTX, "reading NAND flash page failed");
                        nand_fileio_cleanup(&dev);
-                       return nand_fileio_cleanup(&file);
+                       nand_fileio_cleanup(&file);
+                       return retval;
                }
 
                int bytes_read = nand_fileio_read(nand, &file);
@@ -350,7 +327,8 @@ COMMAND_HANDLER(handle_nand_verify_command)
                {
                        command_print(CMD_CTX, "error while reading file");
                        nand_fileio_cleanup(&dev);
-                       return nand_fileio_cleanup(&file);
+                       nand_fileio_cleanup(&file);
+                       return ERROR_FAIL;
                }
 
                if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
@@ -359,7 +337,8 @@ COMMAND_HANDLER(handle_nand_verify_command)
                        command_print(CMD_CTX, "NAND flash contents differ "
                                                "at 0x%8.8" PRIx32, dev.address);
                        nand_fileio_cleanup(&dev);
-                       return nand_fileio_cleanup(&file);
+                       nand_fileio_cleanup(&file);
+                       return ERROR_FAIL;
                }
 
                file.size -= bytes_read;
@@ -369,7 +348,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
        if (nand_fileio_finish(&file) == ERROR_OK)
        {
                command_print(CMD_CTX, "verified file %s in NAND flash %s "
-                               "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
+                               "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
                                CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
                                duration_kbps(&file.bench, dev.size));
        }
@@ -379,6 +358,7 @@ COMMAND_HANDLER(handle_nand_verify_command)
 
 COMMAND_HANDLER(handle_nand_dump_command)
 {
+       int filesize;
        struct nand_device *nand = NULL;
        struct nand_fileio_state s;
        int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
@@ -389,12 +369,13 @@ COMMAND_HANDLER(handle_nand_dump_command)
        while (s.size > 0)
        {
                size_t size_written;
-               int retval = nand_read_page(nand, s.address / nand->page_size,
+               retval = nand_read_page(nand, s.address / nand->page_size,
                                s.page, s.page_size, s.oob, s.oob_size);
                if (ERROR_OK != retval)
                {
                        command_print(CMD_CTX, "reading NAND flash page failed");
-                       return nand_fileio_cleanup(&s);
+                       nand_fileio_cleanup(&s);
+                       return retval;
                }
 
                if (NULL != s.page)
@@ -407,11 +388,15 @@ COMMAND_HANDLER(handle_nand_dump_command)
                s.address += nand->page_size;
        }
 
+       retval = fileio_size(&s.fileio, &filesize);
+       if (retval != ERROR_OK)
+               return retval;
+
        if (nand_fileio_finish(&s) == ERROR_OK)
        {
-               command_print(CMD_CTX, "dumped %zu bytes in %fs (%0.3f kb/s)", 
-                               s.fileio.size, duration_elapsed(&s.bench),
-                               duration_kbps(&s.bench, s.fileio.size));
+               command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f KiB/s)",
+                               (long)filesize, duration_elapsed(&s.bench),
+                               duration_kbps(&s.bench, filesize));
        }
        return ERROR_OK;
 }
@@ -446,74 +431,73 @@ COMMAND_HANDLER(handle_nand_raw_access_command)
 static const struct command_registration nand_exec_command_handlers[] = {
        {
                .name = "list",
-               .handler = &handle_nand_list_command,
+               .handler = handle_nand_list_command,
                .mode = COMMAND_EXEC,
                .help = "list configured NAND flash devices",
        },
        {
                .name = "info",
-               .handler = &handle_nand_info_command,
+               .handler = handle_nand_info_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank>",
-               .help = "print info about a NAND flash device",
+               .usage = "[banknum | first_bank_num last_bank_num]",
+               .help = "print info about one or more NAND flash devices",
        },
        {
                .name = "probe",
-               .handler = &handle_nand_probe_command,
+               .handler = handle_nand_probe_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank>",
-               .help = "identify NAND flash device <num>",
-
+               .usage = "bank_id",
+               .help = "identify NAND flash device",
        },
        {
                .name = "check_bad_blocks",
-               .handler = &handle_nand_check_bad_blocks_command,
+               .handler = handle_nand_check_bad_blocks_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> [<offset> <length>]",
-               .help = "check NAND flash device <num> for bad blocks",
+               .usage = "bank_id [offset length]",
+               .help = "check all or part of NAND flash device for bad blocks",
        },
        {
                .name = "erase",
-               .handler = &handle_nand_erase_command,
+               .handler = handle_nand_erase_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> [<offset> <length>]",
-               .help = "erase blocks on NAND flash device",
+               .usage = "bank_id [offset length]",
+               .help = "erase all or subset of blocks on NAND flash device",
        },
        {
                .name = "dump",
-               .handler = &handle_nand_dump_command,
+               .handler = handle_nand_dump_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> <filename> <offset> <length> "
-                       "[oob_raw | oob_only]",
+               .usage = "bank_id filename offset length "
+                       "['oob_raw'|'oob_only']",
                .help = "dump from NAND flash device",
        },
        {
                .name = "verify",
-               .handler = &handle_nand_verify_command,
+               .handler = handle_nand_verify_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> <filename> <offset> "
-                       "[oob_raw | oob_only | oob_softecc | oob_softecc_kw]",
+               .usage = "bank_id filename offset "
+                       "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
                .help = "verify NAND flash device",
        },
        {
                .name = "write",
-               .handler = &handle_nand_write_command,
+               .handler = handle_nand_write_command,
                .mode = COMMAND_EXEC,
-               .usage = "<bank> <filename> <offset> "
-                       "[oob_raw | oob_only | oob_softecc | oob_softecc_kw]",
+               .usage = "bank_id filename offset "
+                       "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
                .help = "write to NAND flash device",
        },
        {
                .name = "raw_access",
-               .handler = &handle_nand_raw_access_command,
+               .handler = handle_nand_raw_access_command,
                .mode = COMMAND_EXEC,
-               .usage = "<num> ['enable'|'disable']",
+               .usage = "bank_id ['enable'|'disable']",
                .help = "raw access to NAND flash device",
        },
        COMMAND_REGISTRATION_DONE
 };
 
-int nand_init(struct command_context *cmd_ctx)
+static int nand_init(struct command_context *cmd_ctx)
 {
        if (!nand_devices)
                return ERROR_OK;
@@ -537,12 +521,14 @@ COMMAND_HANDLER(handle_nand_init_command)
        LOG_DEBUG("Initializing NAND devices...");
        return nand_init(CMD_CTX);
 }
-int nand_list_walker(struct nand_flash_controller *c, void *x)
+
+static int nand_list_walker(struct nand_flash_controller *c, void *x)
 {
        struct command_context *cmd_ctx = (struct command_context *)x;
        command_print(cmd_ctx, "  %s", c->name);
        return ERROR_OK;
 }
+
 COMMAND_HANDLER(handle_nand_list_drivers)
 {
        command_print(CMD_CTX, "Available NAND flash controller drivers:");
@@ -552,16 +538,36 @@ COMMAND_HANDLER(handle_nand_list_drivers)
 static COMMAND_HELPER(create_nand_device, const char *bank_name,
                struct nand_flash_controller *controller)
 {
+       struct nand_device *c;
+       struct target *target;
+       int retval;
+
+       if (CMD_ARGC < 2)
+       {
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+       target = get_target(CMD_ARGV[1]);
+       if (!target) {
+               LOG_ERROR("invalid target %s", CMD_ARGV[1]);
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
        if (NULL != controller->commands)
        {
-               int retval = register_commands(CMD_CTX, NULL,
+               retval = register_commands(CMD_CTX, NULL,
                                controller->commands);
                if (ERROR_OK != retval)
                        return retval;
        }
-       struct nand_device *c = malloc(sizeof(struct nand_device));
+       c = malloc(sizeof(struct nand_device));
+       if (c == NULL)
+       {
+               LOG_ERROR("End of memory");
+               return ERROR_FAIL;
+       }
 
        c->name = strdup(bank_name);
+       c->target = target;
        c->controller = controller;
        c->controller_priv = NULL;
        c->manufacturer = NULL;
@@ -572,23 +578,29 @@ static COMMAND_HELPER(create_nand_device, const char *bank_name,
        c->use_raw = 0;
        c->next = NULL;
 
-       int retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
+       retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
        if (ERROR_OK != retval)
        {
-               LOG_ERROR("'%s' driver rejected nand flash", controller->name);
+               LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
+                       controller->name,
+                       controller->usage);
                free(c);
-               return ERROR_OK;
+               return retval;
        }
 
+       if (controller->usage == NULL)
+               LOG_DEBUG("'%s' driver usage field missing", controller->name);
+
+       nand_device_add(c);
+
        return ERROR_OK;
 }
 
 COMMAND_HANDLER(handle_nand_device_command)
 {
-       if (CMD_ARGC < 1)
+       if (CMD_ARGC < 2)
        {
-               LOG_ERROR("incomplete nand device configuration");
-               return ERROR_FLASH_BANK_INVALID;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        // save name and increment (for compatibility) with drivers
@@ -612,18 +624,21 @@ static const struct command_registration nand_config_command_handlers[] = {
                .handler = &handle_nand_device_command,
                .mode = COMMAND_CONFIG,
                .help = "defines a new NAND bank",
+               .usage = "bank_id driver target [driver_options ...]",
        },
        {
                .name = "drivers",
                .handler = &handle_nand_list_drivers,
                .mode = COMMAND_ANY,
                .help = "lists available NAND drivers",
+               .usage = ""
        },
        {
                .name = "init",
                .mode = COMMAND_CONFIG,
                .handler = &handle_nand_init_command,
                .help = "initialize NAND devices",
+               .usage = ""
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -632,6 +647,7 @@ static const struct command_registration nand_command_handlers[] = {
                .name = "nand",
                .mode = COMMAND_ANY,
                .help = "NAND flash command group",
+               .usage = "",
                .chain = nand_config_command_handlers,
        },
        COMMAND_REGISTRATION_DONE

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)