PIC32: add flash algorithm support
[fw/openocd] / src / target / cortex_m3.c
index edf9b6f09cc134c71b553a8aad201060837db401..d39d839c5371620bd2e6766f37a797650f7268d5 100644 (file)
 #include "arm_disassembler.h"
 #include "register.h"
 #include "arm_opcodes.h"
-
+#include "arm_semihosting.h"
 
 /* NOTE:  most of this should work fine for the Cortex-M1 and
  * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M.
+ * Some differences:  M0/M1 doesn't have FBP remapping or the
+ * DWT tracing/profiling support.  (So the cycle counter will
+ * not be usable; the other stuff isn't currently used here.)
  *
  * Although there are some workarounds for errata seen only in r0p0
  * silicon, such old parts are hard to find and thus not much tested
@@ -56,7 +59,7 @@ static void cortex_m3_enable_watchpoints(struct target *target);
 static int cortex_m3_store_core_reg_u32(struct target *target,
                enum armv7m_regtype type, uint32_t num, uint32_t value);
 
-static int cortexm3_dap_read_coreregister_u32(struct swjdp_common *swjdp,
+static int cortexm3_dap_read_coreregister_u32(struct adiv5_dap *swjdp,
                uint32_t *value, int regnum)
 {
        int retval;
@@ -67,17 +70,21 @@ static int cortexm3_dap_read_coreregister_u32(struct swjdp_common *swjdp,
 
        mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);
 
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
        /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */
        dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
-       dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
+       retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* mem_ap_read_u32(swjdp, DCB_DCRDR, value); */
        dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
