]> git.sur5r.net Git - openocd/blobdiff - src/flash/nor/tcl.c
flash/nor/tcl.c: Less verbose output of flash erase_check.
[openocd] / src / flash / nor / tcl.c
index 26c43288279ec97369eb75abb43a0b2a2b9d51a5..9628684ed6bac7eb680bf977df2aa51d24640b15 100644 (file)
@@ -15,9 +15,7 @@
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.           *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
 #ifdef HAVE_CONFIG_H
 #include "config.h"
  * 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 +49,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 +139,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;
 
@@ -142,6 +160,7 @@ COMMAND_HANDLER(handle_flash_probe_command)
 
 COMMAND_HANDLER(handle_flash_erase_check_command)
 {
+       bool blank = true;
        if (CMD_ARGC != 1)
                return ERROR_COMMAND_SYNTAX_ERROR;
 
@@ -167,10 +186,11 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
                if (p->sectors[j].is_erased == 0)
                        erase_state = "not erased";
                else if (p->sectors[j].is_erased == 1)
-                       erase_state = "erased";
+                       continue;
                else
                        erase_state = "erase state unknown";
 
+               blank = false;
                command_print(CMD_CTX,
                        "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
                        j,
@@ -180,6 +200,8 @@ COMMAND_HANDLER(handle_flash_erase_check_command)
                        erase_state);
        }
 
+       if (blank)
+               command_print(CMD_CTX, "\tBank is erased");
        return retval;
 }
 
@@ -535,7 +557,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 +575,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 +601,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 +887,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,