target/cortex_m: cumulate DHCSR sticky bits
[openocd.git] / src / target / cortex_m.c
index dcb3ddd8264f14f60ec4ef4880ec1d89f20fd66b..6558252270a95959da1cb797cb437cb3d93fcfa8 100644 (file)
 #include "cortex_m.h"
 #include "target_request.h"
 #include "target_type.h"
+#include "arm_adi_v5.h"
 #include "arm_disassembler.h"
 #include "register.h"
 #include "arm_opcodes.h"
 #include "arm_semihosting.h"
 #include <helper/time_support.h>
+#include <rtt/rtt.h>
 
 /* NOTE:  most of this should work fine for the Cortex-M1 and
  * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
- * Some differences:  M0/M1 doesn't have FBP remapping or the
+ * Some differences:  M0/M1 doesn't have FPB remapping or the
  * DWT tracing/profiling support.  (So the cycle counter will
  * not be usable; the other stuff isn't currently used here.)
  *
  * any longer.
  */
 
+/* Supported Cortex-M Cores */
+static const struct cortex_m_part_info cortex_m_parts[] = {
+       {
+               .partno = CORTEX_M0_PARTNO,
+               .name = "Cortex-M0",
+               .arch = ARM_ARCH_V6M,
+       },
+       {
+               .partno = CORTEX_M0P_PARTNO,
+               .name = "Cortex-M0+",
+               .arch = ARM_ARCH_V6M,
+       },
+       {
+               .partno = CORTEX_M1_PARTNO,
+               .name = "Cortex-M1",
+               .arch = ARM_ARCH_V6M,
+       },
+       {
+               .partno = CORTEX_M3_PARTNO,
+               .name = "Cortex-M3",
+               .arch = ARM_ARCH_V7M,
+               .flags = CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
+       },
+       {
+               .partno = CORTEX_M4_PARTNO,
+               .name = "Cortex-M4",
+               .arch = ARM_ARCH_V7M,
+               .flags = CORTEX_M_F_HAS_FPV4 | CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
+       },
+       {
+               .partno = CORTEX_M7_PARTNO,
+               .name = "Cortex-M7",
+               .arch = ARM_ARCH_V7M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+       {
+               .partno = CORTEX_M23_PARTNO,
+               .name = "Cortex-M23",
+               .arch = ARM_ARCH_V8M,
+       },
+       {
+               .partno = CORTEX_M33_PARTNO,
+               .name = "Cortex-M33",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+       {
+               .partno = CORTEX_M35P_PARTNO,
+               .name = "Cortex-M35P",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+       {
+               .partno = CORTEX_M55_PARTNO,
+               .name = "Cortex-M55",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+};
+
 /* forward declarations */
 static int cortex_m_store_core_reg_u32(struct target *target,
                uint32_t num, uint32_t value);
 static void cortex_m_dwt_free(struct target *target);
 
-static int cortexm_dap_read_coreregister_u32(struct target *target,
-       uint32_t *value, int regnum)
+/** DCB DHCSR register contains S_RETIRE_ST and S_RESET_ST bits cleared
+ *  on a read. Call this helper function each time DHCSR is read
+ *  to preserve S_RESET_ST state in case of a reset event was detected.
+ */
+static inline void cortex_m_cumulate_dhcsr_sticky(struct cortex_m_common *cortex_m,
+               uint32_t dhcsr)
+{
+       cortex_m->dcb_dhcsr_cumulated_sticky |= dhcsr;
+}
+
+/** Read DCB DHCSR register to cortex_m->dcb_dhcsr and cumulate
+ * sticky bits in cortex_m->dcb_dhcsr_cumulated_sticky
+ */
+static int cortex_m_read_dhcsr_atomic_sticky(struct target *target)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+
+       int retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
+                               &cortex_m->dcb_dhcsr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr);
+       return ERROR_OK;
+}
+
+static int cortex_m_load_core_reg_u32(struct target *target,
+               uint32_t regsel, uint32_t *value)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
        int retval;
@@ -71,7 +160,7 @@ static int cortexm_dap_read_coreregister_u32(struct target *target,
                        return retval;
        }
 
-       retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regnum);
+       retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel);
        if (retval != ERROR_OK)
                return retval;
 
@@ -89,8 +178,8 @@ static int cortexm_dap_read_coreregister_u32(struct target *target,
        return retval;
 }
 
-static int cortexm_dap_write_coreregister_u32(struct target *target,
-       uint32_t value, int regnum)
+static int cortex_m_store_core_reg_u32(struct target *target,
+               uint32_t regsel, uint32_t value)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
        int retval;
@@ -108,12 +197,12 @@ static int cortexm_dap_write_coreregister_u32(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regnum | DCRSR_WnR);
+       retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WNR);
        if (retval != ERROR_OK)
                return retval;
 
        if (target->dbg_msg_enabled) {
-               /* restore DCB_DCRDR - this needs to be in a seperate
+               /* restore DCB_DCRDR - this needs to be in a separate
                 * transaction otherwise the emulated DCC channel breaks */
                if (retval == ERROR_OK)
                        retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr);
@@ -129,13 +218,90 @@ static int cortex_m_write_debug_halt_mask(struct target *target,
        struct armv7m_common *armv7m = &cortex_m->armv7m;
 
        /* mask off status bits */
-       cortex_m->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
+       cortex_m->dcb_dhcsr &= ~((0xFFFFul << 16) | mask_off);
        /* create new register mask */
        cortex_m->dcb_dhcsr |= DBGKEY | C_DEBUGEN | mask_on;
 
        return mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR, cortex_m->dcb_dhcsr);
 }
 
+static int cortex_m_set_maskints(struct target *target, bool mask)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       if (!!(cortex_m->dcb_dhcsr & C_MASKINTS) != mask)
+               return cortex_m_write_debug_halt_mask(target, mask ? C_MASKINTS : 0, mask ? 0 : C_MASKINTS);
+       else
+               return ERROR_OK;
+}
+
+static int cortex_m_set_maskints_for_halt(struct target *target)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       switch (cortex_m->isrmasking_mode) {
+               case CORTEX_M_ISRMASK_AUTO:
+                       /* interrupts taken at resume, whether for step or run -> no mask */
+                       return cortex_m_set_maskints(target, false);
+
+               case CORTEX_M_ISRMASK_OFF:
+                       /* interrupts never masked */
+                       return cortex_m_set_maskints(target, false);
+
+               case CORTEX_M_ISRMASK_ON:
+                       /* interrupts always masked */
+                       return cortex_m_set_maskints(target, true);
+
+               case CORTEX_M_ISRMASK_STEPONLY:
+                       /* interrupts masked for single step only -> mask now if MASKINTS
+                        * erratum, otherwise only mask before stepping */
+                       return cortex_m_set_maskints(target, cortex_m->maskints_erratum);
+       }
+       return ERROR_OK;
+}
+
+static int cortex_m_set_maskints_for_run(struct target *target)
+{
+       switch (target_to_cm(target)->isrmasking_mode) {
+               case CORTEX_M_ISRMASK_AUTO:
+                       /* interrupts taken at resume, whether for step or run -> no mask */
+                       return cortex_m_set_maskints(target, false);
+
+               case CORTEX_M_ISRMASK_OFF:
+                       /* interrupts never masked */
+                       return cortex_m_set_maskints(target, false);
+
+               case CORTEX_M_ISRMASK_ON:
+                       /* interrupts always masked */
+                       return cortex_m_set_maskints(target, true);
+
+               case CORTEX_M_ISRMASK_STEPONLY:
+                       /* interrupts masked for single step only -> no mask */
+                       return cortex_m_set_maskints(target, false);
+       }
+       return ERROR_OK;
+}
+
+static int cortex_m_set_maskints_for_step(struct target *target)
+{
+       switch (target_to_cm(target)->isrmasking_mode) {
+               case CORTEX_M_ISRMASK_AUTO:
+                       /* the auto-interrupt should already be done -> mask */
+                       return cortex_m_set_maskints(target, true);
+
+               case CORTEX_M_ISRMASK_OFF:
+                       /* interrupts never masked */
+                       return cortex_m_set_maskints(target, false);
+
+               case CORTEX_M_ISRMASK_ON:
+                       /* interrupts always masked */
+                       return cortex_m_set_maskints(target, true);
+
+               case CORTEX_M_ISRMASK_STEPONLY:
+                       /* interrupts masked for single step only -> mask */
+                       return cortex_m_set_maskints(target, true);
+       }
+       return ERROR_OK;
+}
+
 static int cortex_m_clear_halt(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
@@ -162,21 +328,18 @@ static int cortex_m_clear_halt(struct target *target)
 static int cortex_m_single_step_core(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
-       struct armv7m_common *armv7m = &cortex_m->armv7m;
        int retval;
 
-       /* Mask interrupts before clearing halt, if done already.  This avoids
+       /* Mask interrupts before clearing halt, if not done already.  This avoids
         * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing
         * HALT can put the core into an unknown state.
         */
        if (!(cortex_m->dcb_dhcsr & C_MASKINTS)) {
-               retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
-                               DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
+               retval = cortex_m_write_debug_halt_mask(target, C_MASKINTS, 0);
                if (retval != ERROR_OK)
                        return retval;
        }
-       retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
-                       DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
+       retval = cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
        if (retval != ERROR_OK)
                return retval;
        LOG_DEBUG(" ");
@@ -207,7 +370,6 @@ static int cortex_m_enable_fpb(struct target *target)
 
 static int cortex_m_endreset_event(struct target *target)
 {
-       int i;
        int retval;
        uint32_t dcb_demcr;
        struct cortex_m_common *cortex_m = target_to_cm(target);
@@ -227,18 +389,19 @@ static int cortex_m_endreset_event(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       /* Enable debug requests */
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+       retval = cortex_m_read_dhcsr_atomic_sticky(target);
        if (retval != ERROR_OK)
                return retval;
+
        if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
+               /* Enable debug requests */
                retval = cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP | C_MASKINTS);
                if (retval != ERROR_OK)
                        return retval;
        }
 
-       /* clear any interrupt masking */
-       cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS);
+       /* Restore proper interrupt masking setting for running CPU. */
+       cortex_m_set_maskints_for_run(target);
 
        /* Enable features controlled by ITM and DWT blocks, and catch only
         * the vectors we were told to pay attention to.
@@ -252,7 +415,7 @@ static int cortex_m_endreset_event(struct target *target)
                return retval;
 
        /* Paranoia: evidently some (early?) chips don't preserve all the
-        * debug state (including FBP, DWT, etc) across reset...
+        * debug state (including FPB, DWT, etc) across reset...
         */
 
        /* Enable FPB */
@@ -262,17 +425,17 @@ static int cortex_m_endreset_event(struct target *target)
                return retval;
        }
 
