openocd: src/target: replace the GPL-2.0-or-later license tag
[fw/openocd] / src / target / cortex_m.c
index f682606038bd5c279498a0d32ca5d4c33094fa95..1682f5dec9facbb1cf497ee8d5a095af29173ac3 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
  *   Dominic.Rath@gmx.de                                                   *
@@ -8,19 +10,6 @@
  *   Copyright (C) 2008 by Spencer Oliver                                  *
  *   spen@spen-soft.co.uk                                                  *
  *                                                                         *
- *   This program is free software; you can redistribute it and/or modify  *
- *   it under the terms of the GNU General Public License as published by  *
- *   the Free Software Foundation; either version 2 of the License, or     *
- *   (at your option) any later version.                                   *
- *                                                                         *
- *   This program is distributed in the hope that it will be useful,       *
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
- *   GNU General Public License for more details.                          *
- *                                                                         *
- *   You should have received a copy of the GNU General Public License     *
- *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
- *                                                                         *
  *                                                                         *
  *   Cortex-M3(tm) TRM, ARM DDI 0337E (r1p1) and 0337G (r2p0)              *
  *                                                                         *
@@ -53,6 +42,9 @@
  * any longer.
  */
 
+/* Timeout for register r/w */
+#define DHCSR_S_REGRDY_TIMEOUT (500)
+
 /* Supported Cortex-M Cores */
 static const struct cortex_m_part_info cortex_m_parts[] = {
        {
@@ -118,12 +110,41 @@ 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);
 
+/** 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 cortex_m_common *cortex_m = target_to_cm(target);
        struct armv7m_common *armv7m = target_to_armv7m(target);
        int retval;
-       uint32_t dcrdr;
+       uint32_t dcrdr, tmp_value;
+       int64_t then;
 
        /* because the DCB_DCRDR is used for the emulated dcc channel
         * we have to save/restore the DCB_DCRDR when used */
@@ -137,9 +158,29 @@ static int cortex_m_load_core_reg_u32(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DCRDR, value);
-       if (retval != ERROR_OK)
-               return retval;
+       /* check if value from register is ready and pre-read it */
+       then = timeval_ms();
+       while (1) {
+               retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DHCSR,
+                                                                &cortex_m->dcb_dhcsr);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DCRDR,
+                                                                               &tmp_value);
+               if (retval != ERROR_OK)
+                       return retval;
+               cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr);
+               if (cortex_m->dcb_dhcsr & S_REGRDY)
+                       break;
+               cortex_m->slow_register_read = true; /* Polling (still) needed. */
+               if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) {
+                       LOG_TARGET_ERROR(target, "Timeout waiting for DCRDR transfer ready");
+                       return ERROR_TIMEOUT_REACHED;
+               }
+               keep_alive();
+       }
+
+       *value = tmp_value;
 
        if (target->dbg_msg_enabled) {
                /* restore DCB_DCRDR - this needs to be in a separate
@@ -151,12 +192,180 @@ static int cortex_m_load_core_reg_u32(struct target *target,
        return retval;
 }
 
+static int cortex_m_slow_read_all_regs(struct target *target)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       const unsigned int num_regs = armv7m->arm.core_cache->num_regs;
+
+       /* Opportunistically restore fast read, it'll revert to slow
+        * if any register needed polling in cortex_m_load_core_reg_u32(). */
+       cortex_m->slow_register_read = false;
+
+       for (unsigned int reg_id = 0; reg_id < num_regs; reg_id++) {
+               struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id];
+               if (r->exist) {
+                       int retval = armv7m->arm.read_core_reg(target, r, reg_id, ARM_MODE_ANY);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
+       }
+
+       if (!cortex_m->slow_register_read)
+               LOG_TARGET_DEBUG(target, "Switching back to fast register reads");
+
+       return ERROR_OK;
+}
+
+static int cortex_m_queue_reg_read(struct target *target, uint32_t regsel,
+               uint32_t *reg_value, uint32_t *dhcsr)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       int retval;
+
+       retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel);
+       if (retval != ERROR_OK)
+               return retval;
+
+       retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DHCSR, dhcsr);
+       if (retval != ERROR_OK)
+               return retval;
+
+       return mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, reg_value);
+}
+
+static int cortex_m_fast_read_all_regs(struct target *target)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       int retval;
+       uint32_t dcrdr;
+
+       /* because the DCB_DCRDR is used for the emulated dcc channel
+        * we have to save/restore the DCB_DCRDR when used */
+       if (target->dbg_msg_enabled) {
+               retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DCRDR, &dcrdr);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       const unsigned int num_regs = armv7m->arm.core_cache->num_regs;
+       const unsigned int n_r32 = ARMV7M_LAST_REG - ARMV7M_CORE_FIRST_REG + 1
+                                                          + ARMV7M_FPU_LAST_REG - ARMV7M_FPU_FIRST_REG + 1;
+       /* we need one 32-bit word for each register except FP D0..D15, which
+        * need two words */
+       uint32_t r_vals[n_r32];
+       uint32_t dhcsr[n_r32];
+
+       unsigned int wi = 0; /* write index to r_vals and dhcsr arrays */
+       unsigned int reg_id; /* register index in the reg_list, ARMV7M_R0... */
+       for (reg_id = 0; reg_id < num_regs; reg_id++) {
+               struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id];
+               if (!r->exist)
+                       continue;       /* skip non existent registers */
+
+               if (r->size <= 8) {
+                       /* Any 8-bit or shorter register is unpacked from a 32-bit
+                        * container register. Skip it now. */
+                       continue;
+               }
+
+               uint32_t regsel = armv7m_map_id_to_regsel(reg_id);
+               retval = cortex_m_queue_reg_read(target, regsel, &r_vals[wi],
+                                                                                &dhcsr[wi]);
+               if (retval != ERROR_OK)
+                       return retval;
+               wi++;
+
+               assert(r->size == 32 || r->size == 64);
+               if (r->size == 32)
+                       continue;       /* done with 32-bit register */
+
+               assert(reg_id >= ARMV7M_FPU_FIRST_REG && reg_id <= ARMV7M_FPU_LAST_REG);
+               /* the odd part of FP register (S1, S3...) */
+               retval = cortex_m_queue_reg_read(target, regsel + 1, &r_vals[wi],
+                                                                                        &dhcsr[wi]);
+               if (retval != ERROR_OK)
+                       return retval;
+               wi++;
+       }
+
+       assert(wi <= n_r32);
+
+       retval = dap_run(armv7m->debug_ap->dap);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (target->dbg_msg_enabled) {
+               /* restore DCB_DCRDR - this needs to be in a separate
+                * transaction otherwise the emulated DCC channel breaks */
+               retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRDR, dcrdr);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+
+       bool not_ready = false;
+       for (unsigned int i = 0; i < wi; i++) {
+               if ((dhcsr[i] & S_REGRDY) == 0) {
+                       not_ready = true;
+                       LOG_TARGET_DEBUG(target, "Register %u was not ready during fast read", i);
+               }
+               cortex_m_cumulate_dhcsr_sticky(cortex_m, dhcsr[i]);
+       }
+
+       if (not_ready) {
+               /* Any register was not ready,
+                * fall back to slow read with S_REGRDY polling */
+               return ERROR_TIMEOUT_REACHED;
+       }
+
+       LOG_TARGET_DEBUG(target, "read %u 32-bit registers", wi);
+
+       unsigned int ri = 0; /* read index from r_vals array */
+       for (reg_id = 0; reg_id < num_regs; reg_id++) {
+               struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id];
+               if (!r->exist)
+                       continue;       /* skip non existent registers */
+
+               r->dirty = false;
+
+               unsigned int reg32_id;
+               uint32_t offset;
+               if (armv7m_map_reg_packing(reg_id, &reg32_id, &offset)) {
+                       /* Unpack a partial register from 32-bit container register */
+                       struct reg *r32 = &armv7m->arm.core_cache->reg_list[reg32_id];
+
+                       /* The container register ought to precede all regs unpacked
+                        * from it in the reg_list. So the value should be ready
+                        * to unpack */
+                       assert(r32->valid);
+                       buf_cpy(r32->value + offset, r->value, r->size);
+
+               } else {
+                       assert(r->size == 32 || r->size == 64);
+                       buf_set_u32(r->value, 0, 32, r_vals[ri++]);
+
+                       if (r->size == 64) {
+                               assert(reg_id >= ARMV7M_FPU_FIRST_REG && reg_id <= ARMV7M_FPU_LAST_REG);
+                               /* the odd part of FP register (S1, S3...) */
+                               buf_set_u32(r->value + 4, 0, 32, r_vals[ri++]);
+                       }
+               }
+               r->valid = true;
+       }
+       assert(ri == wi);
+
+       return retval;
+}
+
 static int cortex_m_store_core_reg_u32(struct target *target,
                uint32_t regsel, uint32_t value)
 {
+       struct cortex_m_common *cortex_m = target_to_cm(target);
        struct armv7m_common *armv7m = target_to_armv7m(target);
        int retval;
        uint32_t dcrdr;
+       int64_t then;
 
        /* because the DCB_DCRDR is used for the emulated dcc channel
         * we have to save/restore the DCB_DCRDR when used */
@@ -170,10 +379,25 @@ static int cortex_m_store_core_reg_u32(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
-       retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WNR);
+       retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WNR);
        if (retval != ERROR_OK)
                return retval;
 
