Add 'nand verify' command

Add the 'nand verify' command to perform a dump and fake-write
simultaneously, checking the read bits against those generated by the
write process.  Appropriate user documentation for this command has
been added to the user guide as well.

The algorithm presently makes a relatively naive comparison.  Some chips
that use ECC may not verify correctly using this implementation, but the
new documentation provides details about this limitation.
__archive__
Zachary T Welch 2009-11-07 21:20:45 -08:00
parent da4cb3c029
commit 555757175e
2 changed files with 91 additions and 0 deletions

View File

@ -4620,6 +4620,32 @@ the underlying driver from applying hardware ECC.
@end itemize @end itemize
@end deffn @end deffn
@deffn Command {nand verify} num filename offset [option...]
@cindex NAND verification
@cindex NAND programming
Verify the binary data in the file has been programmed to the
specified NAND device, starting at the specified offset.
The @var{num} parameter is the value shown by @command{nand list}.
Use a complete path name for @var{filename}, so you don't depend
on the directory used to start the OpenOCD server.
The @var{offset} must be an exact multiple of the device's page size.
All data in the file will be read and compared to the contents of the
flash, assuming it doesn't run past the end of the device.
As with @command{nand write}, only full pages are verified, so any extra
space in the last page will be filled with 0xff bytes.
The same @var{options} accepted by @command{nand write},
and the file will be processed similarly to produce the buffers that
can be compared against the contents produced from @command{nand dump}.
@b{NOTE:} This will not work when the underlying NAND controller
driver's @code{write_page} routine must update the OOB with a
hardward-computed ECC before the data is written. This limitation may
be removed in a future release.
@end deffn
@section Other NAND commands @section Other NAND commands
@cindex NAND other commands @cindex NAND other commands

View File

@ -1543,6 +1543,67 @@ COMMAND_HANDLER(handle_nand_write_command)
return ERROR_OK; return ERROR_OK;
} }
COMMAND_HANDLER(handle_nand_verify_command)
{
struct nand_device *nand = NULL;
struct nand_fileio_state file;
int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
&file, &nand, FILEIO_READ, false, true);
if (ERROR_OK != retval)
return retval;
struct nand_fileio_state dev;
nand_fileio_init(&dev);
dev.address = file.address;
dev.size = file.size;
dev.oob_format = file.oob_format;
retval = nand_fileio_start(cmd_ctx, nand, NULL, FILEIO_NONE, &dev);
if (ERROR_OK != retval)
return retval;
while (file.size > 0)
{
int 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);
}
int bytes_read = nand_fileio_read(nand, &file);
if (bytes_read <= 0)
{
command_print(cmd_ctx, "error while reading file");
nand_fileio_cleanup(&dev);
return nand_fileio_cleanup(&file);
}
if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
(dev.oob && memcmp(dev.oob, file.oob, dev.oob_size)) )
{
command_print(cmd_ctx, "NAND flash contents differ "
"at 0x%8.8" PRIx32, dev.address);
nand_fileio_cleanup(&dev);
return nand_fileio_cleanup(&file);
}
file.size -= bytes_read;
file.address += nand->page_size;
}
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)",
args[1], args[0], dev.address, duration_elapsed(&file.bench),
duration_kbps(&file.bench, dev.size));
}
return nand_fileio_cleanup(&dev);
}
COMMAND_HANDLER(handle_nand_dump_command) COMMAND_HANDLER(handle_nand_dump_command)
{ {
struct nand_device *nand = NULL; struct nand_device *nand = NULL;
@ -1641,6 +1702,10 @@ int nand_init(struct command_context *cmd_ctx)
handle_nand_dump_command, COMMAND_EXEC, 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]");
register_command(cmd_ctx, nand_cmd, "verify",
&handle_nand_verify_command, COMMAND_EXEC,
"verify NAND flash device <num> <filename> <offset> "
"[oob_raw | oob_only | oob_softecc | oob_softecc_kw]");
register_command(cmd_ctx, nand_cmd, "write", register_command(cmd_ctx, nand_cmd, "write",
handle_nand_write_command, COMMAND_EXEC, handle_nand_write_command, COMMAND_EXEC,
"write to NAND flash device <num> <filename> <offset> " "write to NAND flash device <num> <filename> <offset> "