This is an automated email from Gerrit. "liangzhen <[email protected]>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/9221
-- gerrit commit fdf0d1484ac4654a9478216da563c9fb188fdccc Author: liangzhen <[email protected]> Date: Tue May 6 14:15:56 2025 +0800 target/riscv: activate dm before get nextdm when Debug Module is inactive, accesses to the nextdm may fail. Specifically, nextdm might not return correct data. Change-Id: Ib19ece315af6e0c4a066f79c0270c119398c3606 Signed-off-by: liangzhen <[email protected]> diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 6fa5e025be..d76c0a427b 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -534,7 +534,33 @@ static int dm_write(struct target *target, uint32_t address, uint32_t value) return dmi_write(target, riscv013_get_dmi_address(target, address), value); } -static bool check_dbgbase_exists(struct target *target) +static int activate_dm(struct target *target, uint32_t dm_base_addr) +{ + uint32_t dmcontrol = 0; + + LOG_TARGET_DEBUG(target, "Activating the DM with DMI base address (dbgbase) = 0x%x", dm_base_addr); + if (dmi_write(target, DM_DMCONTROL + dm_base_addr, DM_DMCONTROL_DMACTIVE) != ERROR_OK) + return ERROR_FAIL; + + const time_t start = time(NULL); + LOG_TARGET_DEBUG(target, "Waiting for the DM to become active."); + while (1) { + if (dmi_read(target, &dmcontrol, DM_DMCONTROL + dm_base_addr) != ERROR_OK) + return ERROR_FAIL; + if (get_field32(dmcontrol, DM_DMCONTROL_DMACTIVE)) + break; + if (time(NULL) - start > riscv_get_command_timeout_sec()) { + LOG_TARGET_ERROR(target, "Debug Module (at address dbgbase=0x%" PRIx32 ") did not become active in %d s. " + "Increase the timeout with 'riscv set_command_timeout_sec'.", + dm_base_addr, riscv_get_command_timeout_sec()); + return ERROR_TIMEOUT_REACHED; + } + } + LOG_TARGET_DEBUG(target, "DM has become active."); + return ERROR_OK; +} + +static int check_dbgbase_exists(struct target *target) { uint32_t next_dm = 0; unsigned int count = 1; @@ -544,7 +570,14 @@ static bool check_dbgbase_exists(struct target *target) while (1) { uint32_t current_dm = next_dm; if (current_dm == target->dbgbase) - return true; + return ERROR_OK; + + uint32_t dmcontrol = 0; + if (dmi_read(target, &dmcontrol, DM_DMCONTROL + current_dm) != ERROR_OK) + break; + if (!get_field32(dmcontrol, DM_DMCONTROL_DMACTIVE) && activate_dm(target, current_dm) != ERROR_OK) + break; + if (dmi_read(target, &next_dm, DM_NEXTDM + current_dm) != ERROR_OK) break; LOG_TARGET_DEBUG(target, "dm @ 0x%x --> nextdm=0x%x", current_dm, next_dm); @@ -565,7 +598,7 @@ static bool check_dbgbase_exists(struct target *target) break; } } - return false; + return ERROR_FAIL; } static int dmstatus_read(struct target *target, uint32_t *dmstatus, @@ -1875,27 +1908,13 @@ static int reset_dm(struct target *target) } while (get_field32(dmcontrol, DM_DMCONTROL_DMACTIVE)); LOG_TARGET_DEBUG(target, "DM reset initiated."); } + /* TODO: Move the code above into `deactivate_dm()` function + * (a logical counterpart to activate_dm()). */ - LOG_TARGET_DEBUG(target, "Activating the DM."); - result = dm_write(target, DM_DMCONTROL, DM_DMCONTROL_DMACTIVE); + result = activate_dm(target, dm->base); if (result != ERROR_OK) return result; - const time_t start = time(NULL); - LOG_TARGET_DEBUG(target, "Waiting for the DM to come out of reset."); - do { - result = dm_read(target, &dmcontrol, DM_DMCONTROL); - if (result != ERROR_OK) - return result; - - if (time(NULL) - start > riscv_get_command_timeout_sec()) { - LOG_TARGET_ERROR(target, "Debug Module did not become active in %d s. " - "Increase the timeout with 'riscv set_command_timeout_sec'.", - riscv_get_command_timeout_sec()); - return ERROR_TIMEOUT_REACHED; - } - } while (!get_field32(dmcontrol, DM_DMCONTROL_DMACTIVE)); - LOG_TARGET_DEBUG(target, "DM successfully reset."); dm->was_reset = true; return ERROR_OK; @@ -2050,7 +2069,7 @@ static int examine(struct target *target) info->abits, RISCV013_DTMCS_ABITS_MIN); } - if (!check_dbgbase_exists(target)) { + if (check_dbgbase_exists(target) != ERROR_OK) { LOG_TARGET_ERROR(target, "Could not find debug module with DMI base address (dbgbase) = 0x%x", target->dbgbase); return ERROR_FAIL; } --