+       /* check if value is written into register */
+       then = timeval_ms();
+       while (1) {
+               retval = cortex_m_read_dhcsr_atomic_sticky(target);
+               if (retval != ERROR_OK)
+                       return retval;
+               if (cortex_m->dcb_dhcsr & S_REGRDY)
+                       break;
+               if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) {
+                       LOG_TARGET_ERROR(target, "Timeout waiting for DCRDR transfer ready");
+                       return ERROR_TIMEOUT_REACHED;
+               }
+               keep_alive();
+       }
+
        if (target->dbg_msg_enabled) {
                /* restore DCB_DCRDR - this needs to be in a separate
                 * transaction otherwise the emulated DCC channel breaks */
@@ -293,7 +517,7 @@ static int cortex_m_clear_halt(struct target *target)
        retval = mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_DFSR, cortex_m->nvic_dfsr);
        if (retval != ERROR_OK)
                return retval;
-       LOG_DEBUG(" NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr);
+       LOG_TARGET_DEBUG(target, "NVIC_DFSR 0x%" PRIx32 "", cortex_m->nvic_dfsr);
 
        return ERROR_OK;
 }
@@ -315,7 +539,7 @@ static int cortex_m_single_step_core(struct target *target)
        retval = cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
        if (retval != ERROR_OK)
                return retval;
-       LOG_DEBUG(" ");
+       LOG_TARGET_DEBUG(target, "single step");
 
        /* restore dhcsr reg */
        cortex_m_clear_halt(target);
@@ -355,18 +579,19 @@ static int cortex_m_endreset_event(struct target *target)
        retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DEMCR, &dcb_demcr);
        if (retval != ERROR_OK)
                return retval;
-       LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr);
+       LOG_TARGET_DEBUG(target, "DCB_DEMCR = 0x%8.8" PRIx32 "", dcb_demcr);
 
        /* this register is used for emulated dcc channel */
        retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRDR, 0);
        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;
@@ -393,7 +618,7 @@ static int cortex_m_endreset_event(struct target *target)
        /* Enable FPB */
        retval = cortex_m_enable_fpb(target);
        if (retval != ERROR_OK) {
-               LOG_ERROR("Failed to enable the FPB");
+               LOG_TARGET_ERROR(target, "Failed to enable the FPB");
                return retval;
        }
 
@@ -428,7 +653,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;
 }