-       dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+       retval = dap_queue_ap_read(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+       if (retval != ERROR_OK)
+               return retval;
 
-       retval = swjdp_transaction_endcheck(swjdp);
+       retval = dap_run(swjdp);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* restore DCB_DCRDR - this needs to be in a seperate
         * transaction otherwise the emulated DCC channel breaks */
@@ -87,7 +94,7 @@ static int cortexm3_dap_read_coreregister_u32(struct swjdp_common *swjdp,
        return retval;
 }
 
-static int cortexm3_dap_write_coreregister_u32(struct swjdp_common *swjdp,
+static int cortexm3_dap_write_coreregister_u32(struct adiv5_dap *swjdp,
                uint32_t value, int regnum)
 {
        int retval;
@@ -98,17 +105,17 @@ static int cortexm3_dap_write_coreregister_u32(struct swjdp_common *swjdp,
 
        mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr);
 
-       swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
        /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */
        dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
-       dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+       retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value);
+       // XXX check retval
 
        /* mem_ap_write_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR); */
        dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
-       dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
+       retval = dap_queue_ap_write(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR);
+       // XXX check retval
 
-       retval = swjdp_transaction_endcheck(swjdp);
+       retval = dap_run(swjdp);
 
        /* restore DCB_DCRDR - this needs to be in a seperate
         * transaction otherwise the emulated DCC channel breaks */
@@ -122,7 +129,7 @@ static int cortex_m3_write_debug_halt_mask(struct target *target,
                uint32_t mask_on, uint32_t mask_off)
 {
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
 
        /* mask off status bits */
        cortex_m3->dcb_dhcsr &= ~((0xFFFF << 16) | mask_off);
@@ -135,7 +142,7 @@ static int cortex_m3_write_debug_halt_mask(struct target *target,
 static int cortex_m3_clear_halt(struct target *target)
 {
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
 
        /* clear step if any */
        cortex_m3_write_debug_halt_mask(target, C_HALT, C_STEP);
@@ -153,7 +160,7 @@ static int cortex_m3_clear_halt(struct target *target)
 static int cortex_m3_single_step_core(struct target *target)
 {
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
        uint32_t dhcsr_save;
 
        /* backup dhcsr reg */
@@ -180,13 +187,15 @@ static int cortex_m3_single_step_core(struct target *target)
 static int cortex_m3_endreset_event(struct target *target)
 {
        int i;
+       int retval;
        uint32_t dcb_demcr;
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct armv7m_common *armv7m = &cortex_m3->armv7m;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
        struct cortex_m3_fp_comparator *fp_list = cortex_m3->fp_comparator_list;
        struct cortex_m3_dwt_comparator *dwt_list = cortex_m3->dwt_comparator_list;
 
-       /* FIXME handling of DEMCR clobbers vector_catch config ... */
+       /* REVISIT The four debug monitor bits are currently ignored... */
        mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &dcb_demcr);
        LOG_DEBUG("DCB_DEMCR = 0x%8.8" PRIx32 "",dcb_demcr);
 
@@ -201,21 +210,14 @@ static int cortex_m3_endreset_event(struct target *target)
        /* clear any interrupt masking */
        cortex_m3_write_debug_halt_mask(target, 0, C_MASKINTS);
 
-       /* Enable trace and DWT; trap hard and bus faults.
+       /* Enable features controlled by ITM and DWT blocks, and catch only
+        * the vectors we were told to pay attention to.
         *
-        * REVISIT why trap those two?  And why trash the vector_catch
-        * config, instead of preserving it?  Catching HARDERR and BUSERR
-        * will interfere with code that handles those itself...
+        * Target firmware is responsible for all fault handling policy
+        * choices *EXCEPT* explicitly scripted overrides like "vector_catch"
+        * or manual updates to the NVIC SHCSR and CCR registers.
         */
-       mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR);
-
-       /* Monitor bus faults as such (instead of as generic HARDERR), but
-        * leave memory management and usage faults disabled.
-        *
-        * REVISIT setting BUSFAULTENA interferes with code which relies
-        * on the default setting.  Why do it?
-        */
-       mem_ap_write_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA);
+       mem_ap_write_u32(swjdp, DCB_DEMCR, TRCENA | armv7m->demcr);
 
        /* Paranoia: evidently some (early?) chips don't preserve all the
         * debug state (including FBP, DWT, etc) across reset...
@@ -241,14 +243,16 @@ static int cortex_m3_endreset_event(struct target *target)
                target_write_u32(target, dwt_list[i].dwt_comparator_address + 8,
                                dwt_list[i].function);
        }
-       swjdp_transaction_endcheck(swjdp);
+       retval = dap_run(swjdp);
+       if (retval != ERROR_OK)
+               return retval;
 
        register_cache_invalidate(cortex_m3->armv7m.core_cache);
 
        /* make sure we have latest dhcsr flags */
        mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
 
-       return ERROR_OK;
+       return retval;
 }
 
 static int cortex_m3_examine_debug_reason(struct target *target)
@@ -282,7 +286,8 @@ static int cortex_m3_examine_exception_reason(struct target *target)
 {
        uint32_t shcsr, except_sr, cfsr = -1, except_ar = -1;
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
+       int retval;
 
        mem_ap_read_u32(swjdp, NVIC_SHCSR, &shcsr);
        switch (armv7m->exception_number)
@@ -320,12 +325,33 @@ static int cortex_m3_examine_exception_reason(struct target *target)
                        except_sr = 0;
                        break;
        }
-       swjdp_transaction_endcheck(swjdp);
-       LOG_DEBUG("%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);
-       return ERROR_OK;
+       retval = dap_run(swjdp);
+       if (retval == ERROR_OK)
+               LOG_DEBUG("%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);
+       return retval;
 }
 
+/* PSP is used in some thread modes */
+static const int armv7m_psp_reg_map[17] = {
+       ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+       ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+       ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+       ARMV7M_R12, ARMV7M_PSP, ARMV7M_R14, ARMV7M_PC,
+       ARMV7M_xPSR,
+};
+
+/* MSP is used in handler and some thread modes */
+static const int armv7m_msp_reg_map[17] = {
+       ARMV7M_R0, ARMV7M_R1, ARMV7M_R2, ARMV7M_R3,
+       ARMV7M_R4, ARMV7M_R5, ARMV7M_R6, ARMV7M_R7,
+       ARMV7M_R8, ARMV7M_R9, ARMV7M_R10, ARMV7M_R11,
+       ARMV7M_R12, ARMV7M_MSP, ARMV7M_R14, ARMV7M_PC,
+       ARMV7M_xPSR,
+};
+
 static int cortex_m3_debug_entry(struct target *target)
 {
        int i;
@@ -333,7 +359,8 @@ static int cortex_m3_debug_entry(struct target *target)
        int retval;
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
        struct armv7m_common *armv7m = &cortex_m3->armv7m;
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct arm *arm = &armv7m->arm;
+       struct adiv5_dap *swjdp = &armv7m->dap;
        struct reg *r;
 
        LOG_DEBUG(" ");
@@ -380,11 +407,27 @@ static int cortex_m3_debug_entry(struct target *target)
        {
                armv7m->core_mode = ARMV7M_MODE_HANDLER;
                armv7m->exception_number = (xPSR & 0x1FF);
+
+               arm->core_mode = ARM_MODE_HANDLER;
+               arm->map = armv7m_msp_reg_map;
        }
        else
        {
-               armv7m->core_mode = buf_get_u32(armv7m->core_cache
-                               ->reg_list[ARMV7M_CONTROL].value, 0, 1);
+               unsigned control = buf_get_u32(armv7m->core_cache
+                               ->reg_list[ARMV7M_CONTROL].value, 0, 2);
+
+               /* is this thread privileged? */
+               armv7m->core_mode = control & 1;
+               arm->core_mode = armv7m->core_mode
+                               ? ARM_MODE_USER_THREAD
+                               : ARM_MODE_THREAD;
+
+               /* which stack is it using? */
+               if (control & 2)
+                       arm->map = armv7m_psp_reg_map;
+               else
+                       arm->map = armv7m_msp_reg_map;
+
                armv7m->exception_number = 0;
        }
 
@@ -395,7 +438,7 @@ static int cortex_m3_debug_entry(struct target *target)
 
        LOG_DEBUG("entered debug state in core mode: %s at PC 0x%" PRIx32 ", target->state: %s",
                armv7m_mode_strings[armv7m->core_mode],
-               *(uint32_t*)(armv7m->core_cache->reg_list[15].value),
+               *(uint32_t*)(arm->pc->value),
                target_state_name(target));
 
        if (armv7m->post_debug_entry)
@@ -409,7 +452,7 @@ static int cortex_m3_poll(struct target *target)
        int retval;
        enum target_state prev_target_state = target->state;
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
 
        /* Read from Debug Halting Control and Status Register */
        retval = mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
@@ -419,6 +462,21 @@ static int cortex_m3_poll(struct target *target)
                return retval;
        }
 
+       /* Recover from lockup.  See ARMv7-M architecture spec,
+        * section B1.5.15 "Unrecoverable exception cases".
+        *
+        * REVISIT Is there a better way to report and handle this?
+        */
+       if (cortex_m3->dcb_dhcsr & S_LOCKUP) {
+               LOG_WARNING("%s -- clearing lockup after double fault",
+                               target_name(target));
+               cortex_m3_write_debug_halt_mask(target, C_HALT, 0);
+               target->debug_reason = DBG_REASON_DBGRQ;
+
+               /* refresh status bits */
+               mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
+       }
+
        if (cortex_m3->dcb_dhcsr & S_RESET_ST)
        {
                /* check if still in reset */
@@ -452,6 +510,9 @@ static int cortex_m3_poll(struct target *target)
                        if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK)
                                return retval;
 
+                       if (arm_semihosting(target, &retval) != 0)
+                               return retval;
+
                        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
                }
                if (prev_target_state == TARGET_DEBUG_RUNNING)
@@ -526,11 +587,11 @@ static int cortex_m3_halt(struct target *target)
 static int cortex_m3_soft_reset_halt(struct target *target)
 {
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
        uint32_t dcb_dhcsr = 0;
        int retval, timeout = 0;
 
-       /* Enter debug state on reset; see end_reset_event() */
+       /* Enter debug state on reset; restore DEMCR in endreset_event() */
        mem_ap_write_u32(swjdp, DCB_DEMCR,
                        TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
 
@@ -579,7 +640,7 @@ static void cortex_m3_enable_breakpoints(struct target *target)
        /* set any pending breakpoints */
        while (breakpoint)
        {
-               if (breakpoint->set == 0)
+               if (!breakpoint->set)
                        cortex_m3_set_breakpoint(target, breakpoint);
                breakpoint = breakpoint->next;
        }
@@ -633,7 +694,7 @@ static int cortex_m3_resume(struct target *target, int current,
        }
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
-       r = armv7m->core_cache->reg_list + 15;
+       r = armv7m->arm.pc;
        if (!current)
        {
                buf_set_u32(r->value, 0, 32, address);
@@ -641,6 +702,16 @@ static int cortex_m3_resume(struct target *target, int current,
                r->valid = true;
        }
 
+       /* if we halted last time due to a bkpt instruction
+        * then we have to manually step over it, otherwise
+        * the core will break again */
+
+       if (!breakpoint_find(target, buf_get_u32(r->value, 0, 32))
+                       && !debug_execution)
+       {
+               armv7m_maybe_skip_bkpt_inst(target, NULL);
+       }
+
        resume_pc = buf_get_u32(r->value, 0, 32);
 
        armv7m_restore_context(target);
@@ -690,9 +761,10 @@ static int cortex_m3_step(struct target *target, int current,
 {
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
        struct armv7m_common *armv7m = &cortex_m3->armv7m;
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
        struct breakpoint *breakpoint = NULL;
-       struct reg *pc = armv7m->core_cache->reg_list + 15;
+       struct reg *pc = armv7m->arm.pc;
+       bool bkpt_inst_found = false;
 
        if (target->state != TARGET_HALTED)
        {
@@ -712,14 +784,23 @@ static int cortex_m3_step(struct target *target, int current,
                        cortex_m3_unset_breakpoint(target, breakpoint);
        }
 
+       armv7m_maybe_skip_bkpt_inst(target, &bkpt_inst_found);
+
        target->debug_reason = DBG_REASON_SINGLESTEP;
 
        armv7m_restore_context(target);
 
        target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
 
-       /* set step and clear halt */
-       cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
+       /* if no bkpt instruction is found at pc then we can perform
+        * a normal step, otherwise we have to manually step over the bkpt
+        * instruction - as such simulate a step */
+       if (bkpt_inst_found == false)
+       {
+               /* set step and clear halt */
+               cortex_m3_write_debug_halt_mask(target, C_STEP, C_HALT);
+       }
+
        mem_ap_read_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr);
 
        /* registers are now invalid */
@@ -738,13 +819,14 @@ static int cortex_m3_step(struct target *target, int current,
        LOG_DEBUG("target stepped dcb_dhcsr = 0x%" PRIx32
                        " nvic_icsr = 0x%" PRIx32,
                        cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr);
+
        return ERROR_OK;
 }
 
 static int cortex_m3_assert_reset(struct target *target)
 {
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
        int assert_srst = 1;
 
        LOG_DEBUG("target->state: %s",
@@ -779,14 +861,15 @@ static int cortex_m3_assert_reset(struct target *target)
 
                /* clear C_HALT in dhcsr reg */
                cortex_m3_write_debug_halt_mask(target, 0, C_HALT);
-
-               /* Enter debug state on reset, cf. end_reset_event() */
-               mem_ap_write_u32(swjdp, DCB_DEMCR,
-                               TRCENA | VC_HARDERR | VC_BUSERR);
        }
        else
        {
-               /* Enter debug state on reset, cf. end_reset_event() */
+               /* Halt in debug on reset; endreset_event() restores DEMCR.
+                *
+                * REVISIT catching BUSERR presumably helps to defend against
+                * bad vector table entries.  Should this include MMERR or
+                * other flags too?
+                */
                mem_ap_write_atomic_u32(swjdp, DCB_DEMCR,
                                TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET);
        }
@@ -936,16 +1019,25 @@ cortex_m3_set_breakpoint(struct target *target, struct breakpoint *breakpoint)
        else if (breakpoint->type == BKPT_SOFT)
        {
                uint8_t code[4];
+
+               /* NOTE: on ARMv6-M and ARMv7-M, BKPT(0xab) is used for
+                * semihosting; don't use that.  Otherwise the BKPT
+                * parameter is arbitrary.
+                */
                buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
-               if ((retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr)) != ERROR_OK)
-               {
+               retval = target_read_memory(target,
+                               breakpoint->address & 0xFFFFFFFE,
+                               breakpoint->length, 1,
+                               breakpoint->orig_instr);
+               if (retval != ERROR_OK)
                        return retval;
-               }
-               if ((retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code)) != ERROR_OK)
-               {
+               retval = target_write_memory(target,
+                               breakpoint->address & 0xFFFFFFFE,
+                               breakpoint->length, 1,
+                               code);
+               if (retval != ERROR_OK)
                        return retval;
-               }
-               breakpoint->set = 0x11; /* Any nice value but 0 */
+               breakpoint->set = true;
        }
 
        LOG_DEBUG("BPID: %d, Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)",
@@ -1008,7 +1100,7 @@ cortex_m3_unset_breakpoint(struct target *target, struct breakpoint *breakpoint)
                        }
                }
        }
-       breakpoint->set = 0;
+       breakpoint->set = false;
 
        return ERROR_OK;
 }
@@ -1187,7 +1279,7 @@ cortex_m3_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)
        target_write_u32(target, comparator->dwt_comparator_address + 8,
                        comparator->function);
 
-       watchpoint->set = 0;
+       watchpoint->set = false;
 
        return ERROR_OK;
 }
@@ -1273,7 +1365,7 @@ static void cortex_m3_enable_watchpoints(struct target *target)
        /* set any pending watchpoints */
        while (watchpoint)
        {
-               if (watchpoint->set == 0)
+               if (!watchpoint->set)
                        cortex_m3_set_watchpoint(target, watchpoint);
                watchpoint = watchpoint->next;
        }
@@ -1284,7 +1376,7 @@ static int cortex_m3_load_core_reg_u32(struct target *target,
 {
        int retval;
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
 
        /* NOTE:  we "know" here that the register identifiers used
         * in the v7m header match the Cortex-M3 Debug Core Register
@@ -1348,7 +1440,7 @@ static int cortex_m3_store_core_reg_u32(struct target *target,
        int retval;
        uint32_t reg;
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
 
 #ifdef ARMV7_GDB_HACKS
        /* If the LR register is being modified, make sure it will put us
@@ -1426,7 +1518,7 @@ static int cortex_m3_read_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
        int retval = ERROR_INVALID_ARGUMENTS;
 
        /* cortex_m3 handles unaligned memory access */
@@ -1451,7 +1543,7 @@ static int cortex_m3_write_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
        int retval = ERROR_INVALID_ARGUMENTS;
 
        if (count && buffer) {
@@ -1632,7 +1724,7 @@ static int cortex_m3_examine(struct target *target)
        uint32_t cpuid, fpcr;
        int i;
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       struct swjdp_common *swjdp = &cortex_m3->armv7m.swjdp_info;
+       struct adiv5_dap *swjdp = &cortex_m3->armv7m.dap;
 
        if ((retval = ahbap_debugport_init(swjdp)) != ERROR_OK)
                return retval;
@@ -1647,7 +1739,8 @@ static int cortex_m3_examine(struct target *target)
                        return retval;
 
                if (((cpuid >> 4) & 0xc3f) == 0xc23)
-                       LOG_DEBUG("CORTEX-M3 processor detected");
+                       LOG_DEBUG("Cortex-M3 r%" PRId8 "p%" PRId8 " processor detected",
+                               (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
                LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
 
                /* NOTE: FPB and DWT are both optional. */
@@ -1680,7 +1773,7 @@ static int cortex_m3_examine(struct target *target)
        return ERROR_OK;
 }
 
-static int cortex_m3_dcc_read(struct swjdp_common *swjdp, uint8_t *value, uint8_t *ctrl)
+static int cortex_m3_dcc_read(struct adiv5_dap *swjdp, uint8_t *value, uint8_t *ctrl)
 {
        uint16_t dcrdr;
 
@@ -1705,7 +1798,7 @@ static int cortex_m3_target_request_data(struct target *target,
                uint32_t size, uint8_t *buffer)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
        uint8_t data;
        uint8_t ctrl;
        uint32_t i;
@@ -1725,7 +1818,7 @@ static int cortex_m3_handle_target_request(void *priv)
        if (!target_was_examined(target))
                return ERROR_OK;
        struct armv7m_common *armv7m = target_to_armv7m(target);
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
 
        if (!target->dbg_msg_enabled)
                return ERROR_OK;
@@ -1769,12 +1862,13 @@ static int cortex_m3_init_arch_info(struct target *target,
        cortex_m3->jtag_info.tap = tap;
        cortex_m3->jtag_info.scann_size = 4;
 
-       armv7m->swjdp_info.dp_select_value = -1;
-       armv7m->swjdp_info.ap_csw_value = -1;
-       armv7m->swjdp_info.ap_tar_value = -1;
-       armv7m->swjdp_info.jtag_info = &cortex_m3->jtag_info;
-       armv7m->swjdp_info.memaccess_tck = 8;
-       armv7m->swjdp_info.tar_autoincr_block = (1 << 12);      /* Cortex-M3 has 4096 bytes autoincrement range */
+       armv7m->arm.dap = &armv7m->dap;
+
+       /* Leave (only) generic DAP stuff for debugport_init(); */
+       armv7m->dap.jtag_info = &cortex_m3->jtag_info;
+       armv7m->dap.memaccess_tck = 8;
+       /* Cortex-M3 has 4096 bytes autoincrement range */
+       armv7m->dap.tar_autoincr_block = (1 << 12);
 
        /* register arch-specific functions */
        armv7m->examine_debug_reason = cortex_m3_examine_debug_reason;
@@ -1825,50 +1919,6 @@ static int cortex_m3_verify_pointer(struct command_context *cmd_ctx,
  * cortexm3_target structure, which is only used with CM3 targets.
  */
 
-/*
- * REVISIT Thumb2 disassembly should work for all ARMv7 cores, as well
- * as at least ARM-1156T2.  The interesting thing about Cortex-M is
- * that *only* Thumb2 disassembly matters.  There are also some small
- * additions to Thumb2 that are specific to ARMv7-M.
- */
-COMMAND_HANDLER(handle_cortex_m3_disassemble_command)
-{
-       int retval;
-       struct target *target = get_current_target(CMD_CTX);
-       struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
-       uint32_t address;
-       unsigned long count = 1;
-       struct arm_instruction cur_instruction;
-
-       retval = cortex_m3_verify_pointer(CMD_CTX, cortex_m3);
-       if (retval != ERROR_OK)
-               return retval;
-
-       errno = 0;
-       switch (CMD_ARGC) {
-       case 2:
-               COMMAND_PARSE_NUMBER(ulong, CMD_ARGV[1], count);
-               /* FALL THROUGH */
-       case 1:
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
-               break;
-       default:
-               command_print(CMD_CTX,
-                       "usage: cortex_m3 disassemble <address> [<count>]");
-               return ERROR_OK;
-       }
-
-       while (count--) {
-               retval = thumb2_opcode(target, address, &cur_instruction);
-               if (retval != ERROR_OK)
-                       return retval;
-               command_print(CMD_CTX, "%s", cur_instruction.text);
-               address += cur_instruction.instruction_size;
-       }
-
-       return ERROR_OK;
-}
-
 static const struct {
        char name[10];
        unsigned mask;
@@ -1888,7 +1938,7 @@ COMMAND_HANDLER(handle_cortex_m3_vector_catch_command)
        struct target *target = get_current_target(CMD_CTX);
        struct cortex_m3_common *cortex_m3 = target_to_cm3(target);
        struct armv7m_common *armv7m = &cortex_m3->armv7m;
-       struct swjdp_common *swjdp = &armv7m->swjdp_info;
+       struct adiv5_dap *swjdp = &armv7m->dap;
        uint32_t demcr = 0;
        int retval;
 
@@ -1925,12 +1975,20 @@ COMMAND_HANDLER(handle_cortex_m3_vector_catch_command)
                        }
                }
 write:
+               /* For now, armv7m->demcr only stores vector catch flags. */
+               armv7m->demcr = catch;
+
                demcr &= ~0xffff;
                demcr |= catch;
 
-               /* write, but don't assume it stuck */
+               /* write, but don't assume it stuck (why not??) */
                mem_ap_write_u32(swjdp, DCB_DEMCR, demcr);
                mem_ap_read_atomic_u32(swjdp, DCB_DEMCR, &demcr);
+
+               /* FIXME be sure to clear DEMCR on clean server shutdown.
+                * Otherwise the vector catch hardware could fire when there's
+                * no debugger hooked up, causing much confusion...
+                */
        }
 
        for (unsigned i = 0; i < ARRAY_SIZE(vec_ids); i++)
@@ -1974,26 +2032,19 @@ COMMAND_HANDLER(handle_cortex_m3_mask_interrupts_command)
 }
 
 static const struct command_registration cortex_m3_exec_command_handlers[] = {
-       {
-               .name = "disassemble",
-               .handler = &handle_cortex_m3_disassemble_command,
-               .mode = COMMAND_EXEC,
-               .help = "disassemble Thumb2 instructions",
-               .usage = "<address> [<count>]",
-       },
        {
                .name = "maskisr",
-               .handler = &handle_cortex_m3_mask_interrupts_command,
+               .handler = handle_cortex_m3_mask_interrupts_command,
                .mode = COMMAND_EXEC,
                .help = "mask cortex_m3 interrupts",
                .usage = "['on'|'off']",
        },
        {
                .name = "vector_catch",
-               .handler = &handle_cortex_m3_vector_catch_command,
+               .handler = handle_cortex_m3_vector_catch_command,
                .mode = COMMAND_EXEC,
-               .help = "catch hardware vectors",
-               .usage = "['all'|'none'|<list>]",
+               .help = "configure hardware vectors to trigger debug entry",
+               .usage = "['all'|'none'|('bus_err'|'chk_err'|...)*]",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -2003,7 +2054,7 @@ static const struct command_registration cortex_m3_command_handlers[] = {
        },
        {
                .name = "cortex_m3",
-               .mode = COMMAND_ANY,
+               .mode = COMMAND_EXEC,
                .help = "Cortex-M3 command group",
                .chain = cortex_m3_exec_command_handlers,
        },