-       cortex_m->fpb_enabled = 1;
+       cortex_m->fpb_enabled = true;
 
        /* Restore FPB registers */
-       for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
+       for (unsigned int i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
                retval = target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value);
                if (retval != ERROR_OK)
                        return retval;
        }
 
        /* Restore DWT registers */
-       for (i = 0; i < cortex_m->dwt_num_comp; i++) {
+       for (unsigned int i = 0; i < cortex_m->dwt_num_comp; i++) {
                retval = target_write_u32(target, dwt_list[i].dwt_comparator_address + 0,
                                dwt_list[i].comp);
                if (retval != ERROR_OK)
@@ -293,7 +456,9 @@ static int cortex_m_endreset_event(struct target *target)
        register_cache_invalidate(armv7m->arm.core_cache);
 
        /* make sure we have latest dhcsr flags */
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+       retval = cortex_m_read_dhcsr_atomic_sticky(target);
+       if (retval != ERROR_OK)
+               return retval;
 
        return retval;
 }
@@ -315,7 +480,9 @@ static int cortex_m_examine_debug_reason(struct target *target)
                        target->debug_reason = DBG_REASON_WATCHPOINT;
                else if (cortex_m->nvic_dfsr & DFSR_VCATCH)
                        target->debug_reason = DBG_REASON_BREAKPOINT;
-               else    /* EXTERNAL, HALTED */
+               else if (cortex_m->nvic_dfsr & DFSR_EXTERNAL)
+                       target->debug_reason = DBG_REASON_DBGRQ;
+               else    /* HALTED */
                        target->debug_reason = DBG_REASON_UNDEFINED;
        }
 
@@ -366,6 +533,14 @@ static int cortex_m_examine_exception_reason(struct target *target)
                        if (retval != ERROR_OK)
                                return retval;
                        break;
+               case 7: /* Secure Fault */
+                       retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_SFSR, &except_sr);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       retval = mem_ap_read_u32(armv7m->debug_ap, NVIC_SFAR, &except_ar);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       break;
                case 11:        /* SVCall */
                        break;
                case 12:        /* Debug Monitor */
@@ -402,8 +577,13 @@ static int cortex_m_debug_entry(struct target *target)
 
        LOG_DEBUG(" ");
 
+       /* Do this really early to minimize the window where the MASKINTS erratum
+        * can pile up pending interrupts. */
+       cortex_m_set_maskints_for_halt(target);
+
        cortex_m_clear_halt(target);
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+
+       retval = cortex_m_read_dhcsr_atomic_sticky(target);
        if (retval != ERROR_OK)
                return retval;
 
@@ -411,25 +591,31 @@ static int cortex_m_debug_entry(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
+       /* examine PE security state */
+       bool secure_state = false;
+       if (armv7m->arm.arch == ARM_ARCH_V8M) {
+               uint32_t dscsr;
+
+               retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DSCSR, &dscsr);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               secure_state = (dscsr & DSCSR_CDS) == DSCSR_CDS;
+       }
+
        /* Examine target state and mode
         * First load register accessible through core debug port */
        int num_regs = arm->core_cache->num_regs;
 
        for (i = 0; i < num_regs; i++) {
                r = &armv7m->arm.core_cache->reg_list[i];
-               if (!r->valid)
+               if (r->exist && !r->valid)
                        arm->read_core_reg(target, r, i, ARM_MODE_ANY);
        }
 
        r = arm->cpsr;
        xPSR = buf_get_u32(r->value, 0, 32);
 
-       /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */
-       if (xPSR & 0xf00) {
-               r->dirty = r->valid;
-               cortex_m_store_core_reg_u32(target, 16, xPSR & ~0xff);
-       }
-
        /* Are we in an exception handler */
        if (xPSR & 0x1FF) {
                armv7m->exception_number = (xPSR & 0x1FF);
@@ -438,7 +624,7 @@ static int cortex_m_debug_entry(struct target *target)
                arm->map = armv7m_msp_reg_map;
        } else {
                unsigned control = buf_get_u32(arm->core_cache
-                               ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+                               ->reg_list[ARMV7M_CONTROL].value, 0, 3);
 
                /* is this thread privileged? */
                arm->core_mode = control & 1
@@ -457,9 +643,10 @@ static int cortex_m_debug_entry(struct target *target)
        if (armv7m->exception_number)
                cortex_m_examine_exception_reason(target);
 
-       LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
+       LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", cpu in %s state, target->state: %s",
                arm_mode_name(arm->core_mode),
                buf_get_u32(arm->pc->value, 0, 32),
+               secure_state ? "Secure" : "Non-Secure",
                target_state_name(target));
 
        if (armv7m->post_debug_entry) {
@@ -480,7 +667,7 @@ static int cortex_m_poll(struct target *target)
        struct armv7m_common *armv7m = &cortex_m->armv7m;
 
        /* Read from Debug Halting Control and Status Register */
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+       retval = cortex_m_read_dhcsr_atomic_sticky(target);
        if (retval != ERROR_OK) {
                target->state = TARGET_UNKNOWN;
                return retval;
@@ -501,13 +688,17 @@ static int cortex_m_poll(struct target *target)
                detected_failure = ERROR_FAIL;
 
                /* refresh status bits */
-               retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+               retval = cortex_m_read_dhcsr_atomic_sticky(target);
                if (retval != ERROR_OK)
                        return retval;
        }
 
-       if (cortex_m->dcb_dhcsr & S_RESET_ST) {
-               target->state = TARGET_RESET;
+       if (cortex_m->dcb_dhcsr_cumulated_sticky & S_RESET_ST) {
+               cortex_m->dcb_dhcsr_cumulated_sticky &= ~S_RESET_ST;
+               if (target->state != TARGET_RESET) {
+                       target->state = TARGET_RESET;
+                       LOG_INFO("%s: external reset detected", target_name(target));
+               }
                return ERROR_OK;
        }
 
@@ -549,18 +740,30 @@ static int cortex_m_poll(struct target *target)
                }
        }
 