@@ -528,7 +755,7 @@ static int cortex_m_examine_exception_reason(struct target *target)
        }
        retval = dap_run(swjdp);
        if (retval == ERROR_OK)
-               LOG_DEBUG("%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32
+               LOG_TARGET_DEBUG(target, "%s SHCSR 0x%" PRIx32 ", SR 0x%" PRIx32
                        ", CFSR 0x%" PRIx32 ", AR 0x%" PRIx32,
                        armv7m_exception_string(armv7m->exception_number),
                        shcsr, except_sr, cfsr, except_ar);
@@ -537,7 +764,6 @@ static int cortex_m_examine_exception_reason(struct target *target)
 
 static int cortex_m_debug_entry(struct target *target)
 {
-       int i;
        uint32_t xPSR;
        int retval;
        struct cortex_m_common *cortex_m = target_to_cm(target);
@@ -545,14 +771,15 @@ static int cortex_m_debug_entry(struct target *target)
        struct arm *arm = &armv7m->arm;
        struct reg *r;
 
-       LOG_DEBUG(" ");
+       LOG_TARGET_DEBUG(target, " ");
 
        /* 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;
 
@@ -572,16 +799,21 @@ static int cortex_m_debug_entry(struct target *target)
                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->exist && !r->valid)
-                       arm->read_core_reg(target, r, i, ARM_MODE_ANY);
+       /* Load all registers to arm.core_cache */
+       if (!cortex_m->slow_register_read) {
+               retval = cortex_m_fast_read_all_regs(target);
+               if (retval == ERROR_TIMEOUT_REACHED) {
+                       cortex_m->slow_register_read = true;
+                       LOG_TARGET_DEBUG(target, "Switched to slow register read");
+               }
        }
 
+       if (cortex_m->slow_register_read)
+               retval = cortex_m_slow_read_all_regs(target);
+
+       if (retval != ERROR_OK)
+               return retval;
+
        r = arm->cpsr;
        xPSR = buf_get_u32(r->value, 0, 32);
 
@@ -612,7 +844,8 @@ 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 ", cpu in %s state, target->state: %s",
+       LOG_TARGET_DEBUG(target, "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",
@@ -636,7 +869,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;
@@ -646,8 +879,7 @@ static int cortex_m_poll(struct target *target)
         * section B1.5.15 "Unrecoverable exception cases".
         */
        if (cortex_m->dcb_dhcsr & S_LOCKUP) {
-               LOG_ERROR("%s -- clearing lockup after double fault",
-                       target_name(target));
+               LOG_TARGET_ERROR(target, "clearing lockup after double fault");
                cortex_m_write_debug_halt_mask(target, C_HALT, 0);
                target->debug_reason = DBG_REASON_DBGRQ;
 
@@ -657,15 +889,16 @@ 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) {
+       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));
+                       LOG_TARGET_INFO(target, "external reset detected");
                }
                return ERROR_OK;
        }
@@ -674,7 +907,7 @@ static int cortex_m_poll(struct target *target)
                /* Cannot switch context while running so endreset is
                 * called with target->state == TARGET_RESET
                 */
