X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Ftcl.c;h=cf0daf34b77c5a37f61a1641fbad5c8601340572;hb=89bf96ffe6ac66c80407af8383b9d5adc0dc35f4;hp=26c43288279ec97369eb75abb43a0b2a2b9d51a5;hpb=667bf9c80fae84c075a422d71140d257b7a23f5a;p=openocd.git diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 26c4328827..cf0daf34b7 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -31,11 +31,18 @@ * Implements Tcl commands used to access NOR flash facilities. */ -COMMAND_HELPER(flash_command_get_bank, unsigned name_index, - struct flash_bank **bank) +COMMAND_HELPER(flash_command_get_bank_maybe_probe, unsigned name_index, + struct flash_bank **bank, bool do_probe) { const char *name = CMD_ARGV[name_index]; - int retval = get_flash_bank_by_name(name, bank); + int retval; + if (do_probe) { + retval = get_flash_bank_by_name(name, bank); + } else { + *bank = get_flash_bank_by_name_noprobe(name); + retval = ERROR_OK; + } + if (retval != ERROR_OK) return retval; if (*bank) @@ -44,7 +51,20 @@ COMMAND_HELPER(flash_command_get_bank, unsigned name_index, unsigned bank_num; COMMAND_PARSE_NUMBER(uint, name, bank_num); - return get_flash_bank_by_num(bank_num, bank); + if (do_probe) { + return get_flash_bank_by_num(bank_num, bank); + } else { + *bank = get_flash_bank_by_num_noprobe(bank_num); + retval = (bank) ? ERROR_OK : ERROR_FAIL; + return retval; + } +} + +COMMAND_HELPER(flash_command_get_bank, unsigned name_index, + struct flash_bank **bank) +{ + return CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, + name_index, bank, true); } COMMAND_HANDLER(handle_flash_info_command) @@ -121,7 +141,7 @@ COMMAND_HANDLER(handle_flash_probe_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); + retval = CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe, 0, &p, false); if (retval != ERROR_OK) return retval; @@ -535,7 +555,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) { uint32_t offset; uint8_t *buffer; - struct fileio fileio; + struct fileio *fileio; if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; @@ -553,23 +573,23 @@ COMMAND_HANDLER(handle_flash_write_bank_command) if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) return ERROR_OK; - int filesize; - retval = fileio_size(&fileio, &filesize); + size_t filesize; + retval = fileio_size(fileio, &filesize); if (retval != ERROR_OK) { - fileio_close(&fileio); + fileio_close(fileio); return retval; } buffer = malloc(filesize); if (buffer == NULL) { - fileio_close(&fileio); + fileio_close(fileio); LOG_ERROR("Out of memory"); return ERROR_FAIL; } size_t buf_cnt; - if (fileio_read(&fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { + if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { free(buffer); - fileio_close(&fileio); + fileio_close(fileio); return ERROR_OK; } @@ -579,17 +599,176 @@ COMMAND_HANDLER(handle_flash_write_bank_command) buffer = NULL; if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) { - command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u" + command_print(CMD_CTX, "wrote %zu bytes from file %s to flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - (long)filesize, CMD_ARGV[1], p->bank_number, offset, + filesize, CMD_ARGV[1], p->bank_number, offset, duration_elapsed(&bench), duration_kbps(&bench, filesize)); } - fileio_close(&fileio); + fileio_close(fileio); + + return retval; +} + +COMMAND_HANDLER(handle_flash_read_bank_command) +{ + uint32_t offset; + uint8_t *buffer; + struct fileio *fileio; + uint32_t length; + size_t written; + + if (CMD_ARGC != 4) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct duration bench; + duration_start(&bench); + + struct flash_bank *p; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); + if (ERROR_OK != retval) + return retval; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], length); + + buffer = malloc(length); + if (buffer == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + retval = flash_driver_read(p, buffer, offset, length); + if (retval != ERROR_OK) { + LOG_ERROR("Read error"); + free(buffer); + return retval; + } + + retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_WRITE, FILEIO_BINARY); + if (retval != ERROR_OK) { + LOG_ERROR("Could not open file"); + free(buffer); + return retval; + } + + retval = fileio_write(fileio, length, buffer, &written); + fileio_close(fileio); + free(buffer); + if (retval != ERROR_OK) { + LOG_ERROR("Could not write file"); + return ERROR_FAIL; + } + + if (duration_measure(&bench) == ERROR_OK) + command_print(CMD_CTX, "wrote %ld bytes to file %s from flash bank %u" + " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", + (long)written, CMD_ARGV[1], p->bank_number, offset, + duration_elapsed(&bench), duration_kbps(&bench, written)); return retval; } + +COMMAND_HANDLER(handle_flash_verify_bank_command) +{ + uint32_t offset; + uint8_t *buffer_file, *buffer_flash; + struct fileio *fileio; + size_t read_cnt; + size_t filesize; + int differ; + + if (CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct duration bench; + duration_start(&bench); + + struct flash_bank *p; + int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p); + if (ERROR_OK != retval) + return retval; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + + retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY); + if (retval != ERROR_OK) { + LOG_ERROR("Could not open file"); + return retval; + } + + retval = fileio_size(fileio, &filesize); + if (retval != ERROR_OK) { + fileio_close(fileio); + return retval; + } + + buffer_file = malloc(filesize); + if (buffer_file == NULL) { + LOG_ERROR("Out of memory"); + fileio_close(fileio); + return ERROR_FAIL; + } + + retval = fileio_read(fileio, filesize, buffer_file, &read_cnt); + fileio_close(fileio); + if (retval != ERROR_OK) { + LOG_ERROR("File read failure"); + free(buffer_file); + return retval; + } + + if (read_cnt != filesize) { + LOG_ERROR("Short read"); + free(buffer_file); + return ERROR_FAIL; + } + + buffer_flash = malloc(filesize); + if (buffer_flash == NULL) { + LOG_ERROR("Out of memory"); + free(buffer_file); + return ERROR_FAIL; + } + + retval = flash_driver_read(p, buffer_flash, offset, read_cnt); + if (retval != ERROR_OK) { + LOG_ERROR("Flash read error"); + free(buffer_flash); + free(buffer_file); + return retval; + } + + if (duration_measure(&bench) == ERROR_OK) + command_print(CMD_CTX, "read %ld bytes from file %s and flash bank %u" + " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", + (long)read_cnt, CMD_ARGV[1], p->bank_number, offset, + duration_elapsed(&bench), duration_kbps(&bench, read_cnt)); + + differ = memcmp(buffer_file, buffer_flash, read_cnt); + command_print(CMD_CTX, "contents %s", differ ? "differ" : "match"); + if (differ) { + uint32_t t; + int diffs = 0; + for (t = 0; t < read_cnt; t++) { + if (buffer_flash[t] == buffer_file[t]) + continue; + command_print(CMD_CTX, "diff %d address 0x%08x. Was 0x%02x instead of 0x%02x", + diffs, t + offset, buffer_flash[t], buffer_file[t]); + if (diffs++ >= 127) { + command_print(CMD_CTX, "More than 128 errors, the rest are not printed."); + break; + } + keep_alive(); + } + } + free(buffer_flash); + free(buffer_file); + + return differ ? ERROR_FAIL : ERROR_OK; +} + void flash_set_dirty(void) { struct flash_bank *c; @@ -706,6 +885,24 @@ static const struct command_registration flash_exec_command_handlers[] = { "and/or erase the region to be used. Allow optional " "offset from beginning of bank (defaults to zero)", }, + { + .name = "read_bank", + .handler = handle_flash_read_bank_command, + .mode = COMMAND_EXEC, + .usage = "bank_id filename offset length", + .help = "Read binary data from flash bank to file, " + "starting at specified byte offset from the " + "beginning of the bank.", + }, + { + .name = "verify_bank", + .handler = handle_flash_verify_bank_command, + .mode = COMMAND_EXEC, + .usage = "bank_id filename offset", + .help = "Read binary data from flash bank and file, " + "starting at specified byte offset from the " + "beginning of the bank. Compare the contents.", + }, { .name = "protect", .handler = handle_flash_protect_command,