-       /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state.
-        * How best to model low power modes?
-        */
-
        if (target->state == TARGET_UNKNOWN) {
-               /* check if processor is retiring instructions */
-               if (cortex_m->dcb_dhcsr & S_RETIRE_ST) {
+               /* Check if processor is retiring instructions or sleeping.
+                * Unlike S_RESET_ST here we test if the target *is* running now,
+                * not if it has been running (possibly in the past). Instructions are
+                * typically processed much faster than OpenOCD polls DHCSR so S_RETIRE_ST
+                * is read always 1. That's the reason not to use dcb_dhcsr_cumulated_sticky.
+                */
+               if (cortex_m->dcb_dhcsr & S_RETIRE_ST || cortex_m->dcb_dhcsr & S_SLEEP) {
                        target->state = TARGET_RUNNING;
                        retval = ERROR_OK;
                }
        }
 
+       /* Check that target is truly halted, since the target could be resumed externally */
+       if ((prev_target_state == TARGET_HALTED) && !(cortex_m->dcb_dhcsr & S_HALT)) {
+               /* registers are now invalid */
+               register_cache_invalidate(armv7m->arm.core_cache);
+
+               target->state = TARGET_RUNNING;
+               LOG_WARNING("%s: external resume detected", target_name(target));
+               target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+               retval = ERROR_OK;
+       }
+
        /* Did we detect a failure condition that we cleared? */
        if (detected_failure != ERROR_OK)
                retval = detected_failure;
@@ -597,6 +800,10 @@ static int cortex_m_halt(struct target *target)
        /* Write to Debug Halting Control and Status Register */
        cortex_m_write_debug_halt_mask(target, C_HALT, 0);
 
+       /* Do this really early to minimize the window where the MASKINTS erratum
+        * can pile up pending interrupts. */
+       cortex_m_set_maskints_for_halt(target);
+
        target->debug_reason = DBG_REASON_DBGRQ;
 
        return ERROR_OK;
@@ -606,14 +813,23 @@ static int cortex_m_soft_reset_halt(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct armv7m_common *armv7m = &cortex_m->armv7m;
-       uint32_t dcb_dhcsr = 0;
        int retval, timeout = 0;
 
-       /* soft_reset_halt is deprecated on cortex_m as the same functionality
-        * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'
-        * As this reset only used VC_CORERESET it would only ever reset the cortex_m
+       /* on single cortex_m MCU soft_reset_halt should be avoided as same functionality
+        * can be obtained by using 'reset halt' and 'cortex_m reset_config vectreset'.
+        * As this reset only uses VC_CORERESET it would only ever reset the cortex_m
         * core, not the peripherals */
-       LOG_WARNING("soft_reset_halt is deprecated, please use 'reset halt' instead.");
+       LOG_DEBUG("soft_reset_halt is discouraged, please use 'reset halt' instead.");
+
+       if (!cortex_m->vectreset_supported) {
+               LOG_ERROR("VECTRESET is not supported on this Cortex-M core");
+               return ERROR_FAIL;
+       }
+
+       /* Set C_DEBUGEN */
+       retval = cortex_m_write_debug_halt_mask(target, 0, C_STEP | C_MASKINTS);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* Enter debug state on reset; restore DEMCR in endreset_event() */
        retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR,
@@ -632,25 +848,23 @@ static int cortex_m_soft_reset_halt(struct target *target)
        register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
 
        while (timeout < 100) {
-               retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &dcb_dhcsr);
+               retval = cortex_m_read_dhcsr_atomic_sticky(target);
                if (retval == ERROR_OK) {
                        retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_DFSR,
                                        &cortex_m->nvic_dfsr);
                        if (retval != ERROR_OK)
                                return retval;
-                       if ((dcb_dhcsr & S_HALT)
+                       if ((cortex_m->dcb_dhcsr & S_HALT)
                                && (cortex_m->nvic_dfsr & DFSR_VCATCH)) {
-                               LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
-                                       "DFSR 0x%08x",
-                                       (unsigned) dcb_dhcsr,
-                                       (unsigned) cortex_m->nvic_dfsr);
+                               LOG_DEBUG("system reset-halted, DHCSR 0x%08" PRIx32 ", DFSR 0x%08" PRIx32,
+                                       cortex_m->dcb_dhcsr, cortex_m->nvic_dfsr);
                                cortex_m_poll(target);
                                /* FIXME restore user's vector catch config */
                                return ERROR_OK;
                        } else
                                LOG_DEBUG("waiting for system reset-halt, "
-                                       "DHCSR 0x%08x, %d ms",
-                                       (unsigned) dcb_dhcsr, timeout);
+                                       "DHCSR 0x%08" PRIx32 ", %d ms",
+                                       cortex_m->dcb_dhcsr, timeout);
                }
                timeout++;
                alive_sleep(1);
