target/arm_adi_v5: search for multiple AP types much more effective way

Cortex-M debug AP could be on AHB3 or AHB5.
Finding AHB3 is fast as AP usually has a low address.
On the other hand, finding AP on the AHB5 equipped device is weird
without this patch. cortex_m_find_mem_ap()
first tries to read IDR from all possible 256 ADIv5 APs and checks
for AHB3 ID and if that fails, starts over and search for AHB5.
It takes long time (74 msec on fast USB HS based STLINK V3J15M7)
and logs lot of rubbish:

Debug: 168 117  target_examine_one(): [stm32u3x.cpu] Examination started
Debug: 169 117  target_call_event_callbacks(): event 19 (examine-start)
Debug: 170 117 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0x0 get 1
Debug: 171 118 arm_adi_v5.c:1226 dap_put_ap(): refcount AP#0x0 put 0
Debug: 172 118 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0x1 get 1
Debug: 173 118 arm_adi_v5.c:1226 dap_put_ap(): refcount AP#0x1 put 0
Debug: 174 118 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0x2 get 1
Debug: 175 119 arm_adi_v5.c:1226 dap_put_ap(): refcount AP#0x2 put 0
...
Debug: 188 123 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0x9 get 1
Debug: 189 123  stlink_usb_error_check(): STLINK_BAD_AP_ERROR
Debug: 190 123 arm_adi_v5.c:1226 dap_put_ap(): refcount AP#0x9 put 0
Debug: 191 123 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0xa get 1
Debug: 192 123  stlink_usb_error_check(): STLINK_BAD_AP_ERROR
Debug: 193 123 arm_adi_v5.c:1226 dap_put_ap(): refcount AP#0xa put 0
...
Debug: 926 190 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0xff get 1
Debug: 927 191  stlink_usb_error_check(): STLINK_BAD_AP_ERROR
Debug: 928 191 arm_adi_v5.c:1226 dap_put_ap(): refcount AP#0xff put 0
Debug: 929 191 arm_adi_v5.c:1154 dap_find_get_ap(): No MEM-AP AHB3 found
Debug: 930 191 arm_adi_v5.c:1201 dap_get_ap(): refcount AP#0x0 get 1
Debug: 931 191 arm_adi_v5.c:1144 dap_find_get_ap(): Found MEM-AP AHB5
 at AP index: 0 (IDR=0x14770015)

Introduce dap_find_by_types_get_ap() to search for the array of AP IDs.

With the patch cortex_m_find_mem_ap() succeeds immediately:

Debug: 168 118  target_examine_one(): [stm32u3x.cpu] Examination started
Debug: 169 118  target_call_event_callbacks(): event 19 (examine-start)
Debug: 170 118 arm_adi_v5.c:1222 dap_get_ap(): refcount AP#0x0 get 1
Debug: 171 118 arm_adi_v5.c:1150 dap_find_by_types_get_ap(): Found MEM-AP
 AHB5 at AP index: 0 (IDR=0x14770015)

Change-Id: Iabcfa1fd64a48febb0f759a213f15d69621ea5cf
Fixes: commit 0d47d85ff5 ("target/cortex_m: Add support for AHB5-AP")
Signed-off-by: Tomas Vanek <vanekt@fbl.cz>
Reviewed-on: https://review.openocd.org/c/openocd/+/9439
Tested-by: jenkins
Reviewed-by: Marc Schink <dev@zapb.de>
This commit is contained in:
Tomas Vanek
2026-02-04 12:45:41 +01:00
parent 7052573187
commit 84f8814003
3 changed files with 51 additions and 13 deletions

View File

