NOR: stellaris message tweaks
[fw/openocd] / src / flash / nor / stellaris.c
index f414ca6f1f0e1582ca821c2ab411b4090f1e66bb..0b7c45a31f45ba241d6df6e21c869d0315a3dae4 100644 (file)
@@ -693,8 +693,8 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
 
        if (!set)
        {
-               LOG_ERROR("Can't unprotect write-protected pages.");
-               /* except by the "recover locked device" procedure ... */
+               LOG_ERROR("Hardware doesn't suppport page-level unprotect. "
+                       "Try the 'recover' command.");
                return ERROR_INVALID_ARGUMENTS;
        }
 
@@ -706,7 +706,7 @@ static int stellaris_protect(struct flash_bank *bank, int set, int first, int la
                        || (last < first) || !(last & 1)
                        || (last >= 2 * stellaris_info->num_lockbits))
        {
-               LOG_ERROR("Can't protect unaligned or out-of-range sectors.");
+               LOG_ERROR("Can't protect unaligned or out-of-range pages.");
                return ERROR_FLASH_SECTOR_INVALID;
        }
 
@@ -805,8 +805,7 @@ static const uint8_t stellaris_write_code[] =
        0x04,0x36,                      /* adds r6, r6, #4 */
        0x96,0x42,                      /* cmp  r6, r2 */
        0xF4,0xD1,                      /* bne  mainloop */
-                                               /* exit: */
-       0xFE,0xE7,                      /* b exit */
+       0x00,0xBE,              /* bkpt #0 */
 /* pFLASH_CTRL_BASE: */
        0x00,0xD0,0x0F,0x40,    /* .word        0x400FD000 */
 /* FLASHWRITECMD: */
@@ -1170,19 +1169,85 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
        return ERROR_OK;
 }
 
+/**
+ * Perform the Stellaris "Recovering a 'Locked' Device procedure.
+ * This performs a mass erase and then restores all nonvolatile registers
+ * (including USER_* registers and flash lock bits) to their defaults.
+ * Accordingly, flash can be reprogrammed, and JTAG can be used.
+ *
+ * NOTE that DustDevil parts (at least rev A0 silicon) have errata which
+ * can affect this operation if flash protection has been enabled.
+ */
+COMMAND_HANDLER(stellaris_handle_recover_command)
+{
+       struct flash_bank *bank;
+       int retval;
+
+       retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* REVISIT ... it may be worth sanity checking that the AP is
+        * inactive before we start.  ARM documents that switching a DP's
+        * mode while it's active can cause fault modes that need a power
+        * cycle to recover.
+        */
+
+       /* assert SRST */
+       if (!(jtag_get_reset_config() & RESET_HAS_SRST)) {
+               LOG_ERROR("Can't recover Stellaris flash without SRST");
+               return ERROR_FAIL;
+       }
+       jtag_add_reset(0, 1);
+
+       for (int i = 0; i < 5; i++) {
+               retval = dap_to_swd(bank->target);
+               if (retval != ERROR_OK)
+                       goto done;
+
+               retval = dap_to_jtag(bank->target);
+               if (retval != ERROR_OK)
+                       goto done;
+       }
+
+       /* de-assert SRST */
+       jtag_add_reset(0, 0);
+       retval = jtag_execute_queue();
+
+       /* wait 400+ msec ... OK, "1+ second" is simpler */
+       usleep(1000);
+
+       /* USER INTERVENTION required for the power cycle
+        * Restarting OpenOCD is likely needed because of mode switching.
+        */
+       LOG_INFO("USER ACTION:  "
+               "power cycle Stellaris chip, then restart OpenOCD.");
+
+done:
+       return retval;
+}
+
 static const struct command_registration stellaris_exec_command_handlers[] = {
        {
                .name = "mass_erase",
-               .handler = &stellaris_handle_mass_erase_command,
+               .handler = stellaris_handle_mass_erase_command,
                .mode = COMMAND_EXEC,
+               .usage = "bank_id",
                .help = "erase entire device",
        },
+       {
+               .name = "recover",
+               .handler = stellaris_handle_recover_command,
+               .mode = COMMAND_EXEC,
+               .usage = "bank_id",
+               .help = "recover (and erase) locked device",
+       },
        COMMAND_REGISTRATION_DONE
 };
 static const struct command_registration stellaris_command_handlers[] = {
        {
                .name = "stellaris",
-               .mode = COMMAND_ANY,
+               .mode = COMMAND_EXEC,
                .help = "Stellaris flash command group",
                .chain = stellaris_exec_command_handlers,
        },