Support for debugging on ARMv8-M CPUs 97/4997/7
authorOmair Javaid <omair.javaid@linaro.org>
Thu, 21 Mar 2019 18:33:13 +0000 (23:33 +0500)
committerMatthias Welwarsky <matthias@welwarsky.de>
Wed, 19 Jun 2019 08:35:05 +0000 (09:35 +0100)
This patch adds ARMv8-M CPUs detection logic in ARMv7m target specific code.

Also adds a slightly different watchpoint manipulation logic for ARMv8-M.

This is based on ARMv8-M architecture reference manual.

Tested on ARM Musca A board.

Change-Id: I0652560954ef02c378a7067fab586edf39d3e9cc
Signed-off-by: Omair Javaid <omair.javaid@linaro.org>
Reviewed-on: http://openocd.zylin.com/4997
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
src/target/cortex_m.c
src/target/cortex_m.h

index e296039..9aaa5bb 100644 (file)
@@ -1391,18 +1391,8 @@ int cortex_m_remove_breakpoint(struct target *target, struct breakpoint *breakpo
 int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint)
 {
        int dwt_num = 0;
-       uint32_t mask, temp;
        struct cortex_m_common *cortex_m = target_to_cm(target);
 
-       /* watchpoint params were validated earlier */
-       mask = 0;
-       temp = watchpoint->length;
-       while (temp) {
-               temp >>= 1;
-               mask++;
-       }
-       mask--;
-
        /* REVISIT Don't fully trust these "not used" records ... users
         * may set up breakpoints by hand, e.g. dual-address data value
         * watchpoint using comparator #1; comparator #0 matching cycle
@@ -1425,11 +1415,22 @@ int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint
        target_write_u32(target, comparator->dwt_comparator_address + 0,
                comparator->comp);
 
-       comparator->mask = mask;
-       target_write_u32(target, comparator->dwt_comparator_address + 4,
-               comparator->mask);
+       if ((cortex_m->dwt_devarch & 0x1FFFFF) != DWT_DEVARCH_ARMV8M) {
+               uint32_t mask = 0, temp;
+
+               /* watchpoint params were validated earlier */
+               temp = watchpoint->length;
+               while (temp) {
+                       temp >>= 1;
+                       mask++;
+               }
+               mask--;
 
-       switch (watchpoint->rw) {
+               comparator->mask = mask;
+               target_write_u32(target, comparator->dwt_comparator_address + 4,
+                       comparator->mask);
+
+               switch (watchpoint->rw) {
                case WPT_READ:
                        comparator->function = 5;
                        break;
@@ -1439,7 +1440,26 @@ int cortex_m_set_watchpoint(struct target *target, struct watchpoint *watchpoint
                case WPT_ACCESS:
                        comparator->function = 7;
                        break;
+               }
+       } else {
+               uint32_t data_size = watchpoint->length >> 1;
+               comparator->mask = (watchpoint->length >> 1) | 1;
+
+               switch (watchpoint->rw) {
+               case WPT_ACCESS:
+                       comparator->function = 4;
+                       break;
+               case WPT_WRITE:
+                       comparator->function = 5;
+                       break;
+               case WPT_READ:
+                       comparator->function = 6;
+                       break;
+               }
+               comparator->function = comparator->function | (1 << 4) |
+                               (data_size << 10);
        }
+
        target_write_u32(target, comparator->dwt_comparator_address + 8,
                comparator->function);
 
@@ -1982,6 +2002,9 @@ void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
                return;
        }
 
+       target_read_u32(target, DWT_DEVARCH, &cm->dwt_devarch);
+       LOG_DEBUG("DWT_DEVARCH: 0x%" PRIx32, cm->dwt_devarch);
+
        cm->dwt_num_comp = (dwtcr >> 28) & 0xF;
        cm->dwt_comp_available = cm->dwt_num_comp;
        cm->dwt_comparator_list = calloc(cm->dwt_num_comp,
@@ -2112,6 +2135,20 @@ int cortex_m_examine(struct target *target)
                /* Get CPU Type */
                i = (cpuid >> 4) & 0xf;
 
+               switch (cpuid & ARM_CPUID_PARTNO_MASK) {
+                       case CORTEX_M23_PARTNO:
+                               i = 23;
+                               break;
+
+                       case CORTEX_M33_PARTNO:
+                               i = 33;
+                               break;
+
+                       default:
+                               break;
+               }
+
+
                LOG_DEBUG("Cortex-M%d r%" PRId8 "p%" PRId8 " processor detected",
                                i, (uint8_t)((cpuid >> 20) & 0xf), (uint8_t)((cpuid >> 0) & 0xf));
                cortex_m->maskints_erratum = false;
@@ -2138,7 +2175,7 @@ int cortex_m_examine(struct target *target)
                                LOG_DEBUG("Cortex-M%d floating point feature FPv4_SP found", i);
                                armv7m->fp_feature = FPv4_SP;
                        }
-               } else if (i == 7) {
+               } else if (i == 7 || i == 33) {
                        target_read_u32(target, MVFR0, &mvfr0);
                        target_read_u32(target, MVFR1, &mvfr1);
 
index 2f29903..54d7a02 100644 (file)
 #define ITM_LAR_KEY    0xC5ACCE55
 
 #define CPUID          0xE000ED00
+
+#define ARM_CPUID_PARTNO_MASK  0xFFF0
+
+#define CORTEX_M23_PARTNO      0xD200
+#define CORTEX_M33_PARTNO      0xD210
+
 /* Debug Control Block */
 #define DCB_DHCSR      0xE000EDF0
 #define DCB_DCRSR      0xE000EDF4
@@ -52,6 +58,9 @@
 #define DWT_COMP0      0xE0001020
 #define DWT_MASK0      0xE0001024
 #define DWT_FUNCTION0  0xE0001028
+#define DWT_DEVARCH            0xE0001FBC
+
+#define DWT_DEVARCH_ARMV8M     0x101A02
 
 #define FP_CTRL                0xE0002000
 #define FP_REMAP       0xE0002004
@@ -181,6 +190,7 @@ struct cortex_m_common {
        /* Data Watchpoint and Trace (DWT) */
        int dwt_num_comp;
        int dwt_comp_available;
+       uint32_t dwt_devarch;
        struct cortex_m_dwt_comparator *dwt_comparator_list;
        struct reg_cache *dwt_cache;