target/cortex_m: use cortex_m->dcb_dhcsr in cortex_m_soft_reset_halt()
[fw/openocd] / src / target / cortex_m.c
index e442fc3b66ef4da8a6f7a22f2aacb50fa13f013c..d4affa6831fdcd202031d99d9817b72dae0df03c 100644 (file)
@@ -34,6 +34,7 @@
 #include "cortex_m.h"
 #include "target_request.h"
 #include "target_type.h"
+#include "arm_adi_v5.h"
 #include "arm_disassembler.h"
 #include "register.h"
 #include "arm_opcodes.h"
  * any longer.
  */
 
+/* Supported Cortex-M Cores */
+static const struct cortex_m_part_info cortex_m_parts[] = {
+       {
+               .partno = CORTEX_M0_PARTNO,
+               .name = "Cortex-M0",
+               .arch = ARM_ARCH_V6M,
+       },
+       {
+               .partno = CORTEX_M0P_PARTNO,
+               .name = "Cortex-M0+",
+               .arch = ARM_ARCH_V6M,
+       },
+       {
+               .partno = CORTEX_M1_PARTNO,
+               .name = "Cortex-M1",
+               .arch = ARM_ARCH_V6M,
+       },
+       {
+               .partno = CORTEX_M3_PARTNO,
+               .name = "Cortex-M3",
+               .arch = ARM_ARCH_V7M,
+               .flags = CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
+       },
+       {
+               .partno = CORTEX_M4_PARTNO,
+               .name = "Cortex-M4",
+               .arch = ARM_ARCH_V7M,
+               .flags = CORTEX_M_F_HAS_FPV4 | CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
+       },
+       {
+               .partno = CORTEX_M7_PARTNO,
+               .name = "Cortex-M7",
+               .arch = ARM_ARCH_V7M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+       {
+               .partno = CORTEX_M23_PARTNO,
+               .name = "Cortex-M23",
+               .arch = ARM_ARCH_V8M,
+       },
+       {
+               .partno = CORTEX_M33_PARTNO,
+               .name = "Cortex-M33",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+       {
+               .partno = CORTEX_M35P_PARTNO,
+               .name = "Cortex-M35P",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+       {
+               .partno = CORTEX_M55_PARTNO,
+               .name = "Cortex-M55",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
+};
+
 /* forward declarations */
 static int cortex_m_store_core_reg_u32(struct target *target,
                uint32_t num, uint32_t value);
@@ -109,7 +170,7 @@ 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_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WNR);
        if (retval != ERROR_OK)
                return retval;
 
@@ -240,7 +301,6 @@ static int cortex_m_clear_halt(struct target *target)
 static int cortex_m_single_step_core(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
-       struct armv7m_common *armv7m = &cortex_m->armv7m;
        int retval;
 
        /* Mask interrupts before clearing halt, if not done already.  This avoids
@@ -248,13 +308,11 @@ static int cortex_m_single_step_core(struct target *target)
         * HALT can put the core into an unknown state.
         */
        if (!(cortex_m->dcb_dhcsr & C_MASKINTS)) {
-               retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
-                               DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN);
+               retval = cortex_m_write_debug_halt_mask(target, C_MASKINTS, 0);
                if (retval != ERROR_OK)
                        return retval;
        }
-       retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DHCSR,
-                       DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN);
+       retval = cortex_m_write_debug_halt_mask(target, C_STEP, C_HALT);
        if (retval != ERROR_OK)
                return retval;
        LOG_DEBUG(" ");
@@ -718,7 +776,6 @@ 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
@@ -754,25 +811,23 @@ static int cortex_m_soft_reset_halt(struct target *target)
        register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
 
        while (timeout < 100) {
-               retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &dcb_dhcsr);
+               retval = mem_ap_read_atomic_u32(armv7m->debug_ap, DCB_DHCSR, &cortex_m->dcb_dhcsr);
                if (retval == ERROR_OK) {
                        retval = mem_ap_read_atomic_u32(armv7m->debug_ap, NVIC_DFSR,
                                        &cortex_m->nvic_dfsr);
                        if (retval != ERROR_OK)
                                return retval;
-                       if ((dcb_dhcsr & S_HALT)
+                       if ((cortex_m->dcb_dhcsr & S_HALT)
                                && (cortex_m->nvic_dfsr & DFSR_VCATCH)) {
-                               LOG_DEBUG("system reset-halted, DHCSR 0x%08x, "
-                                       "DFSR 0x%08x",
-                                       (unsigned) dcb_dhcsr,
-                                       (unsigned) cortex_m->nvic_dfsr);
+                               LOG_DEBUG("system reset-halted, DHCSR 0x%08" PRIx32 ", DFSR 0x%08" PRIx32,
+                                       cortex_m->dcb_dhcsr, cortex_m->nvic_dfsr);
                                cortex_m_poll(target);
                                /* FIXME restore user's vector catch config */
                                return ERROR_OK;
                        } else
                                LOG_DEBUG("waiting for system reset-halt, "
-                                       "DHCSR 0x%08x, %d ms",
-                                       (unsigned) dcb_dhcsr, timeout);
+                                       "DHCSR 0x%08" PRIx32 ", %d ms",
+                                       cortex_m->dcb_dhcsr, timeout);
                }
                timeout++;
                alive_sleep(1);
@@ -915,8 +970,11 @@ static int cortex_m_step(struct target *target, int current,
        }
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
-       if (!current)
+       if (!current) {
                buf_set_u32(pc->value, 0, 32, address);
+               pc->dirty = true;
+               pc->valid = true;
+       }
 
        uint32_t pc_value = buf_get_u32(pc->value, 0, 32);
 
@@ -1180,7 +1238,7 @@ static int cortex_m_assert_reset(struct target *target)
                retval = ERROR_OK;
        } else {
                /* Use a standard Cortex-M3 software reset mechanism.
-                * We default to using VECRESET as it is supported on all current cores
+                * We default to using VECTRESET as it is supported on all current cores
                 * (except Cortex-M0, M0+ and M1 which support SYSRESETREQ only!)
                 * This has the disadvantage of not resetting the peripherals, so a
                 * reset-init event handler is needed to perform any peripheral resets.
@@ -1971,9 +2029,9 @@ int cortex_m_examine(struct target *target)
        struct adiv5_dap *swjdp = cortex_m->armv7m.arm.dap;
        struct armv7m_common *armv7m = target_to_armv7m(target);
 
-       /* stlink shares the examine handler but does not support
+       /* hla_target shares the examine handler but does not support
         * all its calls */
-       if (!armv7m->stlink) {
+       if (!armv7m->is_hla_target) {
                if (cortex_m->apsel == DP_APSEL_INVALID) {
                        /* Search for the MEM-AP */
                        retval = cortex_m_find_mem_ap(swjdp, &armv7m->debug_ap);
@@ -2001,35 +2059,31 @@ int cortex_m_examine(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               /* Get CPU Type */
-               unsigned int core = (cpuid >> 4) & 0xf;
-
-               /* Check if it is an ARMv8-M core */
-               armv7m->arm.arch = ARM_ARCH_V8M;
+               /* Get ARCH and CPU types */
+               const enum cortex_m_partno core_partno = (cpuid & ARM_CPUID_PARTNO_MASK) >> ARM_CPUID_PARTNO_POS;
 
-               switch (cpuid & ARM_CPUID_PARTNO_MASK) {
-                       case CORTEX_M23_PARTNO:
-                               core = 23;
-                               break;
-                       case CORTEX_M33_PARTNO:
-                               core = 33;
-                               break;
-                       case CORTEX_M35P_PARTNO:
-                               core = 35;
-                               break;
-                       case CORTEX_M55_PARTNO:
-                               core = 55;
-                               break;
-                       default:
-                               armv7m->arm.arch = ARM_ARCH_V7M;
+               for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) {
+                       if (core_partno == cortex_m_parts[n].partno) {
+                               cortex_m->core_info = &cortex_m_parts[n];
                                break;
+                       }
                }
 
+               if (!cortex_m->core_info) {
+                       LOG_ERROR("Cortex-M PARTNO 0x%x is unrecognized", core_partno);
+                       return ERROR_FAIL;
+               }
+
+               armv7m->arm.arch = cortex_m->core_info->arch;
+
+               LOG_INFO("%s: %s r%" PRId8 "p%" PRId8 " processor detected",
+                               target_name(target),
+                               cortex_m->core_info->name,
+                               (uint8_t)((cpuid >> 20) & 0xf),
+                               (uint8_t)((cpuid >> 0) & 0xf));
 
-               LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected",
-                               core, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
                cortex_m->maskints_erratum = false;
-               if (core == 7) {
+               if (core_partno == CORTEX_M7_PARTNO) {
                        uint8_t rev, patch;
                        rev = (cpuid >> 20) & 0xf;
                        patch = (cpuid >> 0) & 0xf;
@@ -2040,30 +2094,27 @@ int cortex_m_examine(struct target *target)
                }
                LOG_DEBUG("cpuid: 0x%8.8" PRIx32 "", cpuid);
 
-               if (core == 4) {
+               if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV4) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
                        /* test for floating point feature on Cortex-M4 */
                        if ((mvfr0 == MVFR0_DEFAULT_M4) && (mvfr1 == MVFR1_DEFAULT_M4)) {
-                               LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", core);
+                               LOG_DEBUG("%s floating point feature FPv4_SP found", cortex_m->core_info->name);
                                armv7m->fp_feature = FPV4_SP;
                        }
-               } else if (core == 7 || core == 33 || core == 35 || core == 55) {
+               } else if (cortex_m->core_info->flags & CORTEX_M_F_HAS_FPV5) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
                        /* test for floating point features on Cortex-M7 */
                        if ((mvfr0 == MVFR0_DEFAULT_M7_SP) && (mvfr1 == MVFR1_DEFAULT_M7_SP)) {
-                               LOG_DEBUG("Cortex-M%d floating point feature FPv5_SP found", core);
+                               LOG_DEBUG("%s floating point feature FPv5_SP found", cortex_m->core_info->name);
                                armv7m->fp_feature = FPV5_SP;
                        } else if ((mvfr0 == MVFR0_DEFAULT_M7_DP) && (mvfr1 == MVFR1_DEFAULT_M7_DP)) {
-                               LOG_DEBUG("Cortex-M%d floating point feature FPv5_DP found", core);
+                               LOG_DEBUG("%s floating point feature FPv5_DP found", cortex_m->core_info->name);
                                armv7m->fp_feature = FPV5_DP;
                        }
-               } else if (core == 0) {
-                       /* Cortex-M0 does not support unaligned memory access */
-                       armv7m->arm.arch = ARM_ARCH_V6M;
                }
 
                /* VECTRESET is supported only on ARMv7-M cores */
@@ -2078,14 +2129,11 @@ int cortex_m_examine(struct target *target)
                        for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++)
                                armv7m->arm.core_cache->reg_list[idx].exist = false;
 
-               if (!armv7m->stlink) {
-                       if (core == 3 || core == 4)
+               if (!armv7m->is_hla_target) {
+                       if (cortex_m->core_info->flags & CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K)
                                /* Cortex-M3/M4 have 4096 bytes autoincrement range,
                                 * s. ARM IHI 0031C: MEM-AP 7.2.2 */
                                armv7m->debug_ap->tar_autoincr_block = (1 << 12);
-                       else if (core == 7)
-                               /* Cortex-M7 has only 1024 bytes autoincrement range */
-                               armv7m->debug_ap->tar_autoincr_block = (1 << 10);
                }
 
                /* Enable debug requests */
@@ -2142,7 +2190,7 @@ int cortex_m_examine(struct target *target)
                cortex_m_dwt_setup(cortex_m, target);
 
                /* These hardware breakpoints only work for code in flash! */
-               LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints",
+               LOG_INFO("%s: target has %d breakpoints, %d watchpoints",
                        target_name(target),
                        cortex_m->fp_num_code,
                        cortex_m->dwt_num_comp);
@@ -2272,7 +2320,7 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
                return ERROR_FAIL;
 
        struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
-       if (cortex_m == NULL) {
+       if (!cortex_m) {
                LOG_ERROR("No memory creating target");
                return ERROR_FAIL;
        }
@@ -2419,7 +2467,7 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
 
        if (CMD_ARGC > 0) {
                n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
-               if (n->name == NULL)
+               if (!n->name)
                        return ERROR_COMMAND_SYNTAX_ERROR;
                cortex_m->isrmasking_mode = n->value;
                cortex_m_set_maskints_for_halt(target);