From: Zach W. <zw...@us...> - 2009-11-16 13:09:57
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 555757175eb344d11f3c0123f2f83460ef6ca67b (commit) via da4cb3c029e7f271ee4fa7165ceefbef04d45e49 (commit) via 51cd370b396d19555158c1eb913e7c8386d92a0f (commit) via 23cc85b307de80be089dcb0048dbb6168e59651a (commit) from 45527ee82c9e7c93b29b79f01f52d663960649c2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 555757175eb344d11f3c0123f2f83460ef6ca67b Author: Zachary T Welch <zw...@su...> Date: Sat Nov 7 21:20:45 2009 -0800 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. diff --git a/doc/openocd.texi b/doc/openocd.texi index bb96a2e..81409ac 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4620,6 +4620,32 @@ the underlying driver from applying hardware ECC. @end itemize @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 @cindex NAND other commands diff --git a/src/flash/nand.c b/src/flash/nand.c index da561f6..46ac728 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -1543,6 +1543,67 @@ COMMAND_HANDLER(handle_nand_write_command) 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) { struct nand_device *nand = NULL; @@ -1641,6 +1702,10 @@ int nand_init(struct command_context *cmd_ctx) handle_nand_dump_command, COMMAND_EXEC, "dump from NAND flash device <num> <filename> " "<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", handle_nand_write_command, COMMAND_EXEC, "write to NAND flash device <num> <filename> <offset> " commit da4cb3c029e7f271ee4fa7165ceefbef04d45e49 Author: Zachary T Welch <zw...@su...> Date: Sat Nov 7 22:37:39 2009 -0800 Add FILEIO_NONE access mode. In some cases, the FILEIO_NONE access mode may be useful as a parameter to indicate that file access should be disabled. High-level routines can use it to skip file access calls, as 'fileio_open' will fail presently if called to open a file using this mode. diff --git a/src/helper/fileio.h b/src/helper/fileio.h index 024ad08..8cba926 100644 --- a/src/helper/fileio.h +++ b/src/helper/fileio.h @@ -38,6 +38,7 @@ enum fileio_type enum fileio_access { + FILEIO_NONE, /* open without any access (invalid mode) */ FILEIO_READ, /* open for reading, position at beginning */ FILEIO_WRITE, /* open for writing, position at beginning */ FILEIO_READWRITE, /* open for writing, position at beginning, allow reading */ commit 51cd370b396d19555158c1eb913e7c8386d92a0f Author: Zachary T Welch <zw...@su...> Date: Thu Nov 5 19:45:24 2009 -0800 Use nand_fileio_* in write/dump commands. This patch eliminates duplicated code in the the NAND 'dump' and 'write' by using the new static helper functions. These changes also fix a possible memory leak in nand dump command, in the case that the dump file failed to open. Overall, the changes should be functionally equivalent, but the resulting code will be easier to improve and extend further. diff --git a/src/flash/nand.c b/src/flash/nand.c index 9cc0802..da561f6 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -1375,13 +1375,13 @@ static int nand_fileio_cleanup(struct nand_fileio_state *state) } return ERROR_OK; } -int nand_fileio_finish(struct nand_fileio_state *state) +static int nand_fileio_finish(struct nand_fileio_state *state) { nand_fileio_cleanup(state); return duration_measure(&state->bench); } -COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, +static COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, struct nand_device **dev, enum fileio_access filemode, bool need_size, bool sw_ecc) { @@ -1449,7 +1449,7 @@ COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, * @returns If no error occurred, returns number of bytes consumed; * otherwise, returns a negative error code.) */ -int nand_fileio_read(struct nand_device *nand, +static int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s) { uint32_t total_read = 0; @@ -1503,284 +1503,82 @@ int nand_fileio_read(struct nand_device *nand, COMMAND_HANDLER(handle_nand_write_command) { - uint32_t offset; - uint32_t binary_size; - uint32_t buf_cnt; - enum oob_formats oob_format = NAND_OOB_NONE; - - struct fileio fileio; - - - if (argc < 3) - { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - struct nand_device *p; - int retval = nand_command_get_device_by_num(cmd_ctx, args[0], &p); + struct nand_device *nand = NULL; + struct nand_fileio_state s; + int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args, + &s, &nand, FILEIO_READ, false, true); if (ERROR_OK != retval) return retval; - uint8_t *page = NULL; - uint32_t page_size = 0; - uint8_t *oob = NULL; - uint32_t oob_size = 0; - const int *eccpos = NULL; - - COMMAND_PARSE_NUMBER(u32, args[2], offset); - - if (argc > 3) - { - for (unsigned i = 3; i < argc; i++) - { - if (!strcmp(args[i], "oob_raw")) - oob_format |= NAND_OOB_RAW; - else if (!strcmp(args[i], "oob_only")) - oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; - else if (!strcmp(args[i], "oob_softecc")) - oob_format |= NAND_OOB_SW_ECC; - else if (!strcmp(args[i], "oob_softecc_kw")) - oob_format |= NAND_OOB_SW_ECC_KW; - else - { - command_print(cmd_ctx, "unknown option: %s", args[i]); - return ERROR_COMMAND_SYNTAX_ERROR; - } - } - } - - struct duration bench; - duration_start(&bench); - - if (fileio_open(&fileio, args[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) - { - return ERROR_OK; - } - - buf_cnt = binary_size = fileio.size; - - if (!(oob_format & NAND_OOB_ONLY)) - { - page_size = p->page_size; - page = malloc(p->page_size); - } - - if (oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) - { - if (p->page_size == 512) { - oob_size = 16; - eccpos = nand_oob_16.eccpos; - } else if (p->page_size == 2048) { - oob_size = 64; - eccpos = nand_oob_64.eccpos; - } - oob = malloc(oob_size); - } - - if (offset % p->page_size) - { - command_print(cmd_ctx, "only page size aligned offsets and sizes are supported"); - fileio_close(&fileio); - free(oob); - free(page); - return ERROR_OK; - } - - while (buf_cnt > 0) + uint32_t total_bytes = s.size; + while (s.size > 0) { - uint32_t size_read; - - if (NULL != page) + int bytes_read = nand_fileio_read(nand, &s); + if (bytes_read <= 0) { - fileio_read(&fileio, page_size, page, &size_read); - buf_cnt -= size_read; - if (size_read < page_size) - { - memset(page + size_read, 0xff, page_size - size_read); - } + command_print(cmd_ctx, "error while reading file"); + return nand_fileio_cleanup(&s); } + s.size -= bytes_read; - if (oob_format & NAND_OOB_SW_ECC) - { - uint32_t i, j; - uint8_t ecc[3]; - memset(oob, 0xff, oob_size); - for (i = 0, j = 0; i < page_size; i += 256) { - nand_calculate_ecc(p, page + i, ecc); - oob[eccpos[j++]] = ecc[0]; - oob[eccpos[j++]] = ecc[1]; - oob[eccpos[j++]] = ecc[2]; - } - } else if (oob_format & NAND_OOB_SW_ECC_KW) - { - /* - * In this case eccpos is not used as - * the ECC data is always stored contigously - * at the end of the OOB area. It consists - * of 10 bytes per 512-byte data block. - */ - uint32_t i; - uint8_t *ecc = oob + oob_size - page_size/512 * 10; - memset(oob, 0xff, oob_size); - for (i = 0; i < page_size; i += 512) { - nand_calculate_ecc_kw(p, page + i, ecc); - ecc += 10; - } - } - else if (NULL != oob) + retval = nand_write_page(nand, s.address / nand->page_size, + s.page, s.page_size, s.oob, s.oob_size); + if (ERROR_OK != retval) { - fileio_read(&fileio, oob_size, oob, &size_read); - buf_cnt -= size_read; - if (size_read < oob_size) - { - memset(oob + size_read, 0xff, oob_size - size_read); - } + command_print(cmd_ctx, "failed writing file %s " + "to NAND flash %s at offset 0x%8.8" PRIx32, + args[1], args[0], s.address); + return nand_fileio_cleanup(&s); } - - if (nand_write_page(p, offset / p->page_size, page, page_size, oob, oob_size) != ERROR_OK) - { - command_print(cmd_ctx, "failed writing file %s to NAND flash %s at offset 0x%8.8" PRIx32 "", - args[1], args[0], offset); - - fileio_close(&fileio); - free(oob); - free(page); - - return ERROR_OK; - } - offset += page_size; + s.address += s.page_size; } - fileio_close(&fileio); - free(oob); - free(page); - oob = NULL; - page = NULL; - if (duration_measure(&bench) == ERROR_OK) + 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)", - args[1], args[0], offset, duration_elapsed(&bench), - duration_kbps(&bench, fileio.size)); + command_print(cmd_ctx, "wrote file %s to NAND flash %s up to " + "offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)", + args[1], args[0], s.address, duration_elapsed(&s.bench), + duration_kbps(&s.bench, total_bytes)); } - return ERROR_OK; } COMMAND_HANDLER(handle_nand_dump_command) { - if (argc < 4) - { - return ERROR_COMMAND_SYNTAX_ERROR; - } - - struct nand_device *p; - int retval = nand_command_get_device_by_num(cmd_ctx, args[0], &p); + struct nand_device *nand = NULL; + struct nand_fileio_state s; + int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args, + &s, &nand, FILEIO_WRITE, true, false); if (ERROR_OK != retval) return retval; - if (NULL == p->device) - { - command_print(cmd_ctx, "#%s: not probed", args[0]); - return ERROR_OK; - } - - struct fileio fileio; - - uint8_t *page = NULL; - uint32_t page_size = 0; - uint8_t *oob = NULL; - uint32_t oob_size = 0; - uint32_t address; - COMMAND_PARSE_NUMBER(u32, args[2], address); - uint32_t size; - COMMAND_PARSE_NUMBER(u32, args[3], size); - uint32_t bytes_done = 0; - enum oob_formats oob_format = NAND_OOB_NONE; - - if (argc > 4) - { - for (unsigned i = 4; i < argc; i++) - { - if (!strcmp(args[i], "oob_raw")) - oob_format |= NAND_OOB_RAW; - else if (!strcmp(args[i], "oob_only")) - oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; - else - command_print(cmd_ctx, "unknown option: '%s'", args[i]); - } - } - - if ((address % p->page_size) || (size % p->page_size)) - { - command_print(cmd_ctx, "only page size aligned addresses and sizes are supported"); - return ERROR_OK; - } - - if (!(oob_format & NAND_OOB_ONLY)) - { - page_size = p->page_size; - page = malloc(p->page_size); - } - - if (oob_format & NAND_OOB_RAW) - { - if (p->page_size == 512) - oob_size = 16; - else if (p->page_size == 2048) - oob_size = 64; - oob = malloc(oob_size); - } - - if (fileio_open(&fileio, args[1], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK) - { - return ERROR_OK; - } - - struct duration bench; - duration_start(&bench); - - while (size > 0) + while (s.size > 0) { uint32_t size_written; - if ((retval = nand_read_page(p, address / p->page_size, page, page_size, oob, oob_size)) != ERROR_OK) + int 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"); - free(page); - free(oob); - fileio_close(&fileio); - return ERROR_OK; + return nand_fileio_cleanup(&s); } - if (NULL != page) - { - fileio_write(&fileio, page_size, page, &size_written); - bytes_done += page_size; - } + if (NULL != s.page) + fileio_write(&s.fileio, s.page_size, s.page, &size_written); - if (NULL != oob) - { - fileio_write(&fileio, oob_size, oob, &size_written); - bytes_done += oob_size; - } + if (NULL != s.oob) + fileio_write(&s.fileio, s.oob_size, s.oob, &size_written); - size -= p->page_size; - address += p->page_size; + s.size -= nand->page_size; + s.address += nand->page_size; } - free(page); - page = NULL; - free(oob); - oob = NULL; - fileio_close(&fileio); - - if (duration_measure(&bench) == ERROR_OK) + if (nand_fileio_finish(&s) == ERROR_OK) { - command_print(cmd_ctx, "dumped %lld byte in %fs (%0.3f kb/s)", - fileio.size, duration_elapsed(&bench), - duration_kbps(&bench, fileio.size)); + command_print(cmd_ctx, "dumped %lld byte in %fs (%0.3f kb/s)", + s.fileio.size, duration_elapsed(&s.bench), + duration_kbps(&s.bench, s.fileio.size)); } - return ERROR_OK; } commit 23cc85b307de80be089dcb0048dbb6168e59651a Author: Zachary T Welch <zw...@su...> Date: Sun Nov 8 02:06:34 2009 -0800 Add nand_fileio_* helper APIs. This patch provides helpers APIs that will eliminate duplicated code in the the NAND 'dump' and 'write' commands by factoring their common code into static helper functions. These helpers may be useful for creating new commands, as shown in the final patch to 'verify' flash from a file. Several previously unreported error conditions now generate messages and propogate the return codes, such as when the file fails to open and bad arguments are given. These changes will fix a possible memory leak in nand dump command, in the case that the dump file failed to open. Overall, the changes should be functionally equivalent, but the resulting code will be easier to improve and extend consistently. diff --git a/src/flash/nand.c b/src/flash/nand.c index be3a669..9cc0802 100644 --- a/src/flash/nand.c +++ b/src/flash/nand.c @@ -1285,6 +1285,222 @@ COMMAND_HANDLER(handle_nand_check_bad_blocks_command) return ERROR_OK; } +struct nand_fileio_state { + uint32_t address; + uint32_t size; + + uint8_t *page; + uint32_t page_size; + + enum oob_formats oob_format; + uint8_t *oob; + uint32_t oob_size; + + const int *eccpos; + + bool file_opened; + struct fileio fileio; + + struct duration bench; +}; + +static void nand_fileio_init(struct nand_fileio_state *state) +{ + memset(state, 0, sizeof(*state)); + state->oob_format = NAND_OOB_NONE; +} + +static int nand_fileio_start(struct command_context *cmd_ctx, + struct nand_device *nand, const char *filename, int filemode, + struct nand_fileio_state *state) +{ + if (state->address % nand->page_size) + { + command_print(cmd_ctx, "only page-aligned addresses are supported"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + duration_start(&state->bench); + + if (NULL != filename) + { + int retval = fileio_open(&state->fileio, filename, filemode, FILEIO_BINARY); + if (ERROR_OK != retval) + { + const char *msg = (FILEIO_READ == filemode) ? "read" : "write"; + command_print(cmd_ctx, "failed to open '%s' for %s access", + filename, msg); + return retval; + } + state->file_opened = true; + } + + if (!(state->oob_format & NAND_OOB_ONLY)) + { + state->page_size = nand->page_size; + state->page = malloc(nand->page_size); + } + + if (state->oob_format & (NAND_OOB_RAW | NAND_OOB_SW_ECC | NAND_OOB_SW_ECC_KW)) + { + if (nand->page_size == 512) + { + state->oob_size = 16; + state->eccpos = nand_oob_16.eccpos; + } + else if (nand->page_size == 2048) + { + state->oob_size = 64; + state->eccpos = nand_oob_64.eccpos; + } + state->oob = malloc(state->oob_size); + } + + return ERROR_OK; +} +static int nand_fileio_cleanup(struct nand_fileio_state *state) +{ + if (state->file_opened) + fileio_close(&state->fileio); + + if (state->oob) + { + free(state->oob); + state->oob = NULL; + } + if (state->page) + { + free(state->page); + state->page = NULL; + } + return ERROR_OK; +} +int nand_fileio_finish(struct nand_fileio_state *state) +{ + nand_fileio_cleanup(state); + return duration_measure(&state->bench); +} + +COMMAND_HELPER(nand_fileio_parse_args, struct nand_fileio_state *state, + struct nand_device **dev, enum fileio_access filemode, + bool need_size, bool sw_ecc) +{ + nand_fileio_init(state); + + unsigned minargs = need_size ? 4 : 3; + if (argc < minargs) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct nand_device *nand; + int retval = nand_command_get_device_by_num(cmd_ctx, args[0], &nand); + if (ERROR_OK != retval) + return retval; + + if (NULL == nand->device) + { + command_print(cmd_ctx, "#%s: not probed", args[0]); + return ERROR_OK; + } + + COMMAND_PARSE_NUMBER(u32, args[2], state->address); + if (need_size) + { + COMMAND_PARSE_NUMBER(u32, args[2], state->size); + if (state->size % nand->page_size) + { + command_print(cmd_ctx, "only page-aligned sizes are supported"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } + + if (argc > minargs) + { + for (unsigned i = minargs; i < argc; i++) + { + if (!strcmp(args[i], "oob_raw")) + state->oob_format |= NAND_OOB_RAW; + else if (!strcmp(args[i], "oob_only")) + state->oob_format |= NAND_OOB_RAW | NAND_OOB_ONLY; + else if (sw_ecc && !strcmp(args[i], "oob_softecc")) + state->oob_format |= NAND_OOB_SW_ECC; + else if (sw_ecc && !strcmp(args[i], "oob_softecc_kw")) + state->oob_format |= NAND_OOB_SW_ECC_KW; + else + { + command_print(cmd_ctx, "unknown option: %s", args[i]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } + } + + retval = nand_fileio_start(cmd_ctx, nand, args[1], filemode, state); + if (ERROR_OK != retval) + return retval; + + if (!need_size) + state->size = state->fileio.size; + + *dev = nand; + + return ERROR_OK; +} + +/** + * @returns If no error occurred, returns number of bytes consumed; + * otherwise, returns a negative error code.) + */ +int nand_fileio_read(struct nand_device *nand, + struct nand_fileio_state *s) +{ + uint32_t total_read = 0; + uint32_t one_read; + + if (NULL != s->page) + { + fileio_read(&s->fileio, s->page_size, s->page, &one_read); + if (one_read < s->page_size) + memset(s->page + one_read, 0xff, s->page_size - one_read); + total_read += one_read; + } + + if (s->oob_format & NAND_OOB_SW_ECC) + { + uint8_t ecc[3]; + memset(s->oob, 0xff, s->oob_size); + for (uint32_t i = 0, j = 0; i < s->page_size; i += 256) + { + nand_calculate_ecc(nand, s->page + i, ecc); + s->oob[s->eccpos[j++]] = ecc[0]; + s->oob[s->eccpos[j++]] = ecc[1]; + s->oob[s->eccpos[j++]] = ecc[2]; + } + } + else if (s->oob_format & NAND_OOB_SW_ECC_KW) + { + /* + * In this case eccpos is not used as + * the ECC data is always stored contigously + * at the end of the OOB area. It consists + * of 10 bytes per 512-byte data block. + */ + uint8_t *ecc = s->oob + s->oob_size - s->page_size / 512 * 10; + memset(s->oob, 0xff, s->oob_size); + for (uint32_t i = 0; i < s->page_size; i += 512) + { + nand_calculate_ecc_kw(nand, s->page + i, ecc); + ecc += 10; + } + } + else if (NULL != s->oob) + { + fileio_read(&s->fileio, s->oob_size, s->oob, &one_read); + if (one_read < s->oob_size) + memset(s->oob + one_read, 0xff, s->oob_size - one_read); + total_read += one_read; + } + return total_read; +} + COMMAND_HANDLER(handle_nand_write_command) { uint32_t offset; ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 26 +++ src/flash/nand.c | 477 ++++++++++++++++++++++++++++++--------------------- src/helper/fileio.h | 1 + 3 files changed, 305 insertions(+), 199 deletions(-) hooks/post-receive -- Main OpenOCD repository |