target/cortex_m: check core implementor field
[openocd.git] / src / target / cortex_m.c
index 8e9264b79ce5604eca3e71e2fd25a873eea9d115..87a88455270d836a4701ddf6f4840a3204fba16a 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+// SPDX-License-Identifier: GPL-2.0-or-later
 
 /***************************************************************************
  *   Copyright (C) 2005 by Dominic Rath                                    *
@@ -28,6 +28,8 @@
 #include "register.h"
 #include "arm_opcodes.h"
 #include "arm_semihosting.h"
+#include "smp.h"
+#include <helper/nvp.h>
 #include <helper/time_support.h>
 #include <rtt/rtt.h>
 
 /* Supported Cortex-M Cores */
 static const struct cortex_m_part_info cortex_m_parts[] = {
        {
-               .partno = CORTEX_M0_PARTNO,
+               .impl_part = CORTEX_M0_PARTNO,
                .name = "Cortex-M0",
                .arch = ARM_ARCH_V6M,
        },
        {
-               .partno = CORTEX_M0P_PARTNO,
+               .impl_part = CORTEX_M0P_PARTNO,
                .name = "Cortex-M0+",
                .arch = ARM_ARCH_V6M,
        },
        {
-               .partno = CORTEX_M1_PARTNO,
+               .impl_part = CORTEX_M1_PARTNO,
                .name = "Cortex-M1",
                .arch = ARM_ARCH_V6M,
        },
        {
-               .partno = CORTEX_M3_PARTNO,
+               .impl_part = CORTEX_M3_PARTNO,
                .name = "Cortex-M3",
                .arch = ARM_ARCH_V7M,
                .flags = CORTEX_M_F_TAR_AUTOINCR_BLOCK_4K,
        },
        {
-               .partno = CORTEX_M4_PARTNO,
+               .impl_part = 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,
+               .impl_part = CORTEX_M7_PARTNO,
                .name = "Cortex-M7",
                .arch = ARM_ARCH_V7M,
                .flags = CORTEX_M_F_HAS_FPV5,
        },
        {
-               .partno = CORTEX_M23_PARTNO,
+               .impl_part = CORTEX_M23_PARTNO,
                .name = "Cortex-M23",
                .arch = ARM_ARCH_V8M,
        },
        {
-               .partno = CORTEX_M33_PARTNO,
+               .impl_part = CORTEX_M33_PARTNO,
                .name = "Cortex-M33",
                .arch = ARM_ARCH_V8M,
                .flags = CORTEX_M_F_HAS_FPV5,
        },
        {
-               .partno = CORTEX_M35P_PARTNO,
+               .impl_part = CORTEX_M35P_PARTNO,
                .name = "Cortex-M35P",
                .arch = ARM_ARCH_V8M,
                .flags = CORTEX_M_F_HAS_FPV5,
        },
        {
-               .partno = CORTEX_M55_PARTNO,
+               .impl_part = CORTEX_M55_PARTNO,
                .name = "Cortex-M55",
                .arch = ARM_ARCH_V8M,
                .flags = CORTEX_M_F_HAS_FPV5,
        },
        {
-               .partno = STAR_MC1_PARTNO,
+               .impl_part = STAR_MC1_PARTNO,
                .name = "STAR-MC1",
                .arch = ARM_ARCH_V8M,
                .flags = CORTEX_M_F_HAS_FPV5,
@@ -799,15 +801,11 @@ static int cortex_m_debug_entry(struct target *target)
                return retval;
 
        /* examine PE security state */
-       bool secure_state = false;
+       uint32_t dscsr = 0;
        if (armv7m->arm.arch == ARM_ARCH_V8M) {
-               uint32_t dscsr;
-
                retval = mem_ap_read_u32(armv7m->debug_ap, DCB_DSCSR, &dscsr);
                if (retval != ERROR_OK)
                        return retval;
-
-               secure_state = (dscsr & DSCSR_CDS) == DSCSR_CDS;
        }
 
        /* Load all registers to arm.core_cache */
@@ -855,6 +853,7 @@ static int cortex_m_debug_entry(struct target *target)
        if (armv7m->exception_number)
                cortex_m_examine_exception_reason(target);
 
+       bool secure_state = (dscsr & DSCSR_CDS) == DSCSR_CDS;
        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),
@@ -871,7 +870,7 @@ static int cortex_m_debug_entry(struct target *target)
        return ERROR_OK;
 }
 
