target/cortex_m: supress historical reset detection
authorTomas Vanek <vanekt@fbl.cz>
Tue, 2 Aug 2022 09:44:43 +0000 (11:44 +0200)
committerAntonio Borneo <borneo.antonio@gmail.com>
Mon, 15 Aug 2022 13:23:57 +0000 (13:23 +0000)
The S_RESET_ST sticky bit is reset after DHCSR read.
It is set at power-on reset and keeps active until the debuger reads DHCSR.

Ignore S_RESET_ST at the very first read after OpenOCD start
and suppress possibly misleading message "external reset detected"
if we cannot guarantee the reset happened recently.

While on it add a TODO comment.

Change-Id: I15217c2ca6f69ac97aff8be86bce67cba94a42cd
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/7109
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/target/cortex_m.c
src/target/cortex_m.h

index 9497aa0373a0e8aee94b15a8ab3ba66e47065845..aeaeb182945dd6992be42552b153c08baf884f45 100644 (file)
@@ -652,6 +652,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)
@@ -2396,6 +2401,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)) {
index 168613590fb7c2e6eeeab547615414b56e675620..69368a919e448f8e0aa7527e620bbb8386be2b1e 100644 (file)
@@ -206,6 +206,8 @@ struct cortex_m_common {
        /* Context information */
        uint32_t dcb_dhcsr;
        uint32_t dcb_dhcsr_cumulated_sticky;
+       /* DCB DHCSR has been at least once read, so the sticky bits have been reset */
+       bool dcb_dhcsr_sticky_is_recent;
        uint32_t nvic_dfsr;  /* Debug Fault Status Register - shows reason for debug halt */
        uint32_t nvic_icsr;  /* Interrupt Control State Register - shows active and pending IRQ */