armv7m: restore core mode after executing algorithm
[openocd.git] / src / target / armv7m.c
index 5122462f949eef6f3c8cb3b04c23bd9304436c5f..9740a28c5790e6caafe5537e8d594601e0d84a8c 100644 (file)
@@ -8,7 +8,7 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
- *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
+ *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   along with this program; if not, write to the                         *
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *                                                                         *
+ *     ARMv7-M Architecture, Application Level Reference Manual               *
+ *              ARM DDI 0405C (September 2008)                             *
+ *                                                                         *
  ***************************************************************************/
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+#include "breakpoints.h"
 #include "armv7m.h"
-
+#include "algorithm.h"
+#include "register.h"
 
 #if 0
 #define _DEBUG_INSTRUCTION_EXECUTION_
 #endif
 
-char* armv7m_mode_strings[] =
-{
-       "Thread", "Thread (User)", "Handler",
+static char *armv7m_exception_strings[] = {
+       "", "Reset", "NMI", "HardFault",
+       "MemManage", "BusFault", "UsageFault", "RESERVED",
+       "RESERVED", "RESERVED", "RESERVED", "SVCall",
+       "DebugMonitor", "RESERVED", "PendSV", "SysTick"
 };
 
-char* armv7m_exception_strings[] =
-{
-       "", "Reset", "NMI", "HardFault", "MemManage", "BusFault", "UsageFault", "RESERVED", "RESERVED", "RESERVED", "RESERVED",
-       "SVCall", "DebugMonitor", "RESERVED", "PendSV", "SysTick"
+/* PSP is used in some thread modes */
+const int armv7m_psp_reg_map[17] = {
+       ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+       ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+       ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+       ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
+       ARMV7M_xPSR,
 };
 
-char* armv7m_core_reg_list[] =
-{
-       /* Registers accessed through core debug */
-       "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12",
-       "sp", "lr", "pc",
-       "xPSR", "msp", "psp",
-       /* Registers accessed through special reg 20 */
-       "primask", "basepri", "faultmask", "control"
-};
-
-uint8_t armv7m_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-
-reg_t armv7m_gdb_dummy_fp_reg =
-{
-       "GDB dummy floating-point register", armv7m_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
-};
-
-uint8_t armv7m_gdb_dummy_fps_value[] = {0, 0, 0, 0};
-
-reg_t armv7m_gdb_dummy_fps_reg =
-{
-       "GDB dummy floating-point status register", armv7m_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
+/* MSP is used in handler and some thread modes */
+const int armv7m_msp_reg_map[17] = {
+       ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+       ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+       ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+       ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
+       ARMV7M_xPSR,
 };
 
 #ifdef ARMV7_GDB_HACKS
 uint8_t armv7m_gdb_dummy_cpsr_value[] = {0, 0, 0, 0};
 
-reg_t armv7m_gdb_dummy_cpsr_reg =
-{
-       "GDB dummy cpsr register", armv7m_gdb_dummy_cpsr_value, 0, 1, 32, NULL, 0, NULL, 0
+struct reg armv7m_gdb_dummy_cpsr_reg = {
+       .name = "GDB dummy cpsr register",
+       .value = armv7m_gdb_dummy_cpsr_value,
+       .dirty = 0,
+       .valid = 1,
+       .size = 32,
+       .arch_info = NULL,
 };
 #endif
 
-armv7m_core_reg_t armv7m_core_reg_list_arch_info[] =
-{
-       /*  CORE_GP are accesible using the core debug registers */
-       {0, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {1, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {2, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {3, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {4, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {5, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {6, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {7, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {8, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {9, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {10, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {11, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {12, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {13, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {14, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-       {15, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL},
-
-       {16, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* xPSR */
-       {17, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* MSP */
-       {18, ARMV7M_REGISTER_CORE_GP, ARMV7M_MODE_ANY, NULL, NULL}, /* PSP */
-
-       /*  CORE_SP are accesible using coreregister 20 */
-       {19, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* PRIMASK */
-       {20, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* BASEPRI */
-       {21, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}, /* FAULTMASK */
-       {22, ARMV7M_REGISTER_CORE_SP, ARMV7M_MODE_ANY, NULL, NULL}  /* CONTROL */
+/*
+ * These registers are not memory-mapped.  The ARMv7-M profile includes
+ * memory mapped registers too, such as for the NVIC (interrupt controller)
+ * and SysTick (timer) modules; those can mostly be treated as peripherals.
+ *
+ * The ARMv6-M profile is almost identical in this respect, except that it
+ * doesn't include basepri or faultmask registers.
+ */
+static const struct {
+       unsigned id;
+       const char *name;
+       unsigned bits;
+} armv7m_regs[] = {
+       { ARMV7M_R0, "r0", 32 },
+       { ARMV7M_R1, "r1", 32 },
+       { ARMV7M_R2, "r2", 32 },
+       { ARMV7M_R3, "r3", 32 },
+
+       { ARMV7M_R4, "r4", 32 },
+       { ARMV7M_R5, "r5", 32 },
+       { ARMV7M_R6, "r6", 32 },
+       { ARMV7M_R7, "r7", 32 },
+
+       { ARMV7M_R8, "r8", 32 },
+       { ARMV7M_R9, "r9", 32 },
+       { ARMV7M_R10, "r10", 32 },
+       { ARMV7M_R11, "r11", 32 },
+
+       { ARMV7M_R12, "r12", 32 },
+       { ARMV7M_R13, "sp", 32 },
+       { ARMV7M_R14, "lr", 32 },
+       { ARMV7M_PC, "pc", 32 },
+
+       { ARMV7M_xPSR, "xPSR", 32 },
+       { ARMV7M_MSP, "msp", 32 },
+       { ARMV7M_PSP, "psp", 32 },
+
+       { ARMV7M_PRIMASK, "primask", 1 },
+       { ARMV7M_BASEPRI, "basepri", 8 },
+       { ARMV7M_FAULTMASK, "faultmask", 1 },
+       { ARMV7M_CONTROL, "control", 2 },
 };
 
-int armv7m_core_reg_arch_type = -1;
-int armv7m_dummy_core_reg_arch_type = -1;
+#define ARMV7M_NUM_REGS ARRAY_SIZE(armv7m_regs)
 
-int armv7m_restore_context(target_t *target)
+/**
+ * Restores target context using the cache of core registers set up
+ * by armv7m_build_reg_cache(), calling optional core-specific hooks.
+ */
+int armv7m_restore_context(struct target *target)
 {
        int i;
-
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct reg_cache *cache = armv7m->arm.core_cache;
 
        LOG_DEBUG(" ");
 
        if (armv7m->pre_restore_context)
                armv7m->pre_restore_context(target);
 
-       for (i = ARMV7NUMCOREREGS-1; i >= 0; i--)
-       {
-               if (armv7m->core_cache->reg_list[i].dirty)
-               {
-                       armv7m->write_core_reg(target, i);
+       for (i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
+               if (cache->reg_list[i].dirty) {
+                       uint32_t value = buf_get_u32(cache->reg_list[i].value, 0, 32);
+                       armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, ARM_MODE_ANY, value);
                }
        }
 
-       if (armv7m->post_restore_context)
-               armv7m->post_restore_context(target);
-
        return ERROR_OK;
 }
 
 /* Core state functions */
+
+/**
+ * Maps ISR number (from xPSR) to name.
+ * Note that while names and meanings for the first sixteen are standardized
+ * (with zero not a true exception), external interrupts are only numbered.
+ * They are assigned by vendors, which generally assign different numbers to
+ * peripherals (such as UART0 or a USB peripheral controller).
+ */
 char *armv7m_exception_string(int number)
 {
        static char enamebuf[32];
@@ -154,33 +173,29 @@ char *armv7m_exception_string(int number)
        return enamebuf;
 }
 
-int armv7m_get_core_reg(reg_t *reg)
+static int armv7m_get_core_reg(struct reg *reg)
 {
        int retval;
-       armv7m_core_reg_t *armv7m_reg = reg->arch_info;
-       target_t *target = armv7m_reg->target;
-       armv7m_common_t *armv7m_target = target->arch_info;
+       struct arm_reg *armv7m_reg = reg->arch_info;
+       struct target *target = armv7m_reg->target;
+       struct arm *arm = target_to_arm(target);
 
        if (target->state != TARGET_HALTED)
-       {
                return ERROR_TARGET_NOT_HALTED;
-       }
 
-       retval = armv7m_target->read_core_reg(target, armv7m_reg->num);
+       retval = arm->read_core_reg(target, reg, armv7m_reg->num, arm->core_mode);
 
        return retval;
 }
 
-int armv7m_set_core_reg(reg_t *reg, uint8_t *buf)
+static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf)
 {
-       armv7m_core_reg_t *armv7m_reg = reg->arch_info;
-       target_t *target = armv7m_reg->target;
-       u32 value = buf_get_u32(buf, 0, 32);
+       struct arm_reg *armv7m_reg = reg->arch_info;
+       struct target *target = armv7m_reg->target;
+       uint32_t value = buf_get_u32(buf, 0, 32);
 
        if (target->state != TARGET_HALTED)
-       {
                return ERROR_TARGET_NOT_HALTED;
-       }
 
        buf_set_u32(reg->value, 0, 32, value);
        reg->dirty = 1;
@@ -189,90 +204,82 @@ int armv7m_set_core_reg(reg_t *reg, uint8_t *buf)
        return ERROR_OK;
 }
 
-int armv7m_read_core_reg(struct target_s *target, int num)
+static int armv7m_read_core_reg(struct target *target, struct reg *r,
+       int num, enum arm_mode mode)
 {
-       u32 reg_value;
+       uint32_t reg_value;
        int retval;
-       armv7m_core_reg_t * armv7m_core_reg;
+       struct arm_reg *armv7m_core_reg;
+       struct armv7m_common *armv7m = target_to_armv7m(target);
 
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
+       assert(num < (int)armv7m->arm.core_cache->num_regs);
 
-       if ((num < 0) || (num >= ARMV7NUMCOREREGS))
-               return ERROR_INVALID_ARGUMENTS;
+       armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
+       retval = armv7m->load_core_reg_u32(target,
+                       armv7m_core_reg->num, &reg_value);
 
-       armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
-       retval = armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, &reg_value);
-       buf_set_u32(armv7m->core_cache->reg_list[num].value, 0, 32, reg_value);
-       armv7m->core_cache->reg_list[num].valid = 1;
-       armv7m->core_cache->reg_list[num].dirty = 0;
+       buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value);
+       armv7m->arm.core_cache->reg_list[num].valid = 1;
+       armv7m->arm.core_cache->reg_list[num].dirty = 0;
 
        return retval;
 }
 
-int armv7m_write_core_reg(struct target_s *target, int num)
+static int armv7m_write_core_reg(struct target *target, struct reg *r,
+       int num, enum arm_mode mode, uint32_t value)
 {
        int retval;
-       u32 reg_value;
-       armv7m_core_reg_t *armv7m_core_reg;
-
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
-
-       if ((num < 0) || (num >= ARMV7NUMCOREREGS))
-               return ERROR_INVALID_ARGUMENTS;
-
-       reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32);
-       armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info;
-       retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value);
-       if (retval != ERROR_OK)
-       {
+       uint32_t reg_value;
+       struct arm_reg *armv7m_core_reg;
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+
+       assert(num < (int)armv7m->arm.core_cache->num_regs);
+
+       reg_value = buf_get_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32);
+       armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info;
+       retval = armv7m->store_core_reg_u32(target,
+                       armv7m_core_reg->num,
+                       reg_value);
+       if (retval != ERROR_OK) {
                LOG_ERROR("JTAG failure");
-               armv7m->core_cache->reg_list[num].dirty = armv7m->core_cache->reg_list[num].valid;
+               armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid;
                return ERROR_JTAG_DEVICE_ERROR;
        }
-       LOG_DEBUG("write core reg %i value 0x%x", num , reg_value);
-       armv7m->core_cache->reg_list[num].valid = 1;
-       armv7m->core_cache->reg_list[num].dirty = 0;
-
-       return ERROR_OK;
-}
-
-int armv7m_invalidate_core_regs(target_t *target)
-{
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
-       int i;
 
-       for (i = 0; i < armv7m->core_cache->num_regs; i++)
-       {
-               armv7m->core_cache->reg_list[i].valid = 0;
-               armv7m->core_cache->reg_list[i].dirty = 0;
-       }
+       LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
+       armv7m->arm.core_cache->reg_list[num].valid = 1;
+       armv7m->arm.core_cache->reg_list[num].dirty = 0;
 
        return ERROR_OK;
 }
 
-int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size)
+/**
+ * Returns generic ARM userspace registers to GDB.
+ * GDB doesn't quite understand that most ARMs don't have floating point
+ * hardware, so this also fakes a set of long-obsolete FPA registers that
+ * are not used in EABI based software stacks.
+ */
+int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size)
 {
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
+       struct armv7m_common *armv7m = target_to_armv7m(target);
        int i;
 
        *reg_list_size = 26;
-       *reg_list = malloc(sizeof(reg_t*) * (*reg_list_size));
-
+       *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+
+       /*
+        * GDB register packet format for ARM:
+        *  - the first 16 registers are r0..r15
+        *  - (obsolete) 8 FPA registers
+        *  - (obsolete) FPA status
+        *  - CPSR
+        */
        for (i = 0; i < 16; i++)
-       {
-               (*reg_list)[i] = &armv7m->core_cache->reg_list[i];
-       }
+               (*reg_list)[i] = &armv7m->arm.core_cache->reg_list[i];
 
        for (i = 16; i < 24; i++)
-       {
-               (*reg_list)[i] = &armv7m_gdb_dummy_fp_reg;
-       }
-
-       (*reg_list)[24] = &armv7m_gdb_dummy_fps_reg;
+               (*reg_list)[i] = &arm_gdb_dummy_fp_reg;
+       (*reg_list)[24] = &arm_gdb_dummy_fps_reg;
 
 #ifdef ARMV7_GDB_HACKS
        /* use dummy cpsr reg otherwise gdb may try and set the thumb bit */
@@ -280,7 +287,7 @@ int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_
 
        /* ARMV7M is always in thumb mode, try to make GDB understand this
         * if it does not support this arch */
-       *((char*)armv7m->core_cache->reg_list[15].value) |= 1;
+       *((char *)armv7m->arm.pc->value) |= 1;
 #else
        (*reg_list)[25] = &armv7m->core_cache->reg_list[ARMV7M_xPSR];
 #endif
@@ -288,211 +295,265 @@ int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_
        return ERROR_OK;
 }
 
-/* run to exit point. return error if exit point was not reached. */
-static int armv7m_run_and_wait(struct target_s *target, u32 entry_point, int timeout_ms, u32 exit_point, armv7m_common_t *armv7m)
+/** Runs a Thumb algorithm in the target. */
+int armv7m_run_algorithm(struct target *target,
+       int num_mem_params, struct mem_param *mem_params,
+       int num_reg_params, struct reg_param *reg_params,
+       uint32_t entry_point, uint32_t exit_point,
+       int timeout_ms, void *arch_info)
 {
-       u32 pc;
        int retval;
-       /* This code relies on the target specific  resume() and  poll()->debug_entry()
-        * sequence to write register values to the processor and the read them back */
-       if((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK)
-       {
-               return retval;
-       }
 
-       retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
-       /* If the target fails to halt due to the breakpoint, force a halt */
-       if (retval != ERROR_OK || target->state != TARGET_HALTED)
-       {
-               if ((retval=target_halt(target))!=ERROR_OK)
-                       return retval;
-               if ((retval=target_wait_state(target, TARGET_HALTED, 500))!=ERROR_OK)
-               {
-                       return retval;
-               }
-               return ERROR_TARGET_TIMEOUT;
-       }
+       retval = armv7m_start_algorithm(target,
+                       num_mem_params, mem_params,
+                       num_reg_params, reg_params,
+                       entry_point, exit_point,
+                       arch_info);
 
-       armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc);
-       if (pc != exit_point)
-       {
-               LOG_DEBUG("failed algoritm halted at 0x%x ", pc);
-               return ERROR_TARGET_TIMEOUT;
-       }
+       if (retval == ERROR_OK)
+               retval = armv7m_wait_algorithm(target,
+                               num_mem_params, mem_params,
+                               num_reg_params, reg_params,
+                               exit_point, timeout_ms,
+                               arch_info);
 
-       return ERROR_OK;
+       return retval;
 }
 
-int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
+/** Starts a Thumb algorithm in the target. */
+int armv7m_start_algorithm(struct target *target,
+       int num_mem_params, struct mem_param *mem_params,
+       int num_reg_params, struct reg_param *reg_params,
+       uint32_t entry_point, uint32_t exit_point,
+       void *arch_info)
 {
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
-       armv7m_algorithm_t *armv7m_algorithm_info = arch_info;
-       enum armv7m_mode core_mode = armv7m->core_mode;
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
+       enum arm_mode core_mode = armv7m->arm.core_mode;
        int retval = ERROR_OK;
-       int i;
-       u32 context[ARMV7NUMCOREREGS];
 
-       if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC)
-       {
+       /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
+        * at the exit point */
+
+       if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
                LOG_ERROR("current target isn't an ARMV7M target");
                return ERROR_TARGET_INVALID;
        }
 
-       if (target->state != TARGET_HALTED)
-       {
+       if (target->state != TARGET_HALTED) {
                LOG_WARNING("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       /* refresh core register cache */
-       /* Not needed if core register cache is always consistent with target process state */
-       for (i = 0; i < ARMV7NUMCOREREGS; i++)
-       {
-               if (!armv7m->core_cache->reg_list[i].valid)
-                       armv7m->read_core_reg(target, i);
-               context[i] = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
+       /* refresh core register cache
+        * Not needed if core register cache is always consistent with target process state */
+       for (unsigned i = 0; i < ARMV7M_NUM_REGS; i++) {
+
+               armv7m_algorithm_info->context[i] = buf_get_u32(
+                               armv7m->arm.core_cache->reg_list[i].value,
+                               0,
+                               32);
        }
 
-       for (i = 0; i < num_mem_params; i++)
-       {
-               if ((retval=target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value))!=ERROR_OK)
+       for (int i = 0; i < num_mem_params; i++) {
+               /* TODO: Write only out params */
+               retval = target_write_buffer(target, mem_params[i].address,
+                               mem_params[i].size,
+                               mem_params[i].value);
+               if (retval != ERROR_OK)
                        return retval;
        }
 
-       for (i = 0; i < num_reg_params; i++)
-       {
-               reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
-//             u32 regvalue;
+       for (int i = 0; i < num_reg_params; i++) {
+               struct reg *reg =
+                       register_get_by_name(armv7m->arm.core_cache, reg_params[i].reg_name, 0);
+/*             uint32_t regvalue; */
 
-               if (!reg)
-               {
+               if (!reg) {
                        LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
-                       exit(-1);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
 
-               if (reg->size != reg_params[i].size)
-               {
-                       LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
-                       exit(-1);
+               if (reg->size != reg_params[i].size) {
+                       LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size",
+                               reg_params[i].reg_name);
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
 
-//             regvalue = buf_get_u32(reg_params[i].value, 0, 32);
+/*             regvalue = buf_get_u32(reg_params[i].value, 0, 32); */
                armv7m_set_core_reg(reg, reg_params[i].value);
        }
 
-       if (armv7m_algorithm_info->core_mode != ARMV7M_MODE_ANY)
-       {
+       if (armv7m_algorithm_info->core_mode != ARM_MODE_ANY &&
+                       armv7m_algorithm_info->core_mode != core_mode) {
+
+               /* we cannot set ARM_MODE_HANDLER, so use ARM_MODE_THREAD instead */
+               if (armv7m_algorithm_info->core_mode == ARM_MODE_HANDLER) {
+                       armv7m_algorithm_info->core_mode = ARM_MODE_THREAD;
+                       LOG_INFO("ARM_MODE_HANDLER not currently supported, using ARM_MODE_THREAD instead");
+               }
+
                LOG_DEBUG("setting core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
-               buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 1, armv7m_algorithm_info->core_mode);
-               armv7m->core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
-               armv7m->core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
+               buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
+                       0, 1, armv7m_algorithm_info->core_mode);
+               armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
+               armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
        }
 
-       /* ARMV7M always runs in Thumb state */
-       if ((retval = breakpoint_add(target, exit_point, 2, BKPT_SOFT)) != ERROR_OK)
-       {
-               LOG_ERROR("can't add breakpoint to finish algorithm execution");
-               return ERROR_TARGET_FAILURE;
-       }
+       /* save previous core mode */
+       armv7m_algorithm_info->core_mode = core_mode;
 
-       retval = armv7m_run_and_wait(target, entry_point, timeout_ms, exit_point, armv7m);
+       retval = target_resume(target, 0, entry_point, 1, 1);
 
-       breakpoint_remove(target, exit_point);
+       return retval;
+}
 
-       if (retval != ERROR_OK)
-       {
-               return retval;
+/** Waits for an algorithm in the target. */
+int armv7m_wait_algorithm(struct target *target,
+       int num_mem_params, struct mem_param *mem_params,
+       int num_reg_params, struct reg_param *reg_params,
+       uint32_t exit_point, int timeout_ms,
+       void *arch_info)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct armv7m_algorithm *armv7m_algorithm_info = arch_info;
+       int retval = ERROR_OK;
+       uint32_t pc;
+
+       /* NOTE: armv7m_run_algorithm requires that each algorithm uses a software breakpoint
+        * at the exit point */
+
+       if (armv7m_algorithm_info->common_magic != ARMV7M_COMMON_MAGIC) {
+               LOG_ERROR("current target isn't an ARMV7M target");
+               return ERROR_TARGET_INVALID;
+       }
+
+       retval = target_wait_state(target, TARGET_HALTED, timeout_ms);
+       /* If the target fails to halt due to the breakpoint, force a halt */
+       if (retval != ERROR_OK || target->state != TARGET_HALTED) {
+               retval = target_halt(target);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = target_wait_state(target, TARGET_HALTED, 500);
+               if (retval != ERROR_OK)
+                       return retval;
+               return ERROR_TARGET_TIMEOUT;
+       }
+
+       armv7m->load_core_reg_u32(target, 15, &pc);
+       if (exit_point && (pc != exit_point)) {
+               LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32,
+                       pc,
+                       exit_point);
+               return ERROR_TARGET_TIMEOUT;
        }
 
        /* Read memory values to mem_params[] */
-       for (i = 0; i < num_mem_params; i++)
-       {
-               if (mem_params[i].direction != PARAM_OUT)
-                       if((retval = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK)
-                       {
+       for (int i = 0; i < num_mem_params; i++) {
+               if (mem_params[i].direction != PARAM_OUT) {
+                       retval = target_read_buffer(target, mem_params[i].address,
+                                       mem_params[i].size,
+                                       mem_params[i].value);
+                       if (retval != ERROR_OK)
                                return retval;
-                       }
+               }
        }
 
        /* Copy core register values to reg_params[] */
-       for (i = 0; i < num_reg_params; i++)
-       {
-               if (reg_params[i].direction != PARAM_OUT)
-               {
-                       reg_t *reg = register_get_by_name(armv7m->core_cache, reg_params[i].reg_name, 0);
+       for (int i = 0; i < num_reg_params; i++) {
+               if (reg_params[i].direction != PARAM_OUT) {
+                       struct reg *reg = register_get_by_name(armv7m->arm.core_cache,
+                                       reg_params[i].reg_name,
+                                       0);
 
-                       if (!reg)
-                       {
+                       if (!reg) {
                                LOG_ERROR("BUG: register '%s' not found", reg_params[i].reg_name);
-                               exit(-1);
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        }
 
-                       if (reg->size != reg_params[i].size)
-                       {
-                               LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params[i].reg_name);
-                               exit(-1);
+                       if (reg->size != reg_params[i].size) {
+                               LOG_ERROR(
+                                       "BUG: register '%s' size doesn't match reg_params[i].size",
+                                       reg_params[i].reg_name);
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        }
 
                        buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32));
                }
        }
 
-       for (i = ARMV7NUMCOREREGS-1; i >= 0; i--)
-       {
-               u32 regvalue;
-               regvalue = buf_get_u32(armv7m->core_cache->reg_list[i].value, 0, 32);
-               if (regvalue != context[i])
-               {
-                       LOG_DEBUG("restoring register %s with value 0x%8.8x", armv7m->core_cache->reg_list[i].name, context[i]);
-                       buf_set_u32(armv7m->core_cache->reg_list[i].value, 0, 32, context[i]);
-                       armv7m->core_cache->reg_list[i].valid = 1;
-                       armv7m->core_cache->reg_list[i].dirty = 1;
+       for (int i = ARMV7M_NUM_REGS - 1; i >= 0; i--) {
+               uint32_t regvalue;
+               regvalue = buf_get_u32(armv7m->arm.core_cache->reg_list[i].value, 0, 32);
+               if (regvalue != armv7m_algorithm_info->context[i]) {
+                       LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32,
+                                       armv7m->arm.core_cache->reg_list[i].name,
+                               armv7m_algorithm_info->context[i]);
+                       buf_set_u32(armv7m->arm.core_cache->reg_list[i].value,
+                               0, 32, armv7m_algorithm_info->context[i]);
+                       armv7m->arm.core_cache->reg_list[i].valid = 1;
+                       armv7m->arm.core_cache->reg_list[i].dirty = 1;
                }
        }
 
-       armv7m->core_mode = core_mode;
+       /* restore previous core mode */
+       if (armv7m_algorithm_info->core_mode != armv7m->arm.core_mode) {
+               LOG_DEBUG("restoring core_mode: 0x%2.2x", armv7m_algorithm_info->core_mode);
+               buf_set_u32(armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].value,
+                       0, 1, armv7m_algorithm_info->core_mode);
+               armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].dirty = 1;
+               armv7m->arm.core_cache->reg_list[ARMV7M_CONTROL].valid = 1;
+       }
+
+       armv7m->arm.core_mode = armv7m_algorithm_info->core_mode;
 
        return retval;
 }
 
-int armv7m_arch_state(struct target_s *target)
+/** Logs summary of ARMv7-M state for a halted target. */
+int armv7m_arch_state(struct target *target)
 {
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct arm *arm = &armv7m->arm;
+       uint32_t ctrl, sp;
 
-       LOG_USER("target halted due to %s, current mode: %s %s\nxPSR: 0x%8.8x pc: 0x%8.8x",
-                Jim_Nvp_value2name_simple( nvp_target_debug_reason,target->debug_reason)->name,
-               armv7m_mode_strings[armv7m->core_mode],
+       ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32);
+       sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32);
+
+       LOG_USER("target halted due to %s, current mode: %s %s\n"
+               "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s",
+               debug_reason_name(target),
+               arm_mode_name(arm->core_mode),
                armv7m_exception_string(armv7m->exception_number),
-               buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32),
-               buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32));
+               buf_get_u32(arm->cpsr->value, 0, 32),
+               buf_get_u32(arm->pc->value, 0, 32),
+               (ctrl & 0x02) ? 'p' : 'm',
+               sp,
+               arm->is_semihosting ? ", semihosting" : "");
 
        return ERROR_OK;
 }
 
-reg_cache_t *armv7m_build_reg_cache(target_t *target)
+static const struct reg_arch_type armv7m_reg_type = {
+       .get = armv7m_get_core_reg,
+       .set = armv7m_set_core_reg,
+};
+
+/** Builds cache of architecturally defined registers.  */
+struct reg_cache *armv7m_build_reg_cache(struct target *target)
 {
-       /* get pointers to arch-specific information */
-       armv7m_common_t *armv7m = target->arch_info;
-
-       int num_regs = ARMV7NUMCOREREGS;
-       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
-       reg_cache_t *cache = malloc(sizeof(reg_cache_t));
-       reg_t *reg_list = malloc(sizeof(reg_t) * num_regs);
-       armv7m_core_reg_t *arch_info = malloc(sizeof(armv7m_core_reg_t) * num_regs);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct arm *arm = &armv7m->arm;
+       int num_regs = ARMV7M_NUM_REGS;
+       struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
+       struct reg_cache *cache = malloc(sizeof(struct reg_cache));
+       struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
+       struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg));
        int i;
 
-       if (armv7m_core_reg_arch_type == -1)
-       {
-               armv7m_core_reg_arch_type = register_reg_arch_type(armv7m_get_core_reg, armv7m_set_core_reg);
-       }
-
-       register_init_dummy(&armv7m_gdb_dummy_fps_reg);
 #ifdef ARMV7_GDB_HACKS
        register_init_dummy(&armv7m_gdb_dummy_cpsr_reg);
 #endif
-       register_init_dummy(&armv7m_gdb_dummy_fp_reg);
 
        /* Build the process context cache */
        cache->name = "arm v7m registers";
@@ -500,113 +561,107 @@ reg_cache_t *armv7m_build_reg_cache(target_t *target)
        cache->reg_list = reg_list;
        cache->num_regs = num_regs;
        (*cache_p) = cache;
-       armv7m->core_cache = cache;
 
-       for (i = 0; i < num_regs; i++)
-       {
-               arch_info[i] = armv7m_core_reg_list_arch_info[i];
+       for (i = 0; i < num_regs; i++) {
+               arch_info[i].num = armv7m_regs[i].id;
                arch_info[i].target = target;
-               arch_info[i].armv7m_common = armv7m;
-               reg_list[i].name = armv7m_core_reg_list[i];
-               reg_list[i].size = 32;
+               arch_info[i].arm = arm;
+
+               reg_list[i].name = armv7m_regs[i].name;
+               reg_list[i].size = armv7m_regs[i].bits;
                reg_list[i].value = calloc(1, 4);
                reg_list[i].dirty = 0;
                reg_list[i].valid = 0;
-               reg_list[i].bitfield_desc = NULL;
-               reg_list[i].num_bitfields = 0;
-               reg_list[i].arch_type = armv7m_core_reg_arch_type;
+               reg_list[i].type = &armv7m_reg_type;
                reg_list[i].arch_info = &arch_info[i];
        }
 
+       arm->cpsr = reg_list + ARMV7M_xPSR;
+       arm->pc = reg_list + ARMV7M_PC;
+       arm->core_cache = cache;
        return cache;
 }
 
-int armv7m_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+static int armv7m_setup_semihosting(struct target *target, int enable)
 {
-       armv7m_build_reg_cache(target);
-
+       /* nothing todo for armv7m */
        return ERROR_OK;
 }
 
-int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m)
+/** Sets up target as a generic ARMv7-M core */
+int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m)
 {
-       /* register arch-specific functions */
+       struct arm *arm = &armv7m->arm;
 
-       target->arch_info = armv7m;
-       armv7m->read_core_reg = armv7m_read_core_reg;
-       armv7m->write_core_reg = armv7m_write_core_reg;
-
-       return ERROR_OK;
-}
+       armv7m->common_magic = ARMV7M_COMMON_MAGIC;
+       armv7m->fp_feature = FP_NONE;
 
-int armv7m_register_commands(struct command_context_s *cmd_ctx)
-{
-       command_t *arm_adi_v5_dap_cmd;
+       arm->core_type = ARM_MODE_THREAD;
+       arm->arch_info = armv7m;
+       arm->setup_semihosting = armv7m_setup_semihosting;
 
-       arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap", NULL, COMMAND_ANY, "cortex dap specific commands");         
-       register_command(cmd_ctx, arm_adi_v5_dap_cmd, "info", handle_dap_info_command, COMMAND_EXEC, "Displays dap info for ap [num], default currently selected AP");
-       register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel", handle_dap_apsel_command, COMMAND_EXEC, "Select a different AP [num] (default 0)");
-       register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid", handle_dap_apid_command, COMMAND_EXEC, "Displays id reg from AP [num], default currently selected AP");
-       register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr", handle_dap_baseaddr_command, COMMAND_EXEC, "Displays debug base address from AP [num], default currently selected AP");
-       register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess", handle_dap_memaccess_command, COMMAND_EXEC, "set/get number of extra tck for mem-ap memory bus access [0-255]");
+       arm->read_core_reg = armv7m_read_core_reg;
+       arm->write_core_reg = armv7m_write_core_reg;
 
-       return ERROR_OK;
+       return arm_init_arch_info(target, arm);
 }
 
-int armv7m_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+/** Generates a CRC32 checksum of a memory region. */
+int armv7m_checksum_memory(struct target *target,
+       uint32_t address, uint32_t count, uint32_t *checksum)
 {
-       working_area_t *crc_algorithm;
-       armv7m_algorithm_t armv7m_info;
-       reg_param_t reg_params[2];
+       struct working_area *crc_algorithm;
+       struct armv7m_algorithm armv7m_info;
+       struct reg_param reg_params[2];
        int retval;
 
-       u16 cortex_m3_crc_code[] = {
-               0x4602,                                 /* mov  r2, r0 */
-               0xF04F, 0x30FF,                 /* mov  r0, #0xffffffff */
-               0x460B,                                 /* mov  r3, r1 */
-               0xF04F, 0x0400,                 /* mov  r4, #0 */
-               0xE013,                                 /* b    ncomp */
-                                                               /* nbyte: */
-               0x5D11,                                 /* ldrb r1, [r2, r4] */
-               0xF8DF, 0x7028,                 /* ldr          r7, CRC32XOR */
-               0xEA80, 0x6001,                 /* eor          r0, r0, r1, asl #24 */
-
-               0xF04F, 0x0500,                 /* mov          r5, #0 */
-                                                               /* loop: */
-               0x2800,                                 /* cmp          r0, #0 */
-               0xEA4F, 0x0640,                 /* mov          r6, r0, asl #1 */
-               0xF105, 0x0501,                 /* add          r5, r5, #1 */
-               0x4630,                                 /* mov          r0, r6 */
-               0xBFB8,                                 /* it           lt */
-               0xEA86, 0x0007,                 /* eor          r0, r6, r7 */
-               0x2D08,                                 /* cmp          r5, #8 */
-               0xD1F4,                                 /* bne          loop */
-
-               0xF104, 0x0401,                 /* add  r4, r4, #1 */
-                                                               /* ncomp: */
-               0x429C,                                 /* cmp  r4, r3 */
-               0xD1E9,                                 /* bne  nbyte */
-                                                               /* end: */
-               0xE7FE,                                 /* b    end */
-               0x1DB7, 0x04C1                  /* CRC32XOR:    .word 0x04C11DB7 */
+       /* see contrib/loaders/checksum/armv7m_crc.s for src */
+
+       static const uint8_t cortex_m3_crc_code[] = {
+               /* main: */
+               0x02, 0x46,                     /* mov          r2, r0 */
+               0x00, 0x20,                     /* movs         r0, #0 */
+               0xC0, 0x43,                     /* mvns         r0, r0 */
+               0x0A, 0x4E,                     /* ldr          r6, CRC32XOR */
+               0x0B, 0x46,                     /* mov          r3, r1 */
+               0x00, 0x24,                     /* movs         r4, #0 */
+               0x0D, 0xE0,                     /* b            ncomp */
+               /* nbyte: */
+               0x11, 0x5D,                     /* ldrb         r1, [r2, r4] */
+               0x09, 0x06,                     /* lsls         r1, r1, #24 */
+               0x48, 0x40,                     /* eors         r0, r0, r1 */
+               0x00, 0x25,                     /* movs         r5, #0 */
+               /* loop: */
+               0x00, 0x28,                     /* cmp          r0, #0 */
+               0x02, 0xDA,                     /* bge          notset */
+               0x40, 0x00,                     /* lsls         r0, r0, #1 */
+               0x70, 0x40,                     /* eors         r0, r0, r6 */
+               0x00, 0xE0,                     /* b            cont */
+               /* notset: */
+               0x40, 0x00,                     /* lsls         r0, r0, #1 */
+               /* cont: */
+               0x01, 0x35,                     /* adds         r5, r5, #1 */
+               0x08, 0x2D,                     /* cmp          r5, #8 */
+               0xF6, 0xD1,                     /* bne          loop */
+               0x01, 0x34,                     /* adds         r4, r4, #1 */
+               /* ncomp: */
+               0x9C, 0x42,                     /* cmp          r4, r3 */
+               0xEF, 0xD1,                     /* bne          nbyte */
+               0x00, 0xBE,                     /* bkpt         #0 */
+               0xB7, 0x1D, 0xC1, 0x04  /* CRC32XOR:    .word   0x04c11db7 */
        };
 
-       u32 i;
-
-       if (target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm) != ERROR_OK)
-       {
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       }
+       retval = target_alloc_working_area(target, sizeof(cortex_m3_crc_code), &crc_algorithm);
+       if (retval != ERROR_OK)
+               return retval;
 
-       /* convert flash writing code into a buffer in target endianness */
-       for (i = 0; i < (sizeof(cortex_m3_crc_code)/sizeof(u16)); i++)
-               if((retval = target_write_u16(target, crc_algorithm->address + i*sizeof(u16), cortex_m3_crc_code[i])) != ERROR_OK)
-               {
-                       return retval;
-               }
+       retval = target_write_buffer(target, crc_algorithm->address,
+                       sizeof(cortex_m3_crc_code), (uint8_t *)cortex_m3_crc_code);
+       if (retval != ERROR_OK)
+               goto cleanup;
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-       armv7m_info.core_mode = ARMV7M_MODE_ANY;
+       armv7m_info.core_mode = ARM_MODE_ANY;
 
        init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
        init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
@@ -614,57 +669,59 @@ int armv7m_checksum_memory(struct target_s *target, u32 address, u32 count, u32*
        buf_set_u32(reg_params[0].value, 0, 32, address);
        buf_set_u32(reg_params[1].value, 0, 32, count);
 
-       if ((retval = target_run_algorithm(target, 0, NULL, 2, reg_params,
-               crc_algorithm->address, crc_algorithm->address + (sizeof(cortex_m3_crc_code)-6), 20000, &armv7m_info)) != ERROR_OK)
-       {
-               LOG_ERROR("error executing cortex_m3 crc algorithm");
-               destroy_reg_param(&reg_params[0]);
-               destroy_reg_param(&reg_params[1]);
-               target_free_working_area(target, crc_algorithm);
-               return retval;
-       }
+       int timeout = 20000 * (1 + (count / (1024 * 1024)));
 
-       *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+       retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address,
+                       crc_algorithm->address + (sizeof(cortex_m3_crc_code) - 6),
+                       timeout, &armv7m_info);
+
+       if (retval == ERROR_OK)
+               *checksum = buf_get_u32(reg_params[0].value, 0, 32);
+       else
+               LOG_ERROR("error executing cortex_m3 crc algorithm");
 
        destroy_reg_param(&reg_params[0]);
        destroy_reg_param(&reg_params[1]);
 
+cleanup:
        target_free_working_area(target, crc_algorithm);
 
-       return ERROR_OK;
+       return retval;
 }
 
-int armv7m_blank_check_memory(struct target_s *target, u32 address, u32 count, u32* blank)
+/** Checks whether a memory region is zeroed. */
+int armv7m_blank_check_memory(struct target *target,
+       uint32_t address, uint32_t count, uint32_t *blank)
 {
-       working_area_t *erase_check_algorithm;
-       reg_param_t reg_params[3];
-       armv7m_algorithm_t armv7m_info;
+       struct working_area *erase_check_algorithm;
+       struct reg_param reg_params[3];
+       struct armv7m_algorithm armv7m_info;
        int retval;
-       u32 i;
 
-       u16 erase_check_code[] =
-       {
-                                                       /* loop: */
-               0xF810, 0x3B01,         /* ldrb         r3, [r0], #1 */
-               0xEA02, 0x0203,         /* and  r2, r2, r3 */
-               0x3901,                         /* subs         r1, r1, #1 */
-               0xD1F9,                         /* bne          loop */
-                                                       /* end: */
-               0xE7FE,                         /* b            end */
+       /* see contrib/loaders/erase_check/armv7m_erase_check.s for src */
+
+       static const uint8_t erase_check_code[] = {
+               /* loop: */
+               0x03, 0x78,             /* ldrb r3, [r0] */
+               0x01, 0x30,             /* adds r0, #1 */
+               0x1A, 0x40,             /* ands r2, r2, r3 */
+               0x01, 0x39,             /* subs r1, r1, #1 */
+               0xFA, 0xD1,             /* bne  loop */
+               0x00, 0xBE              /* bkpt #0 */
        };
 
        /* make sure we have a working area */
-       if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK)
-       {
+       if (target_alloc_working_area(target, sizeof(erase_check_code),
+               &erase_check_algorithm) != ERROR_OK)
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       }
 
-       /* convert flash writing code into a buffer in target endianness */
-       for (i = 0; i < (sizeof(erase_check_code)/sizeof(u16)); i++)
-               target_write_u16(target, erase_check_algorithm->address + i*sizeof(u16), erase_check_code[i]);
+       retval = target_write_buffer(target, erase_check_algorithm->address,
+                       sizeof(erase_check_code), (uint8_t *)erase_check_code);
+       if (retval != ERROR_OK)
+               return retval;
 
        armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
-       armv7m_info.core_mode = ARMV7M_MODE_ANY;
+       armv7m_info.core_mode = ARM_MODE_ANY;
 
        init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
        buf_set_u32(reg_params[0].value, 0, 32, address);
@@ -675,17 +732,18 @@ int armv7m_blank_check_memory(struct target_s *target, u32 address, u32 count, u
        init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
        buf_set_u32(reg_params[2].value, 0, 32, 0xff);
 
-       if ((retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
-                       erase_check_algorithm->address, erase_check_algorithm->address + (sizeof(erase_check_code)-2), 10000, &armv7m_info)) != ERROR_OK)
-       {
-               destroy_reg_param(&reg_params[0]);
-               destroy_reg_param(&reg_params[1]);
-               destroy_reg_param(&reg_params[2]);
-               target_free_working_area(target, erase_check_algorithm);
-               return 0;
-       }
+       retval = target_run_algorithm(target,
+                       0,
+                       NULL,
+                       3,
+                       reg_params,
+                       erase_check_algorithm->address,
+                       erase_check_algorithm->address + (sizeof(erase_check_code) - 2),
+                       10000,
+                       &armv7m_info);
 
-       *blank = buf_get_u32(reg_params[2].value, 0, 32);
+       if (retval == ERROR_OK)
+               *blank = buf_get_u32(reg_params[2].value, 0, 32);
 
        destroy_reg_param(&reg_params[0]);
        destroy_reg_param(&reg_params[1]);
@@ -693,135 +751,49 @@ int armv7m_blank_check_memory(struct target_s *target, u32 address, u32 count, u
 
        target_free_working_area(target, erase_check_algorithm);
 
-       return ERROR_OK;
-}
-
-/********************************************************************************************************************
-* Return the debug ap baseaddress in hexadecimal, no extra output to simplify script processing
-*********************************************************************************************************************/
-int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       target_t *target = get_current_target(cmd_ctx);
-       armv7m_common_t *armv7m = target->arch_info;
-       swjdp_common_t *swjdp = &armv7m->swjdp_info;
-       u32 apsel, apselsave, baseaddr;
-       int retval;
-
-       apsel = swjdp->apsel;
-       apselsave = swjdp->apsel;
-       if (argc > 0)
-       {       
-               apsel = strtoul(args[0], NULL, 0);
-       }
-       if (apselsave != apsel)
-       {
-               dap_ap_select(swjdp, apsel);
-       }
-
-       dap_ap_read_reg_u32(swjdp, 0xF8, &baseaddr);
-       retval = swjdp_transaction_endcheck(swjdp);
-       command_print(cmd_ctx, "0x%8.8x", baseaddr);
-
-       if (apselsave != apsel)
-       {
-               dap_ap_select(swjdp, apselsave);
-       }
-
-       return retval;
-}
-
-
-/********************************************************************************************************************
-* Return the debug ap id in hexadecimal, no extra output to simplify script processing
-*********************************************************************************************************************/
-extern int handle_dap_apid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       target_t *target = get_current_target(cmd_ctx);
-       armv7m_common_t *armv7m = target->arch_info;
-       swjdp_common_t *swjdp = &armv7m->swjdp_info;
-       u32 apsel, apselsave, apid;
-       int retval;
-
-       apsel = swjdp->apsel;
-       apselsave = swjdp->apsel;
-       if (argc > 0)
-       {       
-               apsel = strtoul(args[0], NULL, 0);
-       }
-
-       if (apselsave != apsel)
-       {
-               dap_ap_select(swjdp, apsel);
-       }
-
-       dap_ap_read_reg_u32(swjdp, 0xFC, &apid);
-       retval = swjdp_transaction_endcheck(swjdp);
-       command_print(cmd_ctx, "0x%8.8x", apid);
-       if (apselsave != apsel)
-       {
-               dap_ap_select(swjdp, apselsave);
-       }
-
-       return retval;
-}
-
-int handle_dap_apsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       target_t *target = get_current_target(cmd_ctx);
-       armv7m_common_t *armv7m = target->arch_info;
-       swjdp_common_t *swjdp = &armv7m->swjdp_info;
-       u32 apsel, apid;
-       int retval;
-
-       apsel = 0;
-       if (argc > 0)
-       {       
-               apsel = strtoul(args[0], NULL, 0);
-       }
-
-       dap_ap_select(swjdp, apsel);
-       dap_ap_read_reg_u32(swjdp, 0xFC, &apid);
-       retval = swjdp_transaction_endcheck(swjdp);
-       command_print(cmd_ctx, "ap %i selected, identification register 0x%8.8x", apsel, apid);
-
        return retval;
 }
 
-int handle_dap_memaccess_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv7m_common_t *armv7m = target->arch_info;
-       swjdp_common_t *swjdp = &armv7m->swjdp_info;
-       u32 memaccess_tck;
-
-       memaccess_tck = swjdp->memaccess_tck;
-       if (argc > 0)
-       {       
-               memaccess_tck = strtoul(args[0], NULL, 0);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct reg *r = armv7m->arm.pc;
+       bool result = false;
+
+
+       /* if we halted last time due to a bkpt instruction
+        * then we have to manually step over it, otherwise
+        * the core will break again */
+
+       if (target->debug_reason == DBG_REASON_BREAKPOINT) {
+               uint16_t op;
+               uint32_t pc = buf_get_u32(r->value, 0, 32);
+
+               pc &= ~1;
+               if (target_read_u16(target, pc, &op) == ERROR_OK) {
+                       if ((op & 0xFF00) == 0xBE00) {
+                               pc = buf_get_u32(r->value, 0, 32) + 2;
+                               buf_set_u32(r->value, 0, 32, pc);
+                               r->dirty = true;
+                               r->valid = true;
+                               result = true;
+                               LOG_DEBUG("Skipping over BKPT instruction");
+                       }
+               }
        }
 
-       swjdp->memaccess_tck = memaccess_tck;
-       command_print(cmd_ctx, "memory bus access delay set to %i tck", swjdp->memaccess_tck);
+       if (inst_found)
+               *inst_found = result;
 
        return ERROR_OK;
 }
 
-int handle_dap_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-       target_t *target = get_current_target(cmd_ctx);
-       armv7m_common_t *armv7m = target->arch_info;
-       swjdp_common_t *swjdp = &armv7m->swjdp_info;
-       int retval;
-       u32 apsel;
-
-       apsel =  swjdp->apsel;
-       if (argc > 0)
-       {       
-               apsel = strtoul(args[0], NULL, 0);
-       }
-       
-       retval = dap_info_command(cmd_ctx, swjdp, apsel);
-
-       return retval;
-}
-
+const struct command_registration armv7m_command_handlers[] = {
+       {
+               .chain = arm_command_handlers,
+       },
+       {
+               .chain = dap_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)