-static int cortex_m_poll(struct target *target)
+static int cortex_m_poll_one(struct target *target)
 {
        int detected_failure = ERROR_OK;
        int retval = ERROR_OK;
@@ -879,16 +878,6 @@ static int cortex_m_poll(struct target *target)
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct armv7m_common *armv7m = &cortex_m->armv7m;
 
-       /* Check if debug_ap is available to prevent segmentation fault.
-        * If the re-examination after an error does not find a MEM-AP
-        * (e.g. the target stopped communicating), debug_ap pointer
-        * can suddenly become NULL.
-        */
-       if (!armv7m->debug_ap) {
-               target->state = TARGET_UNKNOWN;
-               return ERROR_TARGET_NOT_EXAMINED;
-       }
-
        /* Read from Debug Halting Control and Status Register */
        retval = cortex_m_read_dhcsr_atomic_sticky(target);
        if (retval != ERROR_OK) {
@@ -944,21 +933,26 @@ static int cortex_m_poll(struct target *target)
 
                if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_RESET)) {
                        retval = cortex_m_debug_entry(target);
-                       if (retval != ERROR_OK)
-                               return retval;
 
-                       if (arm_semihosting(target, &retval) != 0)
+                       /* arm_semihosting needs to know registers, don't run if debug entry returned error */
+                       if (retval == ERROR_OK && arm_semihosting(target, &retval) != 0)
                                return retval;
 
-                       target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+                       if (target->smp) {
+                               LOG_TARGET_DEBUG(target, "postpone target event 'halted'");
+                               target->smp_halt_event_postponed = true;
+                       } else {
+                               /* regardless of errors returned in previous code update state */
+                               target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+                       }
                }
                if (prev_target_state == TARGET_DEBUG_RUNNING) {
                        retval = cortex_m_debug_entry(target);
-                       if (retval != ERROR_OK)
-                               return retval;
 
                        target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
                }
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        if (target->state == TARGET_UNKNOWN) {
@@ -991,7 +985,104 @@ static int cortex_m_poll(struct target *target)
        return retval;
 }
 