-               LOG_DEBUG("Exit from reset with dcb_dhcsr 0x%" PRIx32,
+               LOG_TARGET_DEBUG(target, "Exit from reset with dcb_dhcsr 0x%" PRIx32,
                        cortex_m->dcb_dhcsr);
                retval = cortex_m_endreset_event(target);
                if (retval != ERROR_OK) {
@@ -699,7 +932,6 @@ static int cortex_m_poll(struct target *target)
                        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                }
                if (prev_target_state == TARGET_DEBUG_RUNNING) {
-                       LOG_DEBUG(" ");
                        retval = cortex_m_debug_entry(target);
                        if (retval != ERROR_OK)
                                return retval;
@@ -709,7 +941,12 @@ static int cortex_m_poll(struct target *target)
        }
 
        if (target->state == TARGET_UNKNOWN) {
-               /* check if processor is retiring instructions or sleeping */
+               /* 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;
@@ -722,7 +959,7 @@ static int cortex_m_poll(struct target *target)
                register_cache_invalidate(armv7m->arm.core_cache);
 
                target->state = TARGET_RUNNING;
-               LOG_WARNING("%s: external resume detected", target_name(target));
+               LOG_TARGET_WARNING(target, "external resume detected");
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
                retval = ERROR_OK;
        }
@@ -735,20 +972,19 @@ static int cortex_m_poll(struct target *target)
 
 static int cortex_m_halt(struct target *target)
 {
-       LOG_DEBUG("target->state: %s",
-               target_state_name(target));
+       LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target));
 
        if (target->state == TARGET_HALTED) {
-               LOG_DEBUG("target was already halted");
+               LOG_TARGET_DEBUG(target, "target was already halted");
                return ERROR_OK;
        }
 
        if (target->state == TARGET_UNKNOWN)
-               LOG_WARNING("target was in unknown state when halt was requested");
+               LOG_TARGET_WARNING(target, "target was in unknown state when halt was requested");
 
        if (target->state == TARGET_RESET) {
                if ((jtag_get_reset_config() & RESET_SRST_PULLS_TRST) && jtag_get_srst()) {
-                       LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
+                       LOG_TARGET_ERROR(target, "can't request a halt while in reset if nSRST pulls nTRST");
                        return ERROR_TARGET_FAILURE;
                } else {
                        /* we came here in a reset_halt or reset_init sequence
@@ -776,17 +1012,16 @@ 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;
 
        /* 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_DEBUG("soft_reset_halt is discouraged, please use 'reset halt' instead.");
+       LOG_TARGET_DEBUG(target, "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");
+               LOG_TARGET_ERROR(target, "VECTRESET is not supported on this Cortex-M core");
                return ERROR_FAIL;
        }
 
@@ -812,25 +1047,24 @@ 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_TARGET_DEBUG(target, "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);
+                       } else {
+                               LOG_TARGET_DEBUG(target, "waiting for system reset-halt, "
+                                       "DHCSR 0x%08" PRIx32 ", %d ms",
+                                       cortex_m->dcb_dhcsr, timeout);
+                       }
                }
                timeout++;
                alive_sleep(1);
@@ -845,7 +1079,7 @@ void cortex_m_enable_breakpoints(struct target *target)
 
        /* set any pending breakpoints */
        while (breakpoint) {
-               if (!breakpoint->set)
+               if (!breakpoint->is_set)
                        cortex_m_set_breakpoint(target, breakpoint);
                breakpoint = breakpoint->next;
        }
@@ -860,7 +1094,7 @@ static int cortex_m_resume(struct target *target, int current,
        struct reg *r;
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_WARNING(target, "target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -924,7 +1158,7 @@ static int cortex_m_resume(struct target *target, int current,
                /* Single step past breakpoint at current address */
                breakpoint = breakpoint_find(target, resume_pc);
                if (breakpoint) {
-                       LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
+                       LOG_TARGET_DEBUG(target, "unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
                                breakpoint->address,
                                breakpoint->unique_id);
                        cortex_m_unset_breakpoint(target, breakpoint);
@@ -945,11 +1179,11 @@ static int cortex_m_resume(struct target *target, int current,
        if (!debug_execution) {
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-               LOG_DEBUG("target resumed at 0x%" PRIx32 "", resume_pc);
+               LOG_TARGET_DEBUG(target, "target resumed at 0x%" PRIx32 "", resume_pc);
        } else {
                target->state = TARGET_DEBUG_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
-               LOG_DEBUG("target debug resumed at 0x%" PRIx32 "", resume_pc);
+               LOG_TARGET_DEBUG(target, "target debug resumed at 0x%" PRIx32 "", resume_pc);
        }
 
        return ERROR_OK;
@@ -968,7 +1202,7 @@ static int cortex_m_step(struct target *target, int current,
        bool isr_timed_out = false;
 
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_WARNING(target, "target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1041,7 +1275,7 @@ static int cortex_m_step(struct target *target, int current,
                         *
                         */
                        if ((pc_value & 0x02) && breakpoint_find(target, pc_value & ~0x03)) {
-                               LOG_DEBUG("Stepping over next instruction with interrupts disabled");
+                               LOG_TARGET_DEBUG(target, "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 if appropriate */
@@ -1072,16 +1306,14 @@ static int cortex_m_step(struct target *target, int current,
                                        cortex_m_set_maskints_for_halt(target);
                                } else {
                                        /* Start the core */
-                                       LOG_DEBUG("Starting core to serve pending interrupts");
+                                       LOG_TARGET_DEBUG(target, "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;
@@ -1098,7 +1330,7 @@ static int cortex_m_step(struct target *target, int current,
                                        }
 
                                        if (isr_timed_out) {
-                                               LOG_DEBUG("Interrupt handlers didn't complete within time, "
+                                               LOG_TARGET_DEBUG(target, "Interrupt handlers didn't complete within time, "
                                                        "leaving target running");
                                        } else {
                                                /* Step over next instruction with interrupts disabled */
@@ -1116,7 +1348,7 @@ static int cortex_m_step(struct target *target, int current,
                }
        }
 
-       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;
 
@@ -1133,7 +1365,7 @@ static int cortex_m_step(struct target *target, int current,
                return ERROR_OK;
        }
 
-       LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
+       LOG_TARGET_DEBUG(target, "target stepped dcb_dhcsr = 0x%" PRIx32
                " nvic_icsr = 0x%" PRIx32,
                cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
 
@@ -1142,7 +1374,7 @@ static int cortex_m_step(struct target *target, int current,
                return retval;
        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
 
-       LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
+       LOG_TARGET_DEBUG(target, "target stepped dcb_dhcsr = 0x%" PRIx32
                " nvic_icsr = 0x%" PRIx32,
                cortex_m->dcb_dhcsr, cortex_m->nvic_icsr);
 
@@ -1155,7 +1387,7 @@ static int cortex_m_assert_reset(struct target *target)
        struct armv7m_common *armv7m = &cortex_m->armv7m;
        enum cortex_m_soft_reset_config reset_config = cortex_m->soft_reset_config;
 
-       LOG_DEBUG("target->state: %s",
+       LOG_TARGET_DEBUG(target, "target->state: %s",
                target_state_name(target));
 
        enum reset_types jtag_reset_config = jtag_get_reset_config();
@@ -1179,10 +1411,10 @@ static int cortex_m_assert_reset(struct target *target)
                if (jtag_reset_config & RESET_HAS_SRST) {
                        adapter_assert_reset();
                        if (target->reset_halt)
-                               LOG_ERROR("Target not examined, will not halt after reset!");
+                               LOG_TARGET_ERROR(target, "Target not examined, will not halt after reset!");
                        return ERROR_OK;
                } else {
-                       LOG_ERROR("Target not examined, reset NOT asserted!");
+                       LOG_TARGET_ERROR(target, "Target not examined, reset NOT asserted!");
                        return ERROR_FAIL;
                }
        }
@@ -1194,8 +1426,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))
@@ -1229,7 +1461,7 @@ static int cortex_m_assert_reset(struct target *target)
                retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR,
                                TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
                if (retval != ERROR_OK || retval2 != ERROR_OK)
-                       LOG_INFO("AP write error, reset will not halt");
+                       LOG_TARGET_INFO(target, "AP write error, reset will not halt");
        }
 
        if (jtag_reset_config & RESET_HAS_SRST) {
@@ -1249,15 +1481,15 @@ static int cortex_m_assert_reset(struct target *target)
                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_TARGET_WARNING(target, "VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ instead.");
+                       LOG_TARGET_WARNING(target, "Set 'cortex_m reset_config sysresetreq'.");
                }
 
-               LOG_DEBUG("Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ)
+               LOG_TARGET_DEBUG(target, "Using Cortex-M %s", (reset_config == CORTEX_M_RESET_SYSRESETREQ)
                        ? "SYSRESETREQ" : "VECTRESET");
 
                if (reset_config == CORTEX_M_RESET_VECTRESET) {
-                       LOG_WARNING("Only resetting the Cortex-M core, use a reset-init event "
+                       LOG_TARGET_WARNING(target, "Only resetting the Cortex-M core, use a reset-init event "
                                "handler to reset any peripherals or configure hardware srst support.");
                }
 
@@ -1266,11 +1498,11 @@ static int cortex_m_assert_reset(struct target *target)
                                AIRCR_VECTKEY | ((reset_config == CORTEX_M_RESET_SYSRESETREQ)
                                ? AIRCR_SYSRESETREQ : AIRCR_VECTRESET));
                if (retval3 != ERROR_OK)
-                       LOG_DEBUG("Ignoring AP write error right after reset");
+                       LOG_TARGET_DEBUG(target, "Ignoring AP write error right after reset");
 
                retval3 = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
                if (retval3 != ERROR_OK) {
-                       LOG_ERROR("DP initialisation failed");
+                       LOG_TARGET_ERROR(target, "DP initialisation failed");
                        /* The error return value must not be propagated in this case.
                         * SYSRESETREQ or VECTRESET have been possibly triggered
                         * so reset processing should continue */
@@ -1306,7 +1538,7 @@ static int cortex_m_deassert_reset(struct target *target)
 {
        struct armv7m_common *armv7m = &target_to_cm(target)->armv7m;
 
-       LOG_DEBUG("target->state: %s",
+       LOG_TARGET_DEBUG(target, "target->state: %s",
                target_state_name(target));
 
        /* deassert reset lines */
@@ -1320,7 +1552,7 @@ static int cortex_m_deassert_reset(struct target *target)
 
                int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
                if (retval != ERROR_OK) {
-                       LOG_ERROR("DP initialisation failed");
+                       LOG_TARGET_ERROR(target, "DP initialisation failed");
                        return retval;
                }
        }
@@ -1335,8 +1567,8 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
        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) {
-               LOG_WARNING("breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id);
+       if (breakpoint->is_set) {
+               LOG_TARGET_WARNING(target, "breakpoint (BPID: %" PRIu32 ") already set", breakpoint->unique_id);
                return ERROR_OK;
        }
 
@@ -1345,35 +1577,36 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                while (comparator_list[fp_num].used && (fp_num < cortex_m->fp_num_code))
                        fp_num++;
                if (fp_num >= cortex_m->fp_num_code) {
-                       LOG_ERROR("Can not find free FPB Comparator!");
+                       LOG_TARGET_ERROR(target, "Can not find free FPB Comparator!");
                        return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
-               breakpoint->set = fp_num + 1;
+               breakpoint_hw_set(breakpoint, fp_num);
                fpcr_value = breakpoint->address | 1;
                if (cortex_m->fp_rev == 0) {
                        if (breakpoint->address > 0x1FFFFFFF) {
-                               LOG_ERROR("Cortex-M Flash Patch Breakpoint rev.1 cannot handle HW breakpoint above address 0x1FFFFFFE");
+                               LOG_TARGET_ERROR(target, "Cortex-M Flash Patch Breakpoint rev.1 "
+                                               "cannot handle HW breakpoint above address 0x1FFFFFFE");
                                return ERROR_FAIL;
                        }
                        uint32_t hilo;
                        hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW;
                        fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1;
                } else if (cortex_m->fp_rev > 1) {
-                       LOG_ERROR("Unhandled Cortex-M Flash Patch Breakpoint architecture revision");
+                       LOG_TARGET_ERROR(target, "Unhandled Cortex-M Flash Patch Breakpoint architecture revision");
                        return ERROR_FAIL;
                }
                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);
-               LOG_DEBUG("fpc_num %i fpcr_value 0x%" PRIx32 "",
+               LOG_TARGET_DEBUG(target, "fpc_num %i fpcr_value 0x%" PRIx32 "",
                        fp_num,
                        comparator_list[fp_num].fpcr_value);
                if (!cortex_m->fpb_enabled) {
-                       LOG_DEBUG("FPB wasn't enabled, do it now");
+                       LOG_TARGET_DEBUG(target, "FPB wasn't enabled, do it now");
                        retval = cortex_m_enable_fpb(target);
                        if (retval != ERROR_OK) {
-                               LOG_ERROR("Failed to enable the FPB");
+                               LOG_TARGET_ERROR(target, "Failed to enable the FPB");
                                return retval;
                        }
 
@@ -1399,15 +1632,15 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint
                                code);
                if (retval != ERROR_OK)
                        return retval;
-               breakpoint->set = true;
+               breakpoint->is_set = true;
        }
 
-       LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)",
+       LOG_TARGET_DEBUG(target, "BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (n=%u)",
                breakpoint->unique_id,
                (int)(breakpoint->type),
                breakpoint->address,
                breakpoint->length,
-               breakpoint->set);
+               (breakpoint->type == BKPT_SOFT) ? 0 : breakpoint->number);
 
        return ERROR_OK;
 }
@@ -1418,22 +1651,22 @@ 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 <= 0) {
-               LOG_WARNING("breakpoint not set");
+       if (!breakpoint->is_set) {
+               LOG_TARGET_WARNING(target, "breakpoint not set");
                return ERROR_OK;
        }
 
-       LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)",
+       LOG_TARGET_DEBUG(target, "BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (n=%u)",
                breakpoint->unique_id,
                (int)(breakpoint->type),
                breakpoint->address,
                breakpoint->length,
-               breakpoint->set);
+               (breakpoint->type == BKPT_SOFT) ? 0 : breakpoint->number);
 
        if (breakpoint->type == BKPT_HARD) {
-               unsigned int fp_num = breakpoint->set - 1;
+               unsigned int fp_num = breakpoint->number;
                if (fp_num >= cortex_m->fp_num_code) {
-                       LOG_DEBUG("Invalid FP Comparator number in breakpoint");
+                       LOG_TARGET_DEBUG(target, "Invalid FP Comparator number in breakpoint");
                        return ERROR_OK;
                }
                comparator_list[fp_num].used = false;
@@ -1448,7 +1681,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
                if (retval != ERROR_OK)
                        return retval;
        }
-       breakpoint->set = false;
+       breakpoint->is_set = false;
 
        return ERROR_OK;
 }
@@ -1456,12 +1689,12 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi
 int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
        if (breakpoint->length == 3) {
-               LOG_DEBUG("Using a two byte breakpoint for 32bit Thumb-2 request");
+               LOG_TARGET_DEBUG(target, "Using a two byte breakpoint for 32bit Thumb-2 request");
                breakpoint->length = 2;
        }
 
        if ((breakpoint->length != 2)) {
-               LOG_INFO("only breakpoints of two bytes length supported");
+               LOG_TARGET_INFO(target, "only breakpoints of two bytes length supported");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
@@ -1470,7 +1703,7 @@ int cortex_m_add_breakpoint(struct target *target, struct breakpoint *breakpoint
 
 int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
-       if (!breakpoint->set)
+       if (!breakpoint->is_set)
                return ERROR_OK;
 
        return cortex_m_unset_breakpoint(target, breakpoint);
@@ -1493,11 +1726,11 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat
                comparator++, dwt_num++)
                continue;
        if (dwt_num >= cortex_m->dwt_num_comp) {
-               LOG_ERROR("Can not find free DWT Comparator");
+               LOG_TARGET_ERROR(target, "Can not find free DWT Comparator");
                return ERROR_FAIL;
        }
        comparator->used = true;
-       watchpoint->set = dwt_num + 1;
+       watchpoint_set(watchpoint, dwt_num);
 
        comparator->comp = watchpoint->address;
        target_write_u32(target, comparator->dwt_comparator_address + 0,
@@ -1551,7 +1784,7 @@ static int cortex_m_set_watchpoint(struct target *target, struct watchpoint *wat
        target_write_u32(target, comparator->dwt_comparator_address + 8,
                comparator->function);
 
-       LOG_DEBUG("Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
+       LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%d 0x%08x 0x%x 0x%05x",
                watchpoint->unique_id, dwt_num,
                (unsigned) comparator->comp,
                (unsigned) comparator->mask,
@@ -1564,20 +1797,20 @@ static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *w
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct cortex_m_dwt_comparator *comparator;
 
-       if (watchpoint->set <= 0) {
-               LOG_WARNING("watchpoint (wpid: %d) not set",
+       if (!watchpoint->is_set) {
+               LOG_TARGET_WARNING(target, "watchpoint (wpid: %d) not set",
                        watchpoint->unique_id);
                return ERROR_OK;
        }
 
-       unsigned int dwt_num = watchpoint->set - 1;
+       unsigned int dwt_num = watchpoint->number;
 
-       LOG_DEBUG("Watchpoint (ID %d) DWT%d address: 0x%08x clear",
+       LOG_TARGET_DEBUG(target, "Watchpoint (ID %d) DWT%u address: 0x%08x clear",
                watchpoint->unique_id, dwt_num,
                (unsigned) watchpoint->address);
 
        if (dwt_num >= cortex_m->dwt_num_comp) {
-               LOG_DEBUG("Invalid DWT Comparator number in watchpoint");
+               LOG_TARGET_DEBUG(target, "Invalid DWT Comparator number in watchpoint");
                return ERROR_OK;
        }
 
@@ -1587,7 +1820,7 @@ static int cortex_m_unset_watchpoint(struct target *target, struct watchpoint *w
        target_write_u32(target, comparator->dwt_comparator_address + 8,
                comparator->function);
 
-       watchpoint->set = false;
+       watchpoint->is_set = false;
 
        return ERROR_OK;
 }
@@ -1597,13 +1830,13 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
        struct cortex_m_common *cortex_m = target_to_cm(target);
 
        if (cortex_m->dwt_comp_available < 1) {
-               LOG_DEBUG("no comparators?");
+               LOG_TARGET_DEBUG(target, "no comparators?");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
        /* hardware doesn't support data value masking */
        if (watchpoint->mask != ~(uint32_t)0) {
-               LOG_DEBUG("watchpoint value masks not supported");
+               LOG_TARGET_DEBUG(target, "watchpoint value masks not supported");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
@@ -1615,11 +1848,11 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
                        break;
        }
        if (mask == 16) {
-               LOG_DEBUG("unsupported watchpoint length");
+               LOG_TARGET_DEBUG(target, "unsupported watchpoint length");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
        if (watchpoint->address & ((1 << mask) - 1)) {
-               LOG_DEBUG("watchpoint address is unaligned");
+               LOG_TARGET_DEBUG(target, "watchpoint address is unaligned");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
@@ -1631,12 +1864,12 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
         * the data, and another comparator (DATAVADDR0) matching addr.
         */
        if (watchpoint->value) {
-               LOG_DEBUG("data value watchpoint not YET supported");
+               LOG_TARGET_DEBUG(target, "data value watchpoint not YET supported");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
        cortex_m->dwt_comp_available--;
-       LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available);
+       LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available);
 
        return ERROR_OK;
 }
@@ -1647,15 +1880,15 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo
 
        /* REVISIT why check? DWT can be updated with core running ... */
        if (target->state != TARGET_HALTED) {
-               LOG_WARNING("target not halted");
+               LOG_TARGET_WARNING(target, "target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       if (watchpoint->set)
+       if (watchpoint->is_set)
                cortex_m_unset_watchpoint(target, watchpoint);
 
        cortex_m->dwt_comp_available++;
-       LOG_DEBUG("dwt_comp_available: %d", cortex_m->dwt_comp_available);
+       LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available);
 
        return ERROR_OK;
 }
@@ -1668,10 +1901,10 @@ int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watch
        struct cortex_m_common *cortex_m = target_to_cm(target);
 
        for (struct watchpoint *wp = target->watchpoints; wp; wp = wp->next) {
-               if (!wp->set)
+               if (!wp->is_set)
                        continue;
 
-               unsigned int dwt_num = wp->set - 1;
+               unsigned int dwt_num = wp->number;
                struct cortex_m_dwt_comparator *comparator = cortex_m->dwt_comparator_list + dwt_num;
 
                uint32_t dwt_function;
@@ -1695,7 +1928,7 @@ void cortex_m_enable_watchpoints(struct target *target)
 
        /* set any pending watchpoints */
        while (watchpoint) {
-               if (!watchpoint->set)
+               if (!watchpoint->is_set)
                        cortex_m_set_watchpoint(target, watchpoint);
                watchpoint = watchpoint->next;
        }
@@ -1740,6 +1973,10 @@ static int cortex_m_init_target(struct command_context *cmd_ctx,
 void cortex_m_deinit_target(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+
+       if (!armv7m->is_hla_target && armv7m->debug_ap)
+               dap_put_ap(armv7m->debug_ap);
 
        free(cortex_m->fp_comparator_list);
 
@@ -1760,18 +1997,18 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
 
        retval = target_read_u32(target, DWT_PCSR, &reg_value);
        if (retval != ERROR_OK) {
-               LOG_ERROR("Error while reading PCSR");
+               LOG_TARGET_ERROR(target, "Error while reading PCSR");
                return retval;
        }
        if (reg_value == 0) {
-               LOG_INFO("PCSR sampling not supported on this processor.");
+               LOG_TARGET_INFO(target, "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...");
+       LOG_TARGET_INFO(target, "Starting Cortex-M profiling. Sampling DWT_PCSR as fast as we can...");
 
        /* Make sure the target is running */
        target_poll(target);
@@ -1779,7 +2016,7 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
                retval = target_resume(target, 1, 0, 0, 0);
 
        if (retval != ERROR_OK) {
-               LOG_ERROR("Error while resuming target");
+               LOG_TARGET_ERROR(target, "Error while resuming target");
                return retval;
        }
 
@@ -1800,14 +2037,14 @@ int cortex_m_profiling(struct target *target, uint32_t *samples,
                }
 
                if (retval != ERROR_OK) {
-                       LOG_ERROR("Error while reading PCSR");
+                       LOG_TARGET_ERROR(target, "Error while reading PCSR");
                        return retval;
                }
 
 
                gettimeofday(&now, NULL);
                if (sample_count >= max_num_samples || timeval_compare(&now, &timeout) > 0) {
-                       LOG_INFO("Profiling completed. %" PRIu32 " samples.", sample_count);
+                       LOG_TARGET_INFO(target, "Profiling completed. %" PRIu32 " samples.", sample_count);
                        break;
                }
        }
@@ -1918,14 +2155,14 @@ static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target
        int reg;
 
        target_read_u32(target, DWT_CTRL, &dwtcr);
-       LOG_DEBUG("DWT_CTRL: 0x%" PRIx32, dwtcr);
+       LOG_TARGET_DEBUG(target, "DWT_CTRL: 0x%" PRIx32, dwtcr);
        if (!dwtcr) {
-               LOG_DEBUG("no DWT");
+               LOG_TARGET_DEBUG(target, "no DWT");
                return;
        }
 
        target_read_u32(target, DWT_DEVARCH, &cm->dwt_devarch);
-       LOG_DEBUG("DWT_DEVARCH: 0x%" PRIx32, cm->dwt_devarch);
+       LOG_TARGET_DEBUG(target, "DWT_DEVARCH: 0x%" PRIx32, cm->dwt_devarch);
 
        cm->dwt_num_comp = (dwtcr >> 28) & 0xF;
        cm->dwt_comp_available = cm->dwt_num_comp;
@@ -1934,7 +2171,7 @@ static void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target
        if (!cm->dwt_comparator_list) {
 fail0:
                cm->dwt_num_comp = 0;
-               LOG_ERROR("out of mem");
+               LOG_TARGET_ERROR(target, "out of mem");
                return;
        }
 
@@ -1972,7 +2209,7 @@ fail1:
        *register_get_last_cache_p(&target->reg_cache) = cache;
        cm->dwt_cache = cache;
 
-       LOG_DEBUG("DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s",
+       LOG_TARGET_DEBUG(target, "DWT dwtcr 0x%" PRIx32 ", comp %d, watch%s",
                dwtcr, cm->dwt_num_comp,
                (dwtcr & (0xf << 24)) ? " only" : "/trigger");
 
@@ -2018,10 +2255,10 @@ static void cortex_m_dwt_free(struct target *target)
 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)
+       if (dap_find_get_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK)
                return ERROR_OK;
 
-       return dap_find_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap);
+       return dap_find_get_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap);
 }
 
 int cortex_m_examine(struct target *target)
@@ -2035,18 +2272,26 @@ int cortex_m_examine(struct target *target)
        /* hla_target shares the examine handler but does not support
         * all its calls */
        if (!armv7m->is_hla_target) {
+               if (armv7m->debug_ap) {
+                       dap_put_ap(armv7m->debug_ap);
+                       armv7m->debug_ap = NULL;
+               }
+
                if (cortex_m->apsel == DP_APSEL_INVALID) {
                        /* Search for the MEM-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");
+                               LOG_TARGET_ERROR(target, "Could not find MEM-AP to control the core");
                                return retval;
                        }
                } else {
-                       armv7m->debug_ap = dap_ap(swjdp, cortex_m->apsel);
+                       armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel);
+                       if (!armv7m->debug_ap) {
+                               LOG_ERROR("Cannot get AP");
+                               return ERROR_FAIL;
+                       }
                }
 
-               /* Leave (only) generic DAP stuff for debugport_init(); */
                armv7m->debug_ap->memaccess_tck = 8;
 
                retval = mem_ap_init(armv7m->debug_ap);
@@ -2073,14 +2318,13 @@ int cortex_m_examine(struct target *target)
                }
 
                if (!cortex_m->core_info) {
-                       LOG_ERROR("Cortex-M PARTNO 0x%x is unrecognized", core_partno);
+                       LOG_TARGET_ERROR(target, "Cortex-M PARTNO 0x%x is unrecognized", core_partno);
                        return ERROR_FAIL;
                }
 
                armv7m->arm.arch = cortex_m->core_info->arch;
 
-               LOG_INFO("%s: %s r%" PRId8 "p%" PRId8 " processor detected",
-                               target_name(target),
+               LOG_TARGET_INFO(target, "%s r%" PRId8 "p%" PRId8 " processor detected",
                                cortex_m->core_info->name,
                                (uint8_t)((cpuid >> 20) & 0xf),
                                (uint8_t)((cpuid >> 0) & 0xf));
@@ -2091,11 +2335,11 @@ int cortex_m_examine(struct target *target)
                        rev = (cpuid >> 20) & 0xf;
                        patch = (cpuid >> 0) & 0xf;
                        if ((rev == 0) && (patch < 2)) {
-                               LOG_WARNING("Silicon bug: single stepping may enter pending exception handler!");
+                               LOG_TARGET_WARNING(target, "Silicon bug: single stepping may enter pending exception handler!");
                                cortex_m->maskints_erratum = true;
                        }
                }
-               LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
+               LOG_TARGET_DEBUG(target, "cpuid: 0x%8.8" PRIx32 "", cpuid);
 
                if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) {
                        target_read_u32(target, MVFR0, &mvfr0);
@@ -2103,7 +2347,7 @@ int cortex_m_examine(struct target *target)
 
                        /* test for floating point feature on Cortex-M4 */
                        if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
-                               LOG_DEBUG("%s floating point feature FPv4_SP found", cortex_m->core_info->name);
+                               LOG_TARGET_DEBUG(target, "%s floating point feature FPv4_SP found", cortex_m->core_info->name);
                                armv7m->fp_feature = FPV4_SP;
                        }
                } else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) {
@@ -2112,10 +2356,10 @@ int cortex_m_examine(struct target *target)
 
                        /* test for floating point features on Cortex-M7 */
                        if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) {
-                               LOG_DEBUG("%s floating point feature FPv5_SP found", cortex_m->core_info->name);
+                               LOG_TARGET_DEBUG(target, "%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("%s floating point feature FPv5_DP found", cortex_m->core_info->name);
+                               LOG_TARGET_DEBUG(target, "%s floating point feature FPv5_DP found", cortex_m->core_info->name);
                                armv7m->fp_feature = FPV5_DP;
                        }
                }
@@ -2139,11 +2383,13 @@ int cortex_m_examine(struct target *target)
                                armv7m->debug_ap->tar_autoincr_block = (1 << 12);
                }
 
-               /* Enable debug requests */
                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));
@@ -2183,7 +2429,7 @@ int cortex_m_examine(struct target *target)
                        /* make sure we clear any breakpoints enabled on the target */
                        target_write_u32(target, cortex_m->fp_comparator_list[i].fpcr_address, 0);
                }
-               LOG_DEBUG("FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i",
+               LOG_TARGET_DEBUG(target, "FPB fpcr 0x%" PRIx32 ", numcode %i, numlit %i",
                        fpcr,
                        cortex_m->fp_num_code,
                        cortex_m->fp_num_lit);
@@ -2193,8 +2439,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: target has %d breakpoints, %d watchpoints",
-                       target_name(target),
+               LOG_TARGET_INFO(target, "target has %d breakpoints, %d watchpoints",
                        cortex_m->fp_num_code,
                        cortex_m->dwt_num_comp);
        }
@@ -2217,7 +2462,7 @@ static int cortex_m_dcc_read(struct target *target, uint8_t *value, uint8_t *ctr
        *ctrl = (uint8_t)dcrdr;
        *value = (uint8_t)(dcrdr >> 8);
 
-       LOG_DEBUG("data 0x%x ctrl 0x%x", *value, *ctrl);
+       LOG_TARGET_DEBUG(target, "data 0x%x ctrl 0x%x", *value, *ctrl);
 
        /* write ack back to software dcc register
         * signify we have read data */
@@ -2324,7 +2569,7 @@ 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));
        if (!cortex_m) {
-               LOG_ERROR("No memory creating target");
+               LOG_TARGET_ERROR(target, "No memory creating target");
                return ERROR_FAIL;
        }
 
@@ -2341,7 +2586,7 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
 static int cortex_m_verify_pointer(struct command_invocation *cmd,
        struct cortex_m_common *cm)
 {
-       if (cm->common_magic != CORTEX_M_COMMON_MAGIC) {
+       if (!is_cortex_m_with_dap_access(cm)) {
                command_print(cmd, "target is not a Cortex-M");
                return ERROR_TARGET_INVALID;
        }
@@ -2381,7 +2626,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
                return retval;
 
        if (!target_was_examined(target)) {
-               LOG_ERROR("Target not examined yet");
+               LOG_TARGET_ERROR(target, "Target not examined yet");
                return ERROR_FAIL;
        }
 
@@ -2410,7 +2655,7 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command)
                                break;
                        }
                        if (i == ARRAY_SIZE(vec_ids)) {
-                               LOG_ERROR("No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]);
+                               LOG_TARGET_ERROR(target, "No CM3 vector '%s'", CMD_ARGV[CMD_ARGC]);
                                return ERROR_COMMAND_SYNTAX_ERROR;
                        }
                }
@@ -2500,7 +2745,7 @@ COMMAND_HANDLER(handle_cortex_m_reset_config_command)
                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!");
+                               LOG_TARGET_WARNING(target, "VECTRESET is not supported on your Cortex-M core!");
                        else
                                cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;