This is an automated email from Gerrit.

"Antonio Borneo <[email protected]>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9232

-- gerrit

commit d88d7850cd4ff1cd9a5106b64bbd4b432721ea32
Author: Antonio Borneo <[email protected]>
Date:   Wed Nov 5 14:45:29 2025 +0100

    target: cortex-m: defer cache identification on Cortex-M7 under reset
    
    On Cortex-M7 only, several registers in System Control Space (SCS)
    are not accessible when the CPU is under reset, generating a bus
    error.
    This cause OpenOCD to fail examining the CPU when the board reset
    button is pressed or when the flag 'connect_assert_srst' is used
    on 'reset_config' command.
    
    Introduce a deferred identification of the cache and run it during
    polling and at target halted (just in case of polling disabled).
    
    Change-Id: Ia5c582ae95f825c5fb8c2dcfb320142f7ac04a9f
    Signed-off-by: Antonio Borneo <[email protected]>

diff --git a/src/target/armv7m_cache.c b/src/target/armv7m_cache.c
index cc0c9d1404..f07ac142f9 100644
--- a/src/target/armv7m_cache.c
+++ b/src/target/armv7m_cache.c
@@ -68,7 +68,7 @@ static struct armv7m_cache_size decode_ccsidr(uint32_t ccsidr)
        return size;
 }
 
-int armv7m_identify_cache(struct target *target)
+static int armv7m_identify_cache_internal(struct target *target)
 {
        struct armv7m_common *armv7m = target_to_armv7m(target);
        struct armv7m_cache_common *cache = &armv7m->armv7m_cache;
@@ -191,6 +191,54 @@ int armv7m_identify_cache(struct target *target)
        return ERROR_OK;
 }
 
+/*
+ * On Cortex-M7 only, when the CPU is kept in reset, several registers of the
+ * System Control Space (SCS) are not accessible and return bus error.
+ * The list of accessible registers is:
+ * - 0xE000ED00
+ * - 0xE000ED30
+ * - 0xE000EDF0 ... 0xE000EEFC
+ * - 0xE000EF40 ... 0xE000EF48
+ * - 0xE000EFD0 ... 0xE000EFFC
+ * This makes impossible detecting the cache during the reset.
+ * Use a deferred mechanism to detect the cache during polling or when the
+ * Cortex-M7 halts.
+ */
+int armv7m_identify_cache(struct target *target)
+{
+       struct cortex_m_common *cortex_m = target_to_cm(target);
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct armv7m_cache_common *cache = &armv7m->armv7m_cache;
+
+       if (cache->info_valid)
+               return ERROR_OK;
+
+       if (cortex_m->core_info->impl_part == CORTEX_M7_PARTNO
+                       && cortex_m->dcb_dhcsr & S_RESET_ST) {
+               cache->defer_identification = true;
+               return ERROR_OK;
+       }
+
+       return armv7m_identify_cache_internal(target);
+}
+
+int armv7m_deferred_identify_cache(struct target *target)
+{
+       struct armv7m_common *armv7m = target_to_armv7m(target);
+       struct armv7m_cache_common *cache = &armv7m->armv7m_cache;
+
+       if (cache->info_valid || !cache->defer_identification)
+               return ERROR_OK;
+
+       int retval = armv7m_identify_cache_internal(target);
+       if (retval != ERROR_OK)
+               return retval;
+
+       cache->defer_identification = false;
+
+       return ERROR_OK;
+}
+
 int armv7m_d_cache_flush(struct target *target, uint32_t address,
        unsigned int length)
 {
@@ -250,6 +298,11 @@ int armv7m_handle_cache_info_command(struct 
command_invocation *cmd,
                return ERROR_FAIL;
        }
 
+       if (cache->defer_identification) {
+               command_print(cmd, "Cache not detected yet");
+               return ERROR_OK;
+       }
+
        if (!cache->info_valid) {
                command_print(cmd, "No cache detected");
                return ERROR_OK;
diff --git a/src/target/armv7m_cache.h b/src/target/armv7m_cache.h
index 576bff8d6b..e6d943209c 100644
--- a/src/target/armv7m_cache.h
+++ b/src/target/armv7m_cache.h
@@ -38,6 +38,7 @@ struct armv7m_arch_cache {
 // common cache information
 struct armv7m_cache_common {
        bool info_valid;
+       bool defer_identification;
        bool has_i_cache;
        bool has_d_u_cache;
        unsigned int loc;                                       // level of 
coherency
@@ -47,6 +48,7 @@ struct armv7m_cache_common {
 };
 
 int armv7m_identify_cache(struct target *target);
+int armv7m_deferred_identify_cache(struct target *target);
 int armv7m_d_cache_flush(struct target *target, uint32_t address,
        unsigned int length);
 int armv7m_i_cache_inval(struct target *target, uint32_t address,
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 9f0b6284b0..3c094587f6 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -876,6 +876,11 @@ static int cortex_m_debug_entry(struct target *target)
        }
 
        // read caches state
+       if (!armv7m->is_hla_target) {
+               retval = armv7m_deferred_identify_cache(target);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
        uint32_t ccr = 0;
        if (armv7m->armv7m_cache.info_valid) {
                retval = mem_ap_read_u32(armv7m->debug_ap, CCR, &ccr);
@@ -1018,6 +1023,12 @@ static int cortex_m_poll_one(struct target *target)
 
                /* S_RESET_ST was expected (in a reset command). Continue 
processing
                 * to quickly get out of TARGET_RESET state */
+       } else {
+               if (!armv7m->is_hla_target) {
+                       retval = armv7m_deferred_identify_cache(target);
+                       if (retval != ERROR_OK)
+                               return retval;
+               }
        }
 
        if (target->state == TARGET_RESET) {
@@ -2937,6 +2948,18 @@ int cortex_m_examine(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
+               /*
+                * Use a safe value of sticky S_RESET_ST for cache detection, 
before
+                * clearing it below.
+                */
+               if (!armv7m->is_hla_target) {
+                       retval = armv7m_identify_cache(target);
+                       if (retval != ERROR_OK) {
+                               LOG_ERROR("Cannot detect cache");
+                               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).
@@ -3006,14 +3029,6 @@ int cortex_m_examine(struct target *target)
                LOG_TARGET_INFO(target, "target has %d breakpoints, %d 
watchpoints",
                        cortex_m->fp_num_code,
                        cortex_m->dwt_num_comp);
-
-               if (!armv7m->is_hla_target) {
-                       retval = armv7m_identify_cache(target);
-                       if (retval != ERROR_OK) {
-                               LOG_ERROR("Cannot detect cache");
-                               return retval;
-                       }
-               }
        }
 
        return ERROR_OK;

-- 

Reply via email to