target/cortex_m: try to re-examine under reset in cortex_m_assert_reset()
[openocd.git] / src / target / cortex_m.c
index 0a7668ddfa2d4758040e89ca0a726c616d7c80a8..1863441674ef3ba34f6b7f76909cbc4cb548f183 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)              *
  *                                                                         *
@@ -114,6 +103,12 @@ static const struct cortex_m_part_info cortex_m_parts[] = {
                .arch = ARM_ARCH_V8M,
                .flags = CORTEX_M_F_HAS_FPV5,
        },
+       {
+               .partno = STAR_MC1_PARTNO,
+               .name = "STAR-MC1",
+               .arch = ARM_ARCH_V8M,
+               .flags = CORTEX_M_F_HAS_FPV5,
+       },
 };
 
 /* forward declarations */
@@ -663,6 +658,11 @@ static int cortex_m_endreset_event(struct target *target)
 
        register_cache_invalidate(armv7m->arm.core_cache);
 
+       /* TODO: invalidate also working areas (needed in the case of detected reset).
+        * Doing so will require flash drivers to test if working area
+        * is still valid in all target algo calling loops.
+        */
+
        /* make sure we have latest dhcsr flags */
        retval = cortex_m_read_dhcsr_atomic_sticky(target);
        if (retval != ERROR_OK)
@@ -775,7 +775,7 @@ static int cortex_m_examine_exception_reason(struct target *target)
 
 static int cortex_m_debug_entry(struct target *target)
 {
-       uint32_t xPSR;
+       uint32_t xpsr;
        int retval;
        struct cortex_m_common *cortex_m = target_to_cm(target);
        struct armv7m_common *armv7m = &cortex_m->armv7m;
@@ -826,11 +826,11 @@ static int cortex_m_debug_entry(struct target *target)
                return retval;
 
        r = arm->cpsr;
-       xPSR = buf_get_u32(r->value, 0, 32);
+       xpsr = buf_get_u32(r->value, 0, 32);
 
        /* Are we in an exception handler */
-       if (xPSR & 0x1FF) {
-               armv7m->exception_number = (xPSR & 0x1FF);
+       if (xpsr & 0x1FF) {
+               armv7m->exception_number = (xpsr & 0x1FF);
 
                arm->core_mode = ARM_MODE_HANDLER;
                arm->map = armv7m_msp_reg_map;
@@ -879,6 +879,16 @@ 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) {
@@ -1398,8 +1408,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();
 
@@ -1418,24 +1429,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);
 
@@ -1536,7 +1563,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;
@@ -1549,8 +1576,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();
@@ -1558,8 +1586,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) {
@@ -1904,7 +1932,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;
@@ -2397,6 +2425,20 @@ int cortex_m_examine(struct target *target)
                retval = target_read_u32(target, DCB_DHCSR, &cortex_m->dcb_dhcsr);
                if (retval != ERROR_OK)
                        return retval;
+
+               /*  Don't cumulate sticky S_RESET_ST at the very first read of DHCSR
+                *  as S_RESET_ST may indicate a reset that happened long time ago
+                *  (most probably the power-on reset before OpenOCD was started).
+                *  As we are just initializing the debug system we do not need
+                *  to call cortex_m_endreset_event() in the following poll.
+                */
+               if (!cortex_m->dcb_dhcsr_sticky_is_recent) {
+                       cortex_m->dcb_dhcsr_sticky_is_recent = true;
+                       if (cortex_m->dcb_dhcsr & S_RESET_ST) {
+                               LOG_TARGET_DEBUG(target, "reset happened some time ago, ignore");
+                               cortex_m->dcb_dhcsr &= ~S_RESET_ST;
+                       }
+               }
                cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr);
 
                if (!(cortex_m->dcb_dhcsr & C_DEBUGEN)) {

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)