@@ -1112,7 +1112,9 @@ bool is_ap_num_valid(struct adiv5_dap *dap, uint64_t ap_num)
* This function checks the ID for each access port to find the requested Access Port type
* It also calls dap_get_ap() to increment the AP refcount
*/
int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adiv5_ap **ap_out)
int dap_find_by_types_get_ap(struct adiv5_dap *dap,
const enum ap_type *types_to_find, unsigned int num_types,
struct adiv5_ap **ap_out)
{
if (is_adiv6(dap)) {
/* TODO: scan the ROM table and detect the AP available */
@@ -1120,6 +1122,8 @@ int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adi
return ERROR_FAIL;
}
assert(num_types > 0);
/* Maximum AP number is 255 since the SELECT register is 8 bits */
for (unsigned int ap_num = 0; ap_num <= DP_APSEL_MAX; ap_num++) {
struct adiv5_ap *ap = dap_get_ap(dap, ap_num);
@@ -1140,18 +1144,39 @@ int dap_find_get_ap(struct adiv5_dap *dap, enum ap_type type_to_find, struct adi
/* Reading register for a non-existent AP should not cause an error,
* but just to be sure, try to continue searching if an error does happen.
*/
if (retval == ERROR_OK && (id_val & AP_TYPE_MASK) == type_to_find) {
if (retval == ERROR_OK) {
for (unsigned int i = 0; i < num_types; i++) {
if ((id_val & AP_TYPE_MASK) == types_to_find[i]) {
LOG_DEBUG("Found %s at AP index: %d (IDR=0x%08" PRIX32 ")",
ap_type_to_description(type_to_find),
ap_type_to_description(types_to_find[i]),
ap_num, id_val);
*ap_out = ap;
return ERROR_OK;
}
}
}
dap_put_ap(ap);
}
LOG_DEBUG("No %s found", ap_type_to_description(type_to_find));
char *types_str = NULL;
for (unsigned int i = 0; i < num_types; i++) {
if (!types_str) {
types_str = strdup(ap_type_to_description(types_to_find[i]));
} else {
char *next_str = alloc_printf("%s, %s", types_str,
ap_type_to_description(types_to_find[i]));
free(types_str);
types_str = next_str;
}
if (!types_str) {
LOG_ERROR("No memory");
return ERROR_FAIL;
}
}
LOG_DEBUG("No %s found", types_str);
free(types_str);
return ERROR_FAIL;
}

View File

@@ -738,11 +738,22 @@ int adiv6_dap_read_baseptr(struct command_invocation *cmd, struct adiv5_dap *dap
/* test if ap_num is valid, based on current knowledge of dap */
bool is_ap_num_valid(struct adiv5_dap *dap, uint64_t ap_num);
/* Probe Access Ports to find a particular type. Increment AP refcount */
int dap_find_get_ap(struct adiv5_dap *dap,
enum ap_type type_to_find,
/* Probe Access Ports to find any type from array.
* Increment AP refcount */
int dap_find_by_types_get_ap(struct adiv5_dap *dap,
const enum ap_type *types_to_find,
unsigned int num_types,
struct adiv5_ap **ap_out);
/* Probe Access Ports to find a particular type. Increment AP refcount */
static inline int dap_find_get_ap(struct adiv5_dap *dap,
enum ap_type type_to_find,
struct adiv5_ap **ap_out)
{
const enum ap_type types[1] = { type_to_find };
return dap_find_by_types_get_ap(dap, types, 1, ap_out);
}
/* Return AP with specified ap_num. Increment AP refcount */
struct adiv5_ap *dap_get_ap(struct adiv5_dap *dap, uint64_t ap_num);

View File

@@ -2775,10 +2775,12 @@ int cortex_m_security_restore(struct target *target, struct cortex_m_saved_secur
static int cortex_m_find_mem_ap(struct adiv5_dap *swjdp,
struct adiv5_ap **debug_ap)
{
if (dap_find_get_ap(swjdp, AP_TYPE_AHB3_AP, debug_ap) == ERROR_OK)
return ERROR_OK;
const enum ap_type types[] = {
AP_TYPE_AHB3_AP,
AP_TYPE_AHB5_AP
};
return dap_find_get_ap(swjdp, AP_TYPE_AHB5_AP, debug_ap);
return dap_find_by_types_get_ap(swjdp, types, ARRAY_SIZE(types), debug_ap);
}
int cortex_m_examine(struct target *target)