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__
parent
da4cb3c029
commit
555757175e
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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> "
|
||||||
|
|
Loading…
Reference in New Issue