-static int cortex_m_halt(struct target *target)
+static int cortex_m_halt_one(struct target *target);
+
+static int cortex_m_smp_halt_all(struct list_head *smp_targets)
+{
+       int retval = ERROR_OK;
+       struct target_list *head;
+
+       foreach_smp_target(head, smp_targets) {
+               struct target *curr = head->target;
+               if (!target_was_examined(curr))
+                       continue;
+               if (curr->state == TARGET_HALTED)
+                       continue;
+
+               int ret2 = cortex_m_halt_one(curr);
+               if (retval == ERROR_OK)
+                       retval = ret2;  /* store the first error code ignore others */
+       }
+       return retval;
+}
+
+static int cortex_m_smp_post_halt_poll(struct list_head *smp_targets)
+{
+       int retval = ERROR_OK;
+       struct target_list *head;
+
+       foreach_smp_target(head, smp_targets) {
+               struct target *curr = head->target;
+               if (!target_was_examined(curr))
+                       continue;
+               /* skip targets that were already halted */
+               if (curr->state == TARGET_HALTED)
+                       continue;
+
+               int ret2 = cortex_m_poll_one(curr);
+               if (retval == ERROR_OK)
+                       retval = ret2;  /* store the first error code ignore others */
+       }
+       return retval;
+}
+
+static int cortex_m_poll_smp(struct list_head *smp_targets)
+{
+       int retval = ERROR_OK;
+       struct target_list *head;
+       bool halted = false;
+
+       foreach_smp_target(head, smp_targets) {
+               struct target *curr = head->target;
+               if (curr->smp_halt_event_postponed) {
+                       halted = true;
+                       break;
+               }
+       }
+
+       if (halted) {
+               retval = cortex_m_smp_halt_all(smp_targets);
+
+               int ret2 = cortex_m_smp_post_halt_poll(smp_targets);
+               if (retval == ERROR_OK)
+                       retval = ret2;  /* store the first error code ignore others */
+
+               foreach_smp_target(head, smp_targets) {
+                       struct target *curr = head->target;
+                       if (!curr->smp_halt_event_postponed)
+                               continue;
+
+                       curr->smp_halt_event_postponed = false;
+                       if (curr->state == TARGET_HALTED) {
+                               LOG_TARGET_DEBUG(curr, "sending postponed target event 'halted'");
+                               target_call_event_callbacks(curr, TARGET_EVENT_HALTED);
+                       }
+               }
+               /* There is no need to set gdb_service->target
+                * as hwthread_update_threads() selects an interesting thread
+                * by its own
+                */
+       }
+       return retval;
+}
+
+static int cortex_m_poll(struct target *target)
+{
+       int retval = cortex_m_poll_one(target);
+
+       if (target->smp) {
+               struct target_list *last;
+               last = list_last_entry(target->smp_targets, struct target_list, lh);
+               if (target == last->target)
+                       /* After the last target in SMP group has been polled
+                        * check for postponed halted events and eventually halt and re-poll
+                        * other targets */
+                       cortex_m_poll_smp(target->smp_targets);
+       }
+       return retval;
+}
+
+static int cortex_m_halt_one(struct target *target)
 {
        LOG_TARGET_DEBUG(target, "target->state: %s", target_state_name(target));
 
@@ -1029,6 +1120,14 @@ static int cortex_m_halt(struct target *target)
        return ERROR_OK;
 }
 
+static int cortex_m_halt(struct target *target)
+{
+       if (target->smp)
+               return cortex_m_smp_halt_all(target->smp_targets);
+       else
+               return cortex_m_halt_one(target);
+}
+
 static int cortex_m_soft_reset_halt(struct target *target)
 {
        struct cortex_m_common *cortex_m = target_to_cm(target);
@@ -1106,8 +1205,8 @@ void cortex_m_enable_breakpoints(struct target *target)
        }
 }
 
-static int cortex_m_resume(struct target *target, int current,
-       target_addr_t address, int handle_breakpoints, int debug_execution)
+static int cortex_m_restore_one(struct target *target, bool current,
+       target_addr_t *address, bool handle_breakpoints, bool debug_execution)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
        struct breakpoint *breakpoint = NULL;
