cortex_m: Restore fast register reads if no polling is needed
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>
Mon, 8 Nov 2021 17:09:56 +0000 (18:09 +0100)
committerTomas Vanek <vanekt@fbl.cz>
Thu, 18 Nov 2021 21:13:19 +0000 (21:13 +0000)
If the target is in a state where S_REGRDY polling is necessary (slow
clock, low power state...?), OpenOCD will continue to use the slow
path even if the condition is temporary and the target at a later
point would be capable of fast reads again.

Revert to fast reads if a full register dump can be made without need
for polling any of the registers; presumably it will succeed the next
time too.

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

index 82d5eff80055c7a5ccd5b54a15d452436454a8a9..721cf0a2469b9acdaccdda10471c3154fccdb2bc 100644 (file)
@@ -183,6 +183,7 @@ static int cortex_m_load_core_reg_u32(struct target *target,
                cortex_m_cumulate_dhcsr_sticky(cortex_m, cortex_m->dcb_dhcsr);
                if (cortex_m->dcb_dhcsr & S_REGRDY)
                        break;
+               cortex_m->slow_register_read = true; /* Polling (still) needed. */
                if (timeval_ms() > then + DHCSR_S_REGRDY_TIMEOUT) {
                        LOG_ERROR("Timeout waiting for DCRDR transfer ready");
                        return ERROR_TIMEOUT_REACHED;
@@ -204,9 +205,14 @@ static int cortex_m_load_core_reg_u32(struct target *target,
 
 static int cortex_m_slow_read_all_regs(struct target *target)
 {
+       struct cortex_m_common *cortex_m = target_to_cm(target);
        struct armv7m_common *armv7m = target_to_armv7m(target);
        const unsigned int num_regs = armv7m->arm.core_cache->num_regs;
 
+       /* Opportunistically restore fast read, it'll revert to slow
+        * if any register needed polling in cortex_m_load_core_reg_u32(). */
+       cortex_m->slow_register_read = false;
+
        for (unsigned int reg_id = 0; reg_id < num_regs; reg_id++) {
                struct reg *r = &armv7m->arm.core_cache->reg_list[reg_id];
                if (r->exist) {
@@ -215,6 +221,10 @@ static int cortex_m_slow_read_all_regs(struct target *target)
                                return retval;
                }
        }
+
+       if (!cortex_m->slow_register_read)
+               LOG_DEBUG("Switching back to fast register reads");
+
        return ERROR_OK;
 }