@@ -700,15 +914,19 @@ static int cortex_m_resume(struct target *target, int current,
                 * in parallel with disabled interrupts can cause local faults
                 * to not be taken.
                 *
-                * REVISIT this clearly breaks non-debug execution, since the
-                * PRIMASK register state isn't saved/restored...  workaround
-                * by never resuming app code after debug execution.
+                * This breaks non-debug (application) execution if not
+                * called from armv7m_start_algorithm() which saves registers.
                 */
                buf_set_u32(r->value, 0, 1, 1);
                r->dirty = true;
                r->valid = true;
 
-               /* Make sure we are in Thumb mode */
+               /* Make sure we are in Thumb mode, set xPSR.T bit */
+               /* armv7m_start_algorithm() initializes entire xPSR register.
+                * This duplicity handles the case when cortex_m_resume()
+                * is used with the debug_execution flag directly,
+                * not called through armv7m_start_algorithm().
+                */
                r = armv7m->arm.cpsr;
                buf_set_u32(r->value, 24, 1, 1);
                r->dirty = true;
@@ -750,6 +968,7 @@ static int cortex_m_resume(struct target *target, int current,
        }
 
        /* Restart core */
+       cortex_m_set_maskints_for_run(target);
        cortex_m_write_debug_halt_mask(target, 0, C_HALT);
 
        target->debug_reason = DBG_REASON_NOTHALTED;
@@ -788,8 +1007,11 @@ static int cortex_m_step(struct target *target, int current,
        }
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
-       if (!current)
+       if (!current) {
                buf_set_u32(pc->value, 0, 32, address);
+               pc->dirty = true;
+               pc->valid = true;
+       }
 
        uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
 
@@ -812,10 +1034,12 @@ static int cortex_m_step(struct target *target, int current,
         * a normal step, otherwise we have to manually step over the bkpt
         * instruction - as such simulate a step */
        if (bkpt_inst_found == false) {
-               /* Automatic ISR masking mode off: Just step over the next instruction */
-               if ((cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO))
+               if (cortex_m->isrmasking_mode != CORTEX_M_ISRMASK_AUTO) {
+                       /* Automatic ISR masking mode off: Just step over the next
+                        * instruction, with interrupts on or off as appropriate. */
+                       cortex_m_set_maskints_for_step(target);
                        cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
-               else {
+               else {
                        /* Process interrupts during stepping in a way they don't interfere
                         * debugging.
                         *
@@ -842,7 +1066,7 @@ static int cortex_m_step(struct target *target, int current,
                         * just step over the instruction with interrupts disabled.
                         *
                         * The documentation has no information about this, it was found by observation
-                        * on STM32F1 and STM32F2. Proper explanation welcome. STM32F0 dosen't seem to
+                        * on STM32F1 and STM32F2. Proper explanation welcome. STM32F0 doesn't seem to
                         * suffer from this problem.
                         *
                         * To add some confusion: pc_value has bit 0 always set, while the breakpoint
@@ -854,32 +1078,42 @@ static int cortex_m_step(struct target *target, int current,
                                LOG_DEBUG("Stepping over next instruction with interrupts disabled");
                                cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
                                cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
-                               /* Re-enable interrupts */
-                               cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
-                       }
-                       else {
+                               /* Re-enable interrupts if appropriate */
+                               cortex_m_write_debug_halt_mask(target, C_HALT, 0);
+                               cortex_m_set_maskints_for_halt(target);
+                       else {
 
                                /* Set a temporary break point */
-                               if (breakpoint)
+                               if (breakpoint) {
                                        retval = cortex_m_set_breakpoint(target, breakpoint);
-                               else
-                                       retval = breakpoint_add(target, pc_value, 2, BKPT_HARD);
+                               } else {
+                                       enum breakpoint_type type = BKPT_HARD;
+                                       if (cortex_m->fp_rev == 0 && pc_value > 0x1FFFFFFF) {
+                                               /* FPB rev.1 cannot handle such addr, try BKPT instr */
+                                               type = BKPT_SOFT;
+                                       }
+                                       retval = breakpoint_add(target, pc_value, 2, type);
+                               }
+
                                bool tmp_bp_set = (retval == ERROR_OK);
 
                                /* No more breakpoints left, just do a step */
-                               if (!tmp_bp_set)
+                               if (!tmp_bp_set) {
+                                       cortex_m_set_maskints_for_step(target);
                                        cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
-                               else {
+                                       /* Re-enable interrupts if appropriate */
+                                       cortex_m_write_debug_halt_mask(target, C_HALT, 0);
+                                       cortex_m_set_maskints_for_halt(target);
+                               } else {
                                        /* Start the core */
                                        LOG_DEBUG("Starting core to serve pending interrupts");
                                        int64_t t_start = timeval_ms();
+                                       cortex_m_set_maskints_for_run(target);
                                        cortex_m_write_debug_halt_mask(target, 0, C_HALT | C_STEP);
 
                                        /* Wait for pending handlers to complete or timeout */
                                        do {
-                                               retval = mem_ap_read_atomic_u32(armv7m->debug_ap,
-                                                               DCB_DHCSR,
-                                                               &cortex_m->dcb_dhcsr);
+                                               retval = cortex_m_read_dhcsr_atomic_sticky(target);
                                                if (retval != ERROR_OK) {
                                                        target->state = TARGET_UNKNOWN;
                                                        return retval;
@@ -900,19 +1134,21 @@ static int cortex_m_step(struct target *target, int current,
                                                        "leaving target running");
                                        } else {
                                                /* Step over next instruction with interrupts disabled */
+                                               cortex_m_set_maskints_for_step(target);
                                                cortex_m_write_debug_halt_mask(target,
                                                        C_HALT | C_MASKINTS,
                                                        0);
                                                cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
-                                               /* Re-enable interrupts */
-                                               cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
+                                               /* Re-enable interrupts if appropriate */
+                                               cortex_m_write_debug_halt_mask(target, C_HALT, 0);
+                                               cortex_m_set_maskints_for_halt(target);
                                        }
                                }
                        }
                }
        }
 
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+       retval = cortex_m_read_dhcsr_atomic_sticky(target);
        if (retval != ERROR_OK)
                return retval;
 
@@ -990,8 +1226,8 @@ static int cortex_m_assert_reset(struct target *target)
        }
 
        /* Enable debug requests */
-       int retval;
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+       int retval = cortex_m_read_dhcsr_atomic_sticky(target);
+
        /* Store important errors instead of failing and proceed to reset assert */
 
        if (retval != ERROR_OK || !(cortex_m->dcb_dhcsr & C_DEBUGEN))
@@ -1007,8 +1243,7 @@ static int cortex_m_assert_reset(struct target *target)
 
        if (!target->reset_halt) {
                /* Set/Clear C_MASKINTS in a separate operation */
-               if (cortex_m->dcb_dhcsr & C_MASKINTS)
-                       cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS);
+               cortex_m_set_maskints_for_run(target);
 
                /* clear any debug flags before resuming */
                cortex_m_clear_halt(target);
@@ -1038,10 +1273,18 @@ static int cortex_m_assert_reset(struct target *target)
                retval = ERROR_OK;
        } else {
                /* Use a standard Cortex-M3 software reset mechanism.
-                * We default to using VECRESET as it is supported on all current cores.
+                * We default to using VECTRESET as it is supported on all current cores
+                * (except Cortex-M0, M0+ and M1 which support SYSRESETREQ only!)
                 * This has the disadvantage of not resetting the peripherals, so a
                 * reset-init event handler is needed to perform any peripheral resets.
                 */
+               if (!cortex_m->vectreset_supported
+                               && reset_config == CORTEX_M_RESET_VECTRESET) {
+                       reset_config = CORTEX_M_RESET_SYSRESETREQ;
+                       LOG_WARNING("VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead.");
+                       LOG_WARNING("Set 'cortex_m reset_config sysresetreq'.");
+               }
+
                LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ)
                        ? "SYSRESETREQ" : "VECTRESET");
 
@@ -1057,11 +1300,13 @@ static int cortex_m_assert_reset(struct target *target)
                if (retval3 != ERROR_OK)
                        LOG_DEBUG("Ignoring AP write error right after reset");
 
-               retval3 = dap_dp_init(armv7m->debug_ap->dap);
-               if (retval3 != ERROR_OK)
+               retval3 = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
+               if (retval3 != ERROR_OK) {
                        LOG_ERROR("DP initialisation failed");
-
-               else {
+                       /* The error return value must not be propagated in this case.
+                        * SYSRESETREQ or VECTRESET have been possibly triggered
+                        * so reset processing should continue */
+               } else {
                        /* I do not know why this is necessary, but it
                         * fixes strange effects (step/resume cause NMI
                         * after reset) on LM3S6918 -- Michael Schwingen
@@ -1072,7 +1317,7 @@ static int cortex_m_assert_reset(struct target *target)
        }
 
        target->state = TARGET_RESET;
-       jtag_add_sleep(50000);
+       jtag_sleep(50000);
 
        register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
 
@@ -1104,7 +1349,8 @@ static int cortex_m_deassert_reset(struct target *target)
        if ((jtag_reset_config & RESET_HAS_SRST) &&
            !(jtag_reset_config & RESET_SRST_NO_GATING) &&
                target_was_examined(target)) {
-               int retval = dap_dp_init(armv7m->debug_ap->dap);
+
+               int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
                if (retval != ERROR_OK) {
                        LOG_ERROR("DP initialisation failed");
                        return retval;
@@ -1117,7 +1363,7 @@ static int cortex_m_deassert_reset(struct target *target)
 int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
        int retval;
-       int fp_num = 0;
+       unsigned int fp_num = 0;
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
 
@@ -1132,7 +1378,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                        fp_num++;
                if (fp_num >= cortex_m->fp_num_code) {
                        LOG_ERROR("Can not find free FPB Comparator!");
-                       return ERROR_FAIL;
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
                breakpoint->set = fp_num + 1;
                fpcr_value = breakpoint->address | 1;
@@ -1148,7 +1394,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                        LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision");
                        return ERROR_FAIL;
                }
-               comparator_list[fp_num].used = 1;
+               comparator_list[fp_num].used = true;
                comparator_list[fp_num].fpcr_value = fpcr_value;
                target_write_u32(target, comparator_list[fp_num].fpcr_address,
                        comparator_list[fp_num].fpcr_value);
@@ -1163,7 +1409,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                                return retval;
                        }
 
-                       cortex_m->fpb_enabled = 1;
+                       cortex_m->fpb_enabled = true;
                }
        } else if (breakpoint->type == BKPT_SOFT) {
                uint8_t code[4];
@@ -1204,7 +1450,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct cortex_m_fp_comparator *comparator_list = cortex_m->fp_comparator_list;
 
-       if (!breakpoint->set) {
+       if (breakpoint->set <= 0) {
                LOG_WARNING("breakpoint not set");
                return ERROR_OK;
        }
@@ -1217,28 +1463,22 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
                breakpoint->set);
 
        if (breakpoint->type == BKPT_HARD) {
-               int fp_num = breakpoint->set - 1;
-               if ((fp_num < 0) || (fp_num >= cortex_m->fp_num_code)) {
+               unsigned int fp_num = breakpoint->set - 1;
+               if (fp_num >= cortex_m->fp_num_code) {
                        LOG_DEBUG("Invalid FP Comparator number in breakpoint");
                        return ERROR_OK;
                }
-               comparator_list[fp_num].used = 0;
+               comparator_list[fp_num].used = false;
                comparator_list[fp_num].fpcr_value = 0;
                target_write_u32(target, comparator_list[fp_num].fpcr_address,
                        comparator_list[fp_num].fpcr_value);
        } else {
                /* restore original instruction (kept in target endianness) */
-               if (breakpoint->length == 4) {
-                       retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1,
+               retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE,
+                                       breakpoint->length, 1,
                                        breakpoint->orig_instr);
-                       if (retval != ERROR_OK)
-                               return retval;
-               } else {
-                       retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1,
-                                       breakpoint->orig_instr);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+               if (retval != ERROR_OK)
+                       return retval;
        }
        breakpoint->set = false;
 
@@ -1247,13 +1487,6 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
 
 int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
-       struct cortex_m_common *cortex_m = target_to_cm(target);
-
-       if ((breakpoint->type == BKPT_HARD) && (cortex_m->fp_code_available < 1)) {
-               LOG_INFO("no flash patch comparator unit available for hardware breakpoint");
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       }
-
        if (breakpoint->length == 3) {
                LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request");
                breakpoint->length = 2;
@@ -1264,46 +1497,22 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
-       if (breakpoint->type == BKPT_HARD)
-               cortex_m->fp_code_available--;
-
        return cortex_m_set_breakpoint(target, breakpoint);
 }
 
 int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
-       struct cortex_m_common *cortex_m = target_to_cm(target);
-
-       /* REVISIT why check? FBP can be updated with core running ... */
-       if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       if (breakpoint->set)
-               cortex_m_unset_breakpoint(target, breakpoint);
-
-       if (breakpoint->type == BKPT_HARD)
-               cortex_m->fp_code_available++;
+       if (!breakpoint->set)
+               return ERROR_OK;
 
-       return ERROR_OK;
+       return cortex_m_unset_breakpoint(target, breakpoint);
 }
 
-int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
 {
-       int dwt_num = 0;
-       uint32_t mask, temp;
+       unsigned int dwt_num = 0;
        struct cortex_m_common *cortex_m = target_to_cm(target);
 
-       /* watchpoint params were validated earlier */
-       mask = 0;
-       temp = watchpoint->length;
-       while (temp) {
-               temp >>= 1;
-               mask++;
-       }
-       mask--;
-
        /* REVISIT Don't fully trust these "not used" records ... users
         * may set up breakpoints by hand, e.g. dual-address data value
         * watchpoint using comparator #1; comparator #0 matching cycle
@@ -1319,18 +1528,29 @@ int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint
                LOG_ERROR("Can not find free DWT Comparator");
                return ERROR_FAIL;
        }
-       comparator->used = 1;
+       comparator->used = true;
        watchpoint->set = dwt_num + 1;
 
        comparator->comp = watchpoint->address;
        target_write_u32(target, comparator->dwt_comparator_address + 0,
                comparator->comp);
 
-       comparator->mask = mask;
-       target_write_u32(target, comparator->dwt_comparator_address + 4,
-               comparator->mask);
+       if ((cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M) {
+               uint32_t mask = 0, temp;
+
+               /* watchpoint params were validated earlier */
+               temp = watchpoint->length;
+               while (temp) {
+                       temp >>= 1;
+                       mask++;
+               }
+               mask--;
+
+               comparator->mask = mask;
+               target_write_u32(target, comparator->dwt_comparator_address + 4,
+                       comparator->mask);
 
-       switch (watchpoint->rw) {
+               switch (watchpoint->rw) {
                case WPT_READ:
                        comparator->function = 5;
                        break;
@@ -1340,7 +1560,26 @@ int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint
                case WPT_ACCESS:
                        comparator->function = 7;
                        break;
+               }
+       } else {
+               uint32_t data_size = watchpoint->length >> 1;
+               comparator->mask = (watchpoint->length >> 1) | 1;
+
+               switch (watchpoint->rw) {
+               case WPT_ACCESS:
+                       comparator->function = 4;
+                       break;
+               case WPT_WRITE:
+                       comparator->function = 5;
+                       break;
+               case WPT_READ:
+                       comparator->function = 6;
+                       break;
+               }
+               comparator->function = comparator->function | (1 << 4) |
+                               (data_size << 10);
        }
+
        target_write_u32(target, comparator->dwt_comparator_address + 8,
                comparator->function);
 
@@ -1352,31 +1591,30 @@ int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint
        return ERROR_OK;
 }
 
-int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
+static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct cortex_m_dwt_comparator *comparator;
-       int dwt_num;
 
-       if (!watchpoint->set) {
+       if (watchpoint->set <= 0) {
                LOG_WARNING("watchpoint (wpid: %d) not set",
                        watchpoint->unique_id);
                return ERROR_OK;
        }
 
-       dwt_num = watchpoint->set - 1;
+       unsigned int dwt_num = watchpoint->set - 1;
 
        LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
                watchpoint->unique_id, dwt_num,
                (unsigned) watchpoint->address);
 
-       if ((dwt_num < 0) || (dwt_num >= cortex_m->dwt_num_comp)) {
+       if (dwt_num >= cortex_m->dwt_num_comp) {
                LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
                return ERROR_OK;
        }
 
        comparator = cortex_m->dwt_comparator_list + dwt_num;
-       comparator->used = 0;
+       comparator->used = false;
        comparator->function = 0;
        target_write_u32(target, comparator->dwt_comparator_address + 8,
                comparator->function);
@@ -1454,186 +1692,45 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo
        return ERROR_OK;
 }
 
-void cortex_m_enable_watchpoints(struct target *target)
+int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
 {
-       struct watchpoint *watchpoint = target->watchpoints;
-
-       /* set any pending watchpoints */
-       while (watchpoint) {
-               if (!watchpoint->set)
-                       cortex_m_set_watchpoint(target, watchpoint);
-               watchpoint = watchpoint->next;
-       }
-}
-
-static int cortex_m_load_core_reg_u32(struct target *target,
-               uint32_t num, uint32_t *value)
-{
-       int retval;
-
-       /* NOTE:  we "know" here that the register identifiers used
-        * in the v7m header match the Cortex-M3 Debug Core Register
-        * Selector values for R0..R15, xPSR, MSP, and PSP.
-        */
-       switch (num) {
-               case 0 ... 18:
-                       /* read a normal core register */
-                       retval = cortexm_dap_read_coreregister_u32(target, value, num);
-
-                       if (retval != ERROR_OK) {
-                               LOG_ERROR("JTAG failure %i", retval);
-                               return ERROR_JTAG_DEVICE_ERROR;
-                       }
-                       LOG_DEBUG("load from core reg %i  value 0x%" PRIx32 "", (int)num, *value);
-                       break;
-
-               case ARMV7M_FPSCR:
-                       /* Floating-point Status and Registers */
-                       retval = target_write_u32(target, DCB_DCRSR, 0x21);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       retval = target_read_u32(target, DCB_DCRDR, value);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       LOG_DEBUG("load from FPSCR  value 0x%" PRIx32, *value);
-                       break;
-
-               case ARMV7M_S0 ... ARMV7M_S31:
-                       /* Floating-point Status and Registers */
-                       retval = target_write_u32(target, DCB_DCRSR, num - ARMV7M_S0 + 0x40);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       retval = target_read_u32(target, DCB_DCRDR, value);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       LOG_DEBUG("load from FPU reg S%d  value 0x%" PRIx32,
-                                 (int)(num - ARMV7M_S0), *value);
-                       break;
-
-               case ARMV7M_PRIMASK:
-               case ARMV7M_BASEPRI:
-               case ARMV7M_FAULTMASK:
-               case ARMV7M_CONTROL:
-                       /* Cortex-M3 packages these four registers as bitfields
-                        * in one Debug Core register.  So say r0 and r2 docs;
-                        * it was removed from r1 docs, but still works.
-                        */
-                       cortexm_dap_read_coreregister_u32(target, value, 20);
-
-                       switch (num) {
-                               case ARMV7M_PRIMASK:
-                                       *value = buf_get_u32((uint8_t *)value, 0, 1);
-                                       break;
+       if (target->debug_reason != DBG_REASON_WATCHPOINT)
+               return ERROR_FAIL;
 
-                               case ARMV7M_BASEPRI:
-                                       *value = buf_get_u32((uint8_t *)value, 8, 8);
-                                       break;
+       struct cortex_m_common *cortex_m = target_to_cm(target);
 
-                               case ARMV7M_FAULTMASK:
-                                       *value = buf_get_u32((uint8_t *)value, 16, 1);
-                                       break;
+       for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) {
+               if (!wp->set)
+                       continue;
 
-                               case ARMV7M_CONTROL:
-                                       *value = buf_get_u32((uint8_t *)value, 24, 2);
-                                       break;
-                       }
+               unsigned int dwt_num = wp->set - 1;
+               struct cortex_m_dwt_comparator *comparator = cortex_m->dwt_comparator_list + dwt_num;
 
-                       LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value);
-                       break;
+               uint32_t dwt_function;
+               int retval = target_read_u32(target, comparator->dwt_comparator_address + 8, &dwt_function);
+               if (retval != ERROR_OK)
+                       return ERROR_FAIL;
 
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+               /* check the MATCHED bit */
+               if (dwt_function & BIT(24)) {
+                       *hit_watchpoint = wp;
+                       return ERROR_OK;
+               }
        }
 
-       return ERROR_OK;
+       return ERROR_FAIL;
 }
 
-static int cortex_m_store_core_reg_u32(struct target *target,
-               uint32_t num, uint32_t value)
+void cortex_m_enable_watchpoints(struct target *target)
 {
-       int retval;
-       uint32_t reg;
-       struct armv7m_common *armv7m = target_to_armv7m(target);
-
-       /* NOTE:  we "know" here that the register identifiers used
-        * in the v7m header match the Cortex-M3 Debug Core Register
-        * Selector values for R0..R15, xPSR, MSP, and PSP.
-        */
-       switch (num) {
-               case 0 ... 18:
-                       retval = cortexm_dap_write_coreregister_u32(target, value, num);
-                       if (retval != ERROR_OK) {
-                               struct reg *r;
-
-                               LOG_ERROR("JTAG failure");
-                               r = armv7m->arm.core_cache->reg_list + num;
-                               r->dirty = r->valid;
-                               return ERROR_JTAG_DEVICE_ERROR;
-                       }
-                       LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value);
-                       break;
-
-               case ARMV7M_FPSCR:
-                       /* Floating-point Status and Registers */
-                       retval = target_write_u32(target, DCB_DCRDR, value);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       retval = target_write_u32(target, DCB_DCRSR, 0x21 | (1<<16));
-                       if (retval != ERROR_OK)
-                               return retval;
-                       LOG_DEBUG("write FPSCR value 0x%" PRIx32, value);
-                       break;
-
-               case ARMV7M_S0 ... ARMV7M_S31:
-                       /* Floating-point Status and Registers */
-                       retval = target_write_u32(target, DCB_DCRDR, value);
-                       if (retval != ERROR_OK)
-                               return retval;
-                       retval = target_write_u32(target, DCB_DCRSR, (num - ARMV7M_S0 + 0x40) | (1<<16));
-                       if (retval != ERROR_OK)
-                               return retval;
-                       LOG_DEBUG("write FPU reg S%d  value 0x%" PRIx32,
-                                 (int)(num - ARMV7M_S0), value);
-                       break;
-
-               case ARMV7M_PRIMASK:
-               case ARMV7M_BASEPRI:
-               case ARMV7M_FAULTMASK:
-               case ARMV7M_CONTROL:
-                       /* Cortex-M3 packages these four registers as bitfields
-                        * in one Debug Core register.  So say r0 and r2 docs;
-                        * it was removed from r1 docs, but still works.
-                        */
-                       cortexm_dap_read_coreregister_u32(target, &reg, 20);
-
-                       switch (num) {
-                               case ARMV7M_PRIMASK:
-                                       buf_set_u32((uint8_t *)&reg, 0, 1, value);
-                                       break;
-
-                               case ARMV7M_BASEPRI:
-                                       buf_set_u32((uint8_t *)&reg, 8, 8, value);
-                                       break;
-
-                               case ARMV7M_FAULTMASK:
-                                       buf_set_u32((uint8_t *)&reg, 16, 1, value);
-                                       break;
-
-                               case ARMV7M_CONTROL:
-                                       buf_set_u32((uint8_t *)&reg, 24, 2, value);
-                                       break;
-                       }
-
-                       cortexm_dap_write_coreregister_u32(target, reg, 20);
-
-                       LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value);
-                       break;
+       struct watchpoint *watchpoint = target->watchpoints;
 
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+       /* set any pending watchpoints */
+       while (watchpoint) {
+               if (!watchpoint->set)
+                       cortex_m_set_watchpoint(target, watchpoint);
+               watchpoint = watchpoint->next;
        }
-
-       return ERROR_OK;
 }
 
 static int cortex_m_read_memory(struct target *target, target_addr_t address,
@@ -1641,7 +1738,7 @@ static int cortex_m_read_memory(struct target *target, target_addr_t address,
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
 
-       if (armv7m->arm.is_armv6m) {
+       if (armv7m->arm.arch == ARM_ARCH_V6M) {
                /* armv6m does not handle unaligned memory access */
                if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
                        return ERROR_TARGET_UNALIGNED_ACCESS;
@@ -1655,7 +1752,7 @@ static int cortex_m_write_memory(struct target *target, target_addr_t address,
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
 
-       if (armv7m->arm.is_armv6m) {
+       if (armv7m->arm.arch == ARM_ARCH_V6M) {
                /* armv6m does not handle unaligned memory access */
                if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
                        return ERROR_TARGET_UNALIGNED_ACCESS;
@@ -1691,28 +1788,23 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
        struct timeval timeout, now;
        struct armv7m_common *armv7m = target_to_armv7m(target);
        uint32_t reg_value;
-       bool use_pcsr = false;
-       int retval = ERROR_OK;
-       struct reg *reg;
-
-       gettimeofday(&timeout, NULL);
-       timeval_add_time(&timeout, seconds, 0);
+       int retval;
 
        retval = target_read_u32(target, DWT_PCSR, &reg_value);
        if (retval != ERROR_OK) {
                LOG_ERROR("Error while reading PCSR");
                return retval;
        }
-
-       if (reg_value != 0) {
-               use_pcsr = true;
-               LOG_INFO("Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can...");
-       } else {
-               LOG_INFO("Starting profiling. Halting and resuming the"
-                        " target as often as we can...");
-               reg = register_get_by_name(target->reg_cache, "pc", 1);
+       if (reg_value == 0) {
+               LOG_INFO("PCSR sampling not supported on this processor.");
+               return target_profiling_default(target, samples, max_num_samples, num_samples, seconds);
        }
 
+       gettimeofday(&timeout, NULL);
+       timeval_add_time(&timeout, seconds, 0);
+
+       LOG_INFO("Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can...");
+
        /* Make sure the target is running */
        target_poll(target);
        if (target->state == TARGET_HALTED)
@@ -1726,40 +1818,21 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
        uint32_t sample_count = 0;
 
        for (;;) {
-               if (use_pcsr) {
-                       if (armv7m && armv7m->debug_ap) {
-                               uint32_t read_count = max_num_samples - sample_count;
-                               if (read_count > 1024)
-                                       read_count = 1024;
-
-                               retval = mem_ap_read_buf_noincr(armv7m->debug_ap,
-                                                       (void *)&samples[sample_count],
-                                                       4, read_count, DWT_PCSR);
-                               sample_count += read_count;
-                       } else {
-                               target_read_u32(target, DWT_PCSR, &samples[sample_count++]);
-                       }
+               if (armv7m && armv7m->debug_ap) {
+                       uint32_t read_count = max_num_samples - sample_count;
+                       if (read_count > 1024)
+                               read_count = 1024;
+
+                       retval = mem_ap_read_buf_noincr(armv7m->debug_ap,
+                                               (void *)&samples[sample_count],
+                                               4, read_count, DWT_PCSR);
+                       sample_count += read_count;
                } else {
-                       target_poll(target);
-                       if (target->state == TARGET_HALTED) {
-                               reg_value = buf_get_u32(reg->value, 0, 32);
-                               /* current pc, addr = 0, do not handle breakpoints, not debugging */
-                               retval = target_resume(target, 1, 0, 0, 0);
-                               samples[sample_count++] = reg_value;
-                               target_poll(target);
-                               alive_sleep(10); /* sleep 10ms, i.e. <100 samples/second. */
-                       } else if (target->state == TARGET_RUNNING) {
-                               /* We want to quickly sample the PC. */
-                               retval = target_halt(target);
-                       } else {
-                               LOG_INFO("Target not halted or running");
-                               retval = ERROR_OK;
-                               break;
-                       }
+                       target_read_u32(target, DWT_PCSR, &samples[sample_count++]);
                }
 
                if (retval != ERROR_OK) {
-                       LOG_ERROR("Error while reading %s", use_pcsr ? "PCSR" : "target pc");
+                       LOG_ERROR("Error while reading PCSR");
                        return retval;
                }
 
@@ -1856,7 +1929,7 @@ static void cortex_m_dwt_addreg(struct target *t, struct reg *r, const struct dw
 {
        struct dwt_reg_state *state;
 
-       state = calloc(1, sizeof *state);
+       state = calloc(1, sizeof(*state));
        if (!state)
                return;
        state->addr = d->addr;
@@ -1869,12 +1942,12 @@ static void cortex_m_dwt_addreg(struct target *t, struct reg *r, const struct dw
        r->type = &dwt_reg_type;
 }
 
-void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
+static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
 {
        uint32_t dwtcr;
        struct reg_cache *cache;
        struct cortex_m_dwt_comparator *comparator;
-       int reg, i;
+       int reg;
 
        target_read_u32(target, DWT_CTRL, &dwtcr);
        LOG_DEBUG("DWT_CTRL: 0x%" PRIx32, dwtcr);
@@ -1883,6 +1956,9 @@ void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
                return;
        }
 
+       target_read_u32(target, DWT_DEVARCH, &cm->dwt_devarch);
+       LOG_DEBUG("DWT_DEVARCH: 0x%" PRIx32, cm->dwt_devarch);
+
        cm->dwt_num_comp = (dwtcr >> 28) & 0xF;
        cm->dwt_comp_available = cm->dwt_num_comp;
        cm->dwt_comparator_list = calloc(cm->dwt_num_comp,
@@ -1894,7 +1970,7 @@ fail0:
                return;
        }
 
-       cache = calloc(1, sizeof *cache);
+       cache = calloc(1, sizeof(*cache));
        if (!cache) {
 fail1:
                free(cm->dwt_comparator_list);
@@ -1902,7 +1978,7 @@ fail1:
        }
        cache->name = "Cortex-M DWT registers";
        cache->num_regs = 2 + cm->dwt_num_comp * 3;
-       cache->reg_list = calloc(cache->num_regs, sizeof *cache->reg_list);
+       cache->reg_list = calloc(cache->num_regs, sizeof(*cache->reg_list));
        if (!cache->reg_list) {
                free(cache);
                goto fail1;
@@ -1913,7 +1989,7 @@ fail1:
                        dwt_base_regs + reg);
 
        comparator = cm->dwt_comparator_list;
-       for (i = 0; i < cm->dwt_num_comp; i++, comparator++) {
+       for (unsigned int i = 0; i < cm->dwt_num_comp; i++, comparator++) {
                int j;
 
                comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i;
@@ -1971,21 +2047,29 @@ static void cortex_m_dwt_free(struct target *target)
 #define MVFR1_DEFAULT_M7_SP 0x11000011
 #define MVFR1_DEFAULT_M7_DP 0x12000011
 
+static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp,
+               struct adiv5_ap **debug_ap)
+{
+       if (dap_find_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK)
+               return ERROR_OK;
+
+       return dap_find_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap);
+}
+
 int cortex_m_examine(struct target *target)
 {
        int retval;
        uint32_t cpuid, fpcr, mvfr0, mvfr1;
-       int i;
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
        struct armv7m_common *armv7m = target_to_armv7m(target);
 
-       /* stlink shares the examine handler but does not support
+       /* hla_target shares the examine handler but does not support
         * all its calls */
-       if (!armv7m->stlink) {
-               if (cortex_m->apsel < 0) {
+       if (!armv7m->is_hla_target) {
+               if (cortex_m->apsel == DP_APSEL_INVALID) {
                        /* Search for the MEM-AP */
-                       retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap);
+                       retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap);
                        if (retval != ERROR_OK) {
                                LOG_ERROR("Could not find MEM-AP to control the core");
                                return retval;
@@ -2010,69 +2094,96 @@ int cortex_m_examine(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               /* Get CPU Type */
-               i = (cpuid >> 4) & 0xf;
+               /* Get ARCH and CPU types */
+               const enum cortex_m_partno core_partno = (cpuid & ARM_CPUID_PARTNO_MASK) >> ARM_CPUID_PARTNO_POS;
+
+               for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) {
+                       if (core_partno == cortex_m_parts[n].partno) {
+                               cortex_m->core_info = &cortex_m_parts[n];
+                               break;
+                       }
+               }
+
+               if (!cortex_m->core_info) {
+                       LOG_ERROR("Cortex-M PARTNO 0x%x is unrecognized", core_partno);
+                       return ERROR_FAIL;
+               }
+
+               armv7m->arm.arch = cortex_m->core_info->arch;
 
-               LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected",
-                               i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
-               if (i == 7) {
+               LOG_INFO("%s: %s r%" PRId8 "p%" PRId8 " processor detected",
+                               target_name(target),
+                               cortex_m->core_info->name,
+                               (uint8_t)((cpuid >> 20) & 0xf),
+                               (uint8_t)((cpuid >> 0) & 0xf));
+
+               cortex_m->maskints_erratum = false;
+               if (core_partno == CORTEX_M7_PARTNO) {
                        uint8_t rev, patch;
                        rev = (cpuid >> 20) & 0xf;
                        patch = (cpuid >> 0) & 0xf;
-                       if ((rev == 0) && (patch < 2))
-                               LOG_WARNING("Silicon bug: single stepping will enter pending exception handler!");
+                       if ((rev == 0) && (patch < 2)) {
+                               LOG_WARNING("Silicon bug: single stepping may enter pending exception handler!");
+                               cortex_m->maskints_erratum = true;
+                       }
                }
                LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
 
-               if (i == 4) {
+               if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
                        /* test for floating point feature on Cortex-M4 */
                        if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
-                               LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
-                               armv7m->fp_feature = FPv4_SP;
+                               LOG_DEBUG("%s floating point feature FPv4_SP found", cortex_m->core_info->name);
+                               armv7m->fp_feature = FPV4_SP;
                        }
-               } else if (i == 7) {
+               } else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
                        /* test for floating point features on Cortex-M7 */
                        if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) {
-                               LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", i);
-                               armv7m->fp_feature = FPv5_SP;
+                               LOG_DEBUG("%s floating point feature FPv5_SP found", cortex_m->core_info->name);
+                               armv7m->fp_feature = FPV5_SP;
                        } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) {
-                               LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", i);
-                               armv7m->fp_feature = FPv5_DP;
+                               LOG_DEBUG("%s floating point feature FPv5_DP found", cortex_m->core_info->name);
+                               armv7m->fp_feature = FPV5_DP;
                        }
-               } else if (i == 0) {
-                       /* Cortex-M0 does not support unaligned memory access */
-                       armv7m->arm.is_armv6m = true;
                }
 
-               if (armv7m->fp_feature == FP_NONE &&
-                   armv7m->arm.core_cache->num_regs > ARMV7M_NUM_CORE_REGS_NOFP) {
-                       /* free unavailable FPU registers */
-                       size_t idx;
-
-                       for (idx = ARMV7M_NUM_CORE_REGS_NOFP;
-                            idx < armv7m->arm.core_cache->num_regs;
-                            idx++) {
-                               free(armv7m->arm.core_cache->reg_list[idx].value);
-                               free(armv7m->arm.core_cache->reg_list[idx].feature);
-                               free(armv7m->arm.core_cache->reg_list[idx].reg_data_type);
-                       }
-                       armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP;
-               }
+               /* VECTRESET is supported only on ARMv7-M cores */
+               cortex_m->vectreset_supported = armv7m->arm.arch == ARM_ARCH_V7M;
+
+               /* Check for FPU, otherwise mark FPU register as non-existent */
+               if (armv7m->fp_feature == FP_NONE)
+                       for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++)
+                               armv7m->arm.core_cache->reg_list[idx].exist = false;
+
+               if (armv7m->arm.arch != ARM_ARCH_V8M)
+                       for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++)
+                               armv7m->arm.core_cache->reg_list[idx].exist = false;
 
-               if (!armv7m->stlink) {
-                       if (i == 3 || i == 4)
+               if (!armv7m->is_hla_target) {
+                       if (cortex_m->core_info->flags & CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K)
                                /* Cortex-M3/M4 have 4096 bytes autoincrement range,
                                 * s. ARM IHI 0031C: MEM-AP 7.2.2 */
                                armv7m->debug_ap->tar_autoincr_block = (1 << 12);
-                       else if (i == 7)
-                               /* Cortex-M7 has only 1024 bytes autoincrement range */
-                               armv7m->debug_ap->tar_autoincr_block = (1 << 10);
+               }
+
+               retval = target_read_u32(target, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+               if (retval != ERROR_OK)
+                       return retval;
+               cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr);
+
+               if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
+                       /* Enable debug requests */
+                       uint32_t dhcsr = (cortex_m->dcb_dhcsr | C_DEBUGEN) & ~(C_HALT | C_STEP | C_MASKINTS);
+
+                       retval = target_write_u32(target, DCB_DHCSR, DBGKEY | (dhcsr & 0x0000FFFFUL));
+                       if (retval != ERROR_OK)
+                               return retval;
+                       cortex_m->dcb_dhcsr = dhcsr;
                }
 
                /* Configure trace modules */
@@ -2080,10 +2191,8 @@ int cortex_m_examine(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               if (armv7m->trace_config.config_type != TRACE_CONFIG_TYPE_DISABLED) {
-                       armv7m_trace_tpiu_config(target);
+               if (armv7m->trace_config.itm_deferred_config)
                        armv7m_trace_itm_config(target);
-               }
 
                /* NOTE: FPB and DWT are both optional. */
 
@@ -2092,7 +2201,6 @@ int cortex_m_examine(struct target *target)
                /* bits [14:12] and [7:4] */
                cortex_m->fp_num_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF);
                cortex_m->fp_num_lit = (fpcr >> 8) & 0xF;
-               cortex_m->fp_code_available = cortex_m->fp_num_code;
                /* Detect flash patch revision, see RM DDI 0403E.b page C1-817.
                   Revision is zero base, fp_rev == 1 means Rev.2 ! */
                cortex_m->fp_rev = (fpcr >> 28) & 0xf;
@@ -2101,7 +2209,7 @@ int cortex_m_examine(struct target *target)
                                cortex_m->fp_num_code + cortex_m->fp_num_lit,
                                sizeof(struct cortex_m_fp_comparator));
                cortex_m->fpb_enabled = fpcr & 1;
-               for (i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
+               for (unsigned int i = 0; i < cortex_m->fp_num_code + cortex_m->fp_num_lit; i++) {
                        cortex_m->fp_comparator_list[i].type =
                                (i < cortex_m->fp_num_code) ? FPCR_CODE : FPCR_LITERAL;
                        cortex_m->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i;
@@ -2119,7 +2227,7 @@ int cortex_m_examine(struct target *target)
                cortex_m_dwt_setup(cortex_m, target);
 
                /* These hardware breakpoints only work for code in flash! */
-               LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
+               LOG_INFO("%s: target has %d breakpoints, %d watchpoints",
                        target_name(target),
                        cortex_m->fp_num_code,
                        cortex_m->dwt_num_comp);
@@ -2234,21 +2342,27 @@ static int cortex_m_init_arch_info(struct target *target,
        armv7m->load_core_reg_u32 = cortex_m_load_core_reg_u32;
        armv7m->store_core_reg_u32 = cortex_m_store_core_reg_u32;
 
-       target_register_timer_callback(cortex_m_handle_target_request, 1, 1, target);
+       target_register_timer_callback(cortex_m_handle_target_request, 1,
+               TARGET_TIMER_TYPE_PERIODIC, target);
 
        return ERROR_OK;
 }
 
 static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
 {
-       struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
-       cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
        struct adiv5_private_config *pc;
 
        pc = (struct adiv5_private_config *)target->private_config;
        if (adiv5_verify_config(pc) != ERROR_OK)
                return ERROR_FAIL;
 
+       struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
+       if (!cortex_m) {
+               LOG_ERROR("No memory creating target");
+               return ERROR_FAIL;
+       }
+
+       cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
        cortex_m->apsel = pc->ap_num;
 
        cortex_m_init_arch_info(target, cortex_m, pc->dap);
@@ -2258,11 +2372,11 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
 
 /*--------------------------------------------------------------------------*/
 
-static int cortex_m_verify_pointer(struct command_context *cmd_ctx,
+static int cortex_m_verify_pointer(struct command_invocation *cmd,
        struct cortex_m_common *cm)
 {
        if (cm->common_magic != CORTEX_M_COMMON_MAGIC) {
-               command_print(cmd_ctx, "target is not a Cortex-M");
+               command_print(cmd, "target is not a Cortex-M");
                return ERROR_TARGET_INVALID;
        }
        return ERROR_OK;
@@ -2274,20 +2388,6 @@ static int cortex_m_verify_pointer(struct command_context *cmd_ctx,
  * cortexm3_target structure, which is only used with CM3 targets.
  */
 
-static const struct {
-       char name[10];
-       unsigned mask;
-} vec_ids[] = {
-       { "hard_err",   VC_HARDERR, },
-       { "int_err",    VC_INTERR, },
-       { "bus_err",    VC_BUSERR, },
-       { "state_err",  VC_STATERR, },
-       { "chk_err",    VC_CHKERR, },
-       { "nocp_err",   VC_NOCPERR, },
-       { "mm_err",     VC_MMERR, },
-       { "reset",      VC_CORERESET, },
-};
-
 COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
 {
        struct target *target = get_current_target(CMD_CTX);
@@ -2296,10 +2396,29 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
        uint32_t demcr = 0;
        int retval;
 
-       retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
+       static const struct {
+               char name[10];
+               unsigned mask;
+       } vec_ids[] = {
+               { "hard_err",   VC_HARDERR, },
+               { "int_err",    VC_INTERR, },
+               { "bus_err",    VC_BUSERR, },
+               { "state_err",  VC_STATERR, },
+               { "chk_err",    VC_CHKERR, },
+               { "nocp_err",   VC_NOCPERR, },
+               { "mm_err",     VC_MMERR, },
+               { "reset",      VC_CORERESET, },
+       };
+
+       retval = cortex_m_verify_pointer(CMD, cortex_m);
        if (retval != ERROR_OK)
                return retval;
 
+       if (!target_was_examined(target)) {
+               LOG_ERROR("Target not examined yet");
+               return ERROR_FAIL;
+       }
+
        retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &demcr);
        if (retval != ERROR_OK)
                return retval;
@@ -2351,7 +2470,7 @@ write:
        }
 
        for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++) {
-               command_print(CMD_CTX, "%9s: %s", vec_ids[i].name,
+               command_print(CMD, "%9s: %s", vec_ids[i].name,
                        (demcr & vec_ids[i].mask) ? "catch" : "ignore");
        }
 
@@ -2364,39 +2483,35 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
        struct cortex_m_common *cortex_m = target_to_cm(target);
        int retval;
 
-       static const Jim_Nvp nvp_maskisr_modes[] = {
+       static const struct jim_nvp nvp_maskisr_modes[] = {
                { .name = "auto", .value = CORTEX_M_ISRMASK_AUTO },
                { .name = "off", .value = CORTEX_M_ISRMASK_OFF },
                { .name = "on", .value = CORTEX_M_ISRMASK_ON },
+               { .name = "steponly", .value = CORTEX_M_ISRMASK_STEPONLY },
                { .name = NULL, .value = -1 },
        };
-       const Jim_Nvp *n;
+       const struct jim_nvp *n;
 
 
-       retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
+       retval = cortex_m_verify_pointer(CMD, cortex_m);
        if (retval != ERROR_OK)
                return retval;
 
        if (target->state != TARGET_HALTED) {
-               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
+               command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
                return ERROR_OK;
        }
 
        if (CMD_ARGC > 0) {
-               n = Jim_Nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
-               if (n->name == NULL)
+               n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
+               if (!n->name)
                        return ERROR_COMMAND_SYNTAX_ERROR;
                cortex_m->isrmasking_mode = n->value;
-
-
-               if (cortex_m->isrmasking_mode == CORTEX_M_ISRMASK_ON)
-                       cortex_m_write_debug_halt_mask(target, C_HALT | C_MASKINTS, 0);
-               else
-                       cortex_m_write_debug_halt_mask(target, C_HALT, C_MASKINTS);
+               cortex_m_set_maskints_for_halt(target);
        }
 
-       n = Jim_Nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode);
-       command_print(CMD_CTX, "cortex_m interrupt mask %s", n->name);
+       n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode);
+       command_print(CMD, "cortex_m interrupt mask %s", n->name);
 
        return ERROR_OK;
 }
@@ -2408,15 +2523,23 @@ COMMAND_HANDLER(handle_cortex_m_reset_config_command)
        int retval;
        char *reset_config;
 
-       retval = cortex_m_verify_pointer(CMD_CTX, cortex_m);
+       retval = cortex_m_verify_pointer(CMD, cortex_m);
        if (retval != ERROR_OK)
                return retval;
 
        if (CMD_ARGC > 0) {
                if (strcmp(*CMD_ARGV, "sysresetreq") == 0)
                        cortex_m->soft_reset_config = CORTEX_M_RESET_SYSRESETREQ;
-               else if (strcmp(*CMD_ARGV, "vectreset") == 0)
-                       cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
+
+               else if (strcmp(*CMD_ARGV, "vectreset") == 0) {
+                       if (target_was_examined(target)
+                                       && !cortex_m->vectreset_supported)
+                               LOG_WARNING("VECTRESET is not supported on your Cortex-M core!");
+                       else
+                               cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
+
+               } else
+                       return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        switch (cortex_m->soft_reset_config) {
@@ -2433,7 +2556,7 @@ COMMAND_HANDLER(handle_cortex_m_reset_config_command)
                        break;
        }
 
-       command_print(CMD_CTX, "cortex_m reset_config %s", reset_config);
+       command_print(CMD, "cortex_m reset_config %s", reset_config);
 
        return ERROR_OK;
 }
@@ -2444,7 +2567,7 @@ static const struct command_registration cortex_m_exec_command_handlers[] = {
                .handler = handle_cortex_m_mask_interrupts_command,
                .mode = COMMAND_EXEC,
                .help = "mask cortex_m interrupts",
-               .usage = "['auto'|'on'|'off']",
+               .usage = "['auto'|'on'|'off'|'steponly']",
        },
        {
                .name = "vector_catch",
@@ -2458,7 +2581,7 @@ static const struct command_registration cortex_m_exec_command_handlers[] = {
                .handler = handle_cortex_m_reset_config_command,
                .mode = COMMAND_ANY,
                .help = "configure software reset handling",
-               .usage = "['srst'|'sysresetreq'|'vectreset']",
+               .usage = "['sysresetreq'|'vectreset']",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -2469,6 +2592,11 @@ static const struct command_registration cortex_m_command_handlers[] = {
        {
                .chain = armv7m_trace_command_handlers,
        },
+       /* START_DEPRECATED_TPIU */
+       {
+               .chain = arm_tpiu_deprecated_command_handlers,
+       },
+       /* END_DEPRECATED_TPIU */
        {
                .name = "cortex_m",
                .mode = COMMAND_EXEC,
@@ -2476,12 +2604,14 @@ static const struct command_registration cortex_m_command_handlers[] = {
                .usage = "",
                .chain = cortex_m_exec_command_handlers,
        },
+       {
+               .chain = rtt_target_command_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
 
 struct target_type cortexm_target = {
        .name = "cortex_m",
-       .deprecated_name = "cortex_m3",
 
        .poll = cortex_m_poll,
        .arch_state = armv7m_arch_state,
@@ -2496,6 +2626,7 @@ struct target_type cortexm_target = {
        .deassert_reset = cortex_m_deassert_reset,
        .soft_reset_halt = cortex_m_soft_reset_halt,
 
+       .get_gdb_arch = arm_get_gdb_arch,
        .get_gdb_reg_list = armv7m_get_gdb_reg_list,
 
        .read_memory = cortex_m_read_memory,
@@ -2511,6 +2642,7 @@ struct target_type cortexm_target = {
        .remove_breakpoint = cortex_m_remove_breakpoint,
        .add_watchpoint = cortex_m_add_watchpoint,
        .remove_watchpoint = cortex_m_remove_watchpoint,
+       .hit_watchpoint = cortex_m_hit_watchpoint,
 
        .commands = cortex_m_command_handlers,
        .target_create = cortex_m_target_create,

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)