target/armv7m, cortex_m: fix misleading comments
[fw/openocd] / src / target / cortex_m.c
index 9a1f2b16fee1adb2caaad68de9989b00ad41a77f..94cf824893e732edbc856f612b0fa4424c0ba8ad 100644 (file)
@@ -56,8 +56,8 @@ 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)
+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 +71,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 +89,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 +108,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,7 +129,7 @@ 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;
 
@@ -445,6 +445,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 */
@@ -494,6 +502,18 @@ 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.is_armv8m) {
+               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;
@@ -507,12 +527,6 @@ static int cortex_m_debug_entry(struct target *target)
        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);
@@ -521,7 +535,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
@@ -540,9 +554,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) {
@@ -635,13 +650,9 @@ 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 */
+               if (cortex_m->dcb_dhcsr & S_RETIRE_ST || cortex_m->dcb_dhcsr & S_SLEEP) {
                        target->state = TARGET_RUNNING;
                        retval = ERROR_OK;
                }
@@ -710,11 +721,11 @@ static int cortex_m_soft_reset_halt(struct target *target)
        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.");
 
        /* Set C_DEBUGEN */
        retval = cortex_m_write_debug_halt_mask(target, 0, C_STEP | C_MASKINTS);
@@ -806,15 +817,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;
@@ -951,7 +966,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
@@ -966,8 +981,7 @@ static int cortex_m_step(struct target *target, int current,
                                /* Re-enable interrupts if appropriate */
                                cortex_m_write_debug_halt_mask(target, C_HALT, 0);
                                cortex_m_set_maskints_for_halt(target);
-                       }
-                       else {
+                       } else {
 
                                /* Set a temporary break point */
                                if (breakpoint) {
@@ -1393,7 +1407,7 @@ int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpo
        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;
        struct cortex_m_common *cortex_m = target_to_cm(target);
@@ -1476,7 +1490,7 @@ 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;
@@ -1590,176 +1604,6 @@ void cortex_m_enable_watchpoints(struct target *target)
        }
 }
 
-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;
-
-                               case ARMV7M_BASEPRI:
-                                       *value = buf_get_u32((uint8_t *)value, 8, 8);
-                                       break;
-
-                               case ARMV7M_FAULTMASK:
-                                       *value = buf_get_u32((uint8_t *)value, 16, 1);
-                                       break;
-
-                               case ARMV7M_CONTROL:
-                                       *value = buf_get_u32((uint8_t *)value, 24, 2);
-                                       break;
-                       }
-
-                       LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value);
-                       break;
-
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       return ERROR_OK;
-}
-
-static int cortex_m_store_core_reg_u32(struct target *target,
-               uint32_t num, uint32_t value)
-{
-       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;
-
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       return ERROR_OK;
-}
-
 static int cortex_m_read_memory(struct target *target, target_addr_t address,
        uint32_t size, uint32_t count, uint8_t *buffer)
 {
@@ -1815,28 +1659,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)
@@ -1850,40 +1689,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;
                }
 
@@ -1980,7 +1800,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;
@@ -1993,7 +1813,7 @@ 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;
@@ -2021,7 +1841,7 @@ fail0:
                return;
        }
 
-       cache = calloc(1, sizeof *cache);
+       cache = calloc(1, sizeof(*cache));
        if (!cache) {
 fail1:
                free(cm->dwt_comparator_list);
@@ -2029,7 +1849,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;
@@ -2149,16 +1969,24 @@ int cortex_m_examine(struct target *target)
                /* Get CPU Type */
                i = (cpuid >> 4) & 0xf;
 
+               /* Check if it is an ARMv8-M core */
+               armv7m->arm.is_armv8m = true;
+
                switch (cpuid & ARM_CPUID_PARTNO_MASK) {
                        case CORTEX_M23_PARTNO:
                                i = 23;
                                break;
-
                        case CORTEX_M33_PARTNO:
                                i = 33;
                                break;
-
+                       case CORTEX_M35P_PARTNO:
+                               i = 35;
+                               break;
+                       case CORTEX_M55_PARTNO:
+                               i = 55;
+                               break;
                        default:
+                               armv7m->arm.is_armv8m = false;
                                break;
                }
 
@@ -2189,7 +2017,7 @@ int cortex_m_examine(struct target *target)
                                LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
                                armv7m->fp_feature = FPv4_SP;
                        }
-               } else if (i == 7 || i == 33) {
+               } else if (i == 7 || i == 33 || i == 35 || i == 55) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
@@ -2214,7 +2042,6 @@ int cortex_m_examine(struct target *target)
                        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);
                        }
@@ -2231,6 +2058,19 @@ int cortex_m_examine(struct target *target)
                                armv7m->debug_ap->tar_autoincr_block = (1 << 10);
                }
 
+               /* Enable debug requests */
+               retval = target_read_u32(target, DCB_DHCSR, &cortex_m->dcb_dhcsr);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {
+                       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 */
                retval = target_write_u32(target, DCB_DEMCR, TRCENA | armv7m->demcr);
                if (retval != ERROR_OK)
@@ -2461,6 +2301,11 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
        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;