@@ -1115,7 +1214,7 @@ static int cortex_m_resume(struct target *target, int current,
        struct reg *r;
 
        if (target->state != TARGET_HALTED) {
-               LOG_TARGET_WARNING(target, "target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1157,7 +1256,7 @@ static int cortex_m_resume(struct target *target, int current,
        /* current = 1: continue on current pc, otherwise continue at <address> */
        r = armv7m->arm.pc;
        if (!current) {
-               buf_set_u32(r->value, 0, 32, address);
+               buf_set_u32(r->value, 0, 32, *address);
                r->dirty = true;
                r->valid = true;
        }
@@ -1171,8 +1270,12 @@ static int cortex_m_resume(struct target *target, int current,
                armv7m_maybe_skip_bkpt_inst(target, NULL);
 
        resume_pc = buf_get_u32(r->value, 0, 32);
+       if (current)
+               *address = resume_pc;
 
-       armv7m_restore_context(target);
+       int retval = armv7m_restore_context(target);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* the front-end may request us not to handle breakpoints */
        if (handle_breakpoints) {
@@ -1182,34 +1285,99 @@ static int cortex_m_resume(struct target *target, int current,
                        LOG_TARGET_DEBUG(target, "unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")",
                                breakpoint->address,
                                breakpoint->unique_id);
-                       cortex_m_unset_breakpoint(target, breakpoint);
-                       cortex_m_single_step_core(target);
-                       cortex_m_set_breakpoint(target, breakpoint);
+                       retval = cortex_m_unset_breakpoint(target, breakpoint);
+                       if (retval == ERROR_OK)
+                               retval = cortex_m_single_step_core(target);
+                       int ret2 = cortex_m_set_breakpoint(target, breakpoint);
+                       if (retval != ERROR_OK)
+                               return retval;
+                       if (ret2 != ERROR_OK)
+                               return ret2;
                }
        }
 
+       return ERROR_OK;
+}
+
+static int cortex_m_restart_one(struct target *target, bool debug_execution)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+
        /* Restart core */
        cortex_m_set_maskints_for_run(target);
        cortex_m_write_debug_halt_mask(target, 0, C_HALT);
 
        target->debug_reason = DBG_REASON_NOTHALTED;
-
        /* registers are now invalid */
        register_cache_invalidate(armv7m->arm.core_cache);
 
        if (!debug_execution) {
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
-               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_TARGET_DEBUG(target, "target debug resumed at 0x%" PRIx32 "", resume_pc);
        }
 
        return ERROR_OK;
 }
 
+static int cortex_m_restore_smp(struct target *target, bool handle_breakpoints)
+{
+       struct target_list *head;
+       target_addr_t address;
+       foreach_smp_target(head, target->smp_targets) {
+               struct target *curr = head->target;
+               /* skip calling target */
+               if (curr == target)
+                       continue;
+               if (!target_was_examined(curr))
+                       continue;
+               /* skip running targets */
+               if (curr->state == TARGET_RUNNING)
+                       continue;
+
+               int retval = cortex_m_restore_one(curr, true, &address,
+                                                                               handle_breakpoints, false);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               retval = cortex_m_restart_one(curr, false);
+               if (retval != ERROR_OK)
+                       return retval;
+
+               LOG_TARGET_DEBUG(curr, "SMP resumed at " TARGET_ADDR_FMT, address);
+       }
+       return ERROR_OK;
+}
+
+static int cortex_m_resume(struct target *target, int current,
+                                                  target_addr_t address, int handle_breakpoints, int debug_execution)
+{
+       int retval = cortex_m_restore_one(target, !!current, &address, !!handle_breakpoints, !!debug_execution);
+       if (retval != ERROR_OK) {
+               LOG_TARGET_ERROR(target, "context restore failed, aborting resume");
+               return retval;
+       }
+
+       if (target->smp && !debug_execution) {
+               retval = cortex_m_restore_smp(target, !!handle_breakpoints);
+               if (retval != ERROR_OK)
+                       LOG_WARNING("resume of a SMP target failed, trying to resume current one");
+       }
+
+       cortex_m_restart_one(target, !!debug_execution);
+       if (retval != ERROR_OK) {
+               LOG_TARGET_ERROR(target, "resume failed");
+               return retval;
+       }
+
+       LOG_TARGET_DEBUG(target, "%sresumed at " TARGET_ADDR_FMT,
+                                       debug_execution ? "debug " : "", address);
+
+       return ERROR_OK;
+}
+
 /* int irqstepcount = 0; */
 static int cortex_m_step(struct target *target, int current,
        target_addr_t address, int handle_breakpoints)
@@ -1223,10 +1391,15 @@ static int cortex_m_step(struct target *target, int current,
        bool isr_timed_out = false;
 
        if (target->state != TARGET_HALTED) {
-               LOG_TARGET_WARNING(target, "target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
+       /* Just one of SMP cores will step. Set the gdb control
+        * target to current one or gdb miss gdb-end event */
+       if (target->smp && target->gdb_service)
+               target->gdb_service->target = target;
+
        /* current = 1: continue on current pc, otherwise continue at <address> */
        if (!current) {
                buf_set_u32(pc->value, 0, 32, address);
@@ -1408,8 +1581,9 @@ 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_TARGET_DEBUG(target, "target->state: %s",
-               target_state_name(target));
+       LOG_TARGET_DEBUG(target, "target->state: %s,%s examined",
+               target_state_name(target),
+               target_was_examined(target) ? "" : " not");
 
        enum reset_types jtag_reset_config = jtag_get_reset_config();
 
@@ -1428,24 +1602,40 @@ static int cortex_m_assert_reset(struct target *target)
 
        bool srst_asserted = false;
 
-       if (!target_was_examined(target)) {
-               if (jtag_reset_config & RESET_HAS_SRST) {
-                       adapter_assert_reset();
+       if ((jtag_reset_config & RESET_HAS_SRST) &&
+               ((jtag_reset_config & RESET_SRST_NO_GATING) || !armv7m->debug_ap)) {
+               /* If we have no debug_ap, asserting SRST is the only thing
+                * we can do now */
+               adapter_assert_reset();
+               srst_asserted = true;
+       }
+
+       /* TODO: replace the hack calling target_examine_one()
+        * as soon as a better reset framework is available */
+       if (!target_was_examined(target) && !target->defer_examine
+               && srst_asserted && (jtag_reset_config & RESET_SRST_NO_GATING)) {
+               LOG_TARGET_DEBUG(target, "Trying to re-examine under reset");
+               target_examine_one(target);
+       }
+
+       /* We need at least debug_ap to go further.
+        * Inform user and bail out if we don't have one. */
+       if (!armv7m->debug_ap) {
+               if (srst_asserted) {
                        if (target->reset_halt)
-                               LOG_TARGET_ERROR(target, "Target not examined, will not halt after reset!");
+                               LOG_TARGET_ERROR(target, "Debug AP not available, will not halt after reset!");
+
+                       /* Do not propagate error: reset was asserted, proceed to deassert! */
+                       target->state = TARGET_RESET;
+                       register_cache_invalidate(cortex_m->armv7m.arm.core_cache);
                        return ERROR_OK;
+
                } else {
-                       LOG_TARGET_ERROR(target, "Target not examined, reset NOT asserted!");
+                       LOG_TARGET_ERROR(target, "Debug AP not available, reset NOT asserted!");
                        return ERROR_FAIL;
                }
        }
 
-       if ((jtag_reset_config & RESET_HAS_SRST) &&
-           (jtag_reset_config & RESET_SRST_NO_GATING)) {
-               adapter_assert_reset();
-               srst_asserted = true;
-       }
-
        /* Enable debug requests */
        int retval = cortex_m_read_dhcsr_atomic_sticky(target);
 
@@ -1546,7 +1736,7 @@ static int cortex_m_assert_reset(struct target *target)
        if (retval != ERROR_OK)
                return retval;
 
-       if (target->reset_halt) {
+       if (target->reset_halt && target_was_examined(target)) {
                retval = target_halt(target);
                if (retval != ERROR_OK)
                        return retval;
@@ -1559,8 +1749,9 @@ static int cortex_m_deassert_reset(struct target *target)
 {
        struct armv7m_common *armv7m = &target_to_cm(target)->armv7m;
 
-       LOG_TARGET_DEBUG(target, "target->state: %s",
-               target_state_name(target));
+       LOG_TARGET_DEBUG(target, "target->state: %s,%s examined",
+               target_state_name(target),
+               target_was_examined(target) ? "" : " not");
 
        /* deassert reset lines */
        adapter_deassert_reset();
@@ -1568,8 +1759,8 @@ static int cortex_m_deassert_reset(struct target *target)
        enum reset_types jtag_reset_config = jtag_get_reset_config();
 
        if ((jtag_reset_config & RESET_HAS_SRST) &&
-           !(jtag_reset_config & RESET_SRST_NO_GATING) &&
-               target_was_examined(target)) {
+               !(jtag_reset_config & RESET_SRST_NO_GATING) &&
+               armv7m->debug_ap) {
 
                int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap);
                if (retval != ERROR_OK) {
@@ -1855,8 +2046,14 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
-       /* hardware doesn't support data value masking */
-       if (watchpoint->mask != ~(uint32_t)0) {
+       /* REVISIT This DWT may well be able to watch for specific data
+        * values.  Requires comparator #1 to set DATAVMATCH and match
+        * the data, and another comparator (DATAVADDR0) matching addr.
+        *
+        * NOTE: hardware doesn't support data value masking, so we'll need
+        * to check that mask is zero
+        */
+       if (watchpoint->mask != WATCHPOINT_IGNORE_DATA_VALUE_MASK) {
                LOG_TARGET_DEBUG(target, "watchpoint value masks not supported");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
@@ -1877,18 +2074,6 @@ int cortex_m_add_watchpoint(struct target *target, struct watchpoint *watchpoint
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
-       /* Caller doesn't seem to be able to describe watching for data
-        * values of zero; that flags "no value".
-        *
-        * REVISIT This DWT may well be able to watch for specific data
-        * values.  Requires comparator #1 to set DATAVMATCH and match
-        * the data, and another comparator (DATAVADDR0) matching addr.
-        */
-       if (watchpoint->value) {
-               LOG_TARGET_DEBUG(target, "data value watchpoint not YET supported");
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-       }
-
        cortex_m->dwt_comp_available--;
        LOG_TARGET_DEBUG(target, "dwt_comp_available: %d", cortex_m->dwt_comp_available);
 
@@ -1901,7 +2086,7 @@ 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_TARGET_WARNING(target, "target not halted");
+               LOG_TARGET_ERROR(target, "not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -1914,7 +2099,7 @@ int cortex_m_remove_watchpoint(struct target *target, struct watchpoint *watchpo
        return ERROR_OK;
 }
 
-int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
+static int cortex_m_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint)
 {
        if (target->debug_reason != DBG_REASON_WATCHPOINT)
                return ERROR_FAIL;
@@ -2262,6 +2447,22 @@ static void cortex_m_dwt_free(struct target *target)
        cm->dwt_cache = NULL;
 }
 
+static bool cortex_m_has_tz(struct target *target)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       uint32_t dauthstatus;
+
+       if (armv7m->arm.arch != ARM_ARCH_V8M)
+               return false;
+
+       int retval = target_read_u32(target, DAUTHSTATUS, &dauthstatus);
+       if (retval != ERROR_OK) {
+               LOG_WARNING("Error reading DAUTHSTATUS register");
+               return false;
+       }
+       return (dauthstatus & DAUTHSTATUS_SID_MASK) != 0;
+}
+
 #define MVFR0 0xe000ef40
 #define MVFR1 0xe000ef44
 
@@ -2293,23 +2494,20 @@ 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_TARGET_ERROR(target, "Could not find MEM-AP to control the core");
-                               return retval;
-                       }
-               } else {
-                       armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel);
-                       if (!armv7m->debug_ap) {
-                               LOG_ERROR("Cannot get AP");
-                               return ERROR_FAIL;
+               if (!armv7m->debug_ap) {
+                       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_TARGET_ERROR(target, "Could not find MEM-AP to control the core");
+                                       return retval;
+                               }
+                       } else {
+                               armv7m->debug_ap = dap_get_ap(swjdp, cortex_m->apsel);
+                               if (!armv7m->debug_ap) {
+                                       LOG_ERROR("Cannot get AP");
+                                       return ERROR_FAIL;
+                               }
                        }
                }
 
@@ -2328,18 +2526,18 @@ int cortex_m_examine(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               /* Get ARCH and CPU types */
-               const enum cortex_m_partno core_partno = (cpuid & ARM_CPUID_PARTNO_MASK) >> ARM_CPUID_PARTNO_POS;
+               /* Inspect implementor/part to look for recognized cores  */
+               unsigned int impl_part = cpuid & (ARM_CPUID_IMPLEMENTOR_MASK | ARM_CPUID_PARTNO_MASK);
 
                for (unsigned int n = 0; n < ARRAY_SIZE(cortex_m_parts); n++) {
-                       if (core_partno == cortex_m_parts[n].partno) {
+                       if (impl_part == cortex_m_parts[n].impl_part) {
                                cortex_m->core_info = &cortex_m_parts[n];
                                break;
                        }
                }
 
                if (!cortex_m->core_info) {
-                       LOG_TARGET_ERROR(target, "Cortex-M PARTNO 0x%x is unrecognized", core_partno);
+                       LOG_TARGET_ERROR(target, "Cortex-M CPUID: 0x%x is unrecognized", cpuid);
                        return ERROR_FAIL;
                }
 
@@ -2351,7 +2549,7 @@ int cortex_m_examine(struct target *target)
                                (uint8_t)((cpuid >> 0) & 0xf));
 
                cortex_m->maskints_erratum = false;
-               if (core_partno == CORTEX_M7_PARTNO) {
+               if (impl_part == CORTEX_M7_PARTNO) {
                        uint8_t rev, patch;
                        rev = (cpuid >> 20) & 0xf;
                        patch = (cpuid >> 0) & 0xf;
@@ -2393,7 +2591,7 @@ int cortex_m_examine(struct target *target)
                        for (size_t idx = ARMV7M_FPU_FIRST_REG; idx <= ARMV7M_FPU_LAST_REG; idx++)
                                armv7m->arm.core_cache->reg_list[idx].exist = false;
 
-               if (armv7m->arm.arch != ARM_ARCH_V8M)
+               if (!cortex_m_has_tz(target))
                        for (size_t idx = ARMV8M_FIRST_REG; idx <= ARMV8M_LAST_REG; idx++)
                                armv7m->arm.core_cache->reg_list[idx].exist = false;
 
@@ -2729,14 +2927,14 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
        struct cortex_m_common *cortex_m = target_to_cm(target);
        int retval;
 
-       static const struct jim_nvp nvp_maskisr_modes[] = {
+       static const struct nvp nvp_maskisr_modes[] = {
                { .name = "auto", .value = CORTEX_M_ISRMASK_AUTO },
                { .name = "off", .value = CORTEX_M_ISRMASK_OFF },
                { .name = "on", .value = CORTEX_M_ISRMASK_ON },
                { .name = "steponly", .value = CORTEX_M_ISRMASK_STEPONLY },
                { .name = NULL, .value = -1 },
        };
-       const struct jim_nvp *n;
+       const struct nvp *n;
 
 
        retval = cortex_m_verify_pointer(CMD, cortex_m);
@@ -2744,19 +2942,19 @@ COMMAND_HANDLER(handle_cortex_m_mask_interrupts_command)
                return retval;
 
        if (target->state != TARGET_HALTED) {
-               command_print(CMD, "target must be stopped for \"%s\" command", CMD_NAME);
-               return ERROR_OK;
+               command_print(CMD, "Error: target must be stopped for \"%s\" command", CMD_NAME);
+               return ERROR_TARGET_NOT_HALTED;
        }
 
        if (CMD_ARGC > 0) {
-               n = jim_nvp_name2value_simple(nvp_maskisr_modes, CMD_ARGV[0]);
+               n = nvp_name2value(nvp_maskisr_modes, CMD_ARGV[0]);
                if (!n->name)
                        return ERROR_COMMAND_SYNTAX_ERROR;
                cortex_m->isrmasking_mode = n->value;
                cortex_m_set_maskints_for_halt(target);
        }
 
-       n = jim_nvp_value2name_simple(nvp_maskisr_modes, cortex_m->isrmasking_mode);
+       n = nvp_value2name(nvp_maskisr_modes, cortex_m->isrmasking_mode);
        command_print(CMD, "cortex_m interrupt mask %s", n->name);
 
        return ERROR_OK;
@@ -2829,6 +3027,9 @@ static const struct command_registration cortex_m_exec_command_handlers[] = {
                .help = "configure software reset handling",
                .usage = "['sysresetreq'|'vectreset']",
        },
+       {
+               .chain = smp_command_handlers,
+       },
        COMMAND_REGISTRATION_DONE
 };
 static const struct command_registration cortex_m_command_handlers[] = {

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)