target/adi: unify DPIDR TARGETID handling in adiv5_dp_init

this makes the assumption that DPs will be v1 or higher, for SWD-DP scans this is
guaranteed, but on JTAG-SCANS it may not be true, DPv0 does not have DPIDR
implemented and reads are UNPREDICTABLE

Signed-off-by: Rafael Silva <perigoso@riseup.net>
This commit is contained in:
Rafael Silva 2022-08-06 02:17:47 +01:00 committed by Rachel Mant
parent c04b98435a
commit ce6477886f
8 changed files with 157 additions and 134 deletions

View File

@ -130,17 +130,6 @@ int jlink_swdp_scan(bmp_info_t *info)
return 0; return 0;
} }
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_ALL) {
dp->debug_port_id = jlink_adiv5_swdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_DPIDR, 0);
}
if (e.type) {
DEBUG_WARN("DP not responding for DPIDR! Reset stuck low?\n");
free(dp);
return 0;
}
dp->version = (dp->debug_port_id & ADIV5_DP_DPIDR_VERSION_MASK) >> ADIV5_DP_DPIDR_VERSION_OFFSET;
dp->dp_read = jlink_adiv5_swdp_read; dp->dp_read = jlink_adiv5_swdp_read;
dp->error = jlink_adiv5_swdp_error; dp->error = jlink_adiv5_swdp_error;
dp->low_access = jlink_adiv5_swdp_low_access; dp->low_access = jlink_adiv5_swdp_low_access;
@ -148,14 +137,8 @@ int jlink_swdp_scan(bmp_info_t *info)
jlink_adiv5_swdp_error(dp); jlink_adiv5_swdp_error(dp);
if (dp->version >= 2) {
/* READ TARGETID, only available on DPv2 or later */
adiv5_dp_write(dp, ADIV5_DP_SELECT, 2); /* TARGETID is on bank 2 */
dp->target_id = adiv5_dp_read(dp, ADIV5_DP_TARGETID);
adiv5_dp_write(dp, ADIV5_DP_SELECT, 0);
}
adiv5_dp_init(dp); adiv5_dp_init(dp);
return target_list ? 1U : 0U; return target_list ? 1U : 0U;
} }

View File

@ -673,15 +673,15 @@ static int stlink_enter_debug_jtag(bmp_info_t *info)
return stlink_usb_error_check(data, true); return stlink_usb_error_check(data, true);
} }
static uint32_t stlink_read_coreid(void) // static uint32_t stlink_read_coreid(void)
{ // {
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND, STLINK_DEBUG_APIV2_READ_IDCODES}; // uint8_t cmd[16] = {STLINK_DEBUG_COMMAND, STLINK_DEBUG_APIV2_READ_IDCODES};
uint8_t data[12]; // uint8_t data[12];
send_recv(info.usb_link, cmd, 16, data, 12); // send_recv(info.usb_link, cmd, 16, data, 12);
uint32_t id = data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24; // uint32_t id = data[4] | data[5] << 8 | data[6] << 16 | data[7] << 24;
DEBUG_INFO("Read Core ID: 0x%08" PRIx32 "\n", id); // DEBUG_INFO("Read Core ID: 0x%08" PRIx32 "\n", id);
return id; // return id;
} // }
static int stlink_read_idcodes(bmp_info_t *info, uint32_t *idcodes) static int stlink_read_idcodes(bmp_info_t *info, uint32_t *idcodes)
{ {
@ -1070,15 +1070,16 @@ void stlink_adiv5_dp_defaults(ADIv5_DP_t *dp)
int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp) int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp)
{ {
stlink_leave_state(info); stlink_leave_state(info);
uint8_t cmd[16] = {STLINK_DEBUG_COMMAND, uint8_t cmd[16] = {STLINK_DEBUG_COMMAND,
STLINK_DEBUG_APIV2_ENTER, STLINK_DEBUG_APIV2_ENTER,
STLINK_DEBUG_ENTER_SWD_NO_RESET}; STLINK_DEBUG_ENTER_SWD_NO_RESET};
uint8_t data[2]; uint8_t data[2];
stlink_send_recv_retry(cmd, 16, data, 2); stlink_send_recv_retry(cmd, 16, data, 2);
if (stlink_usb_error_check(data, true)) if (stlink_usb_error_check(data, true))
exit( -1); exit( -1);
dp->debug_port_id = stlink_read_coreid();
dp->version = (dp->debug_port_id & ADIV5_DP_DPIDR_VERSION_MASK) >> ADIV5_DP_DPIDR_VERSION_OFFSET;
dp->dp_read = stlink_dp_read; dp->dp_read = stlink_dp_read;
dp->error = stlink_dp_error; dp->error = stlink_dp_error;
@ -1087,12 +1088,6 @@ int stlink_enter_debug_swd(bmp_info_t *info, ADIv5_DP_t *dp)
stlink_dp_error(dp); stlink_dp_error(dp);
if (dp->version >= 2) {
/* READ TARGETID, only available on DPv2 or later */
adiv5_dp_write(dp, ADIV5_DP_SELECT, 2); /* TARGETID is on bank 2 */
dp->target_id = adiv5_dp_read(dp, ADIV5_DP_TARGETID);
adiv5_dp_write(dp, ADIV5_DP_SELECT, 0);
}
return 0; return 0;
} }

View File

@ -474,8 +474,8 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, const size_t re
/* CIDR preamble sanity check */ /* CIDR preamble sanity check */
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) { if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) {
DEBUG_WARN("%s%" PRIu32 " 0x%08" PRIx32 ": 0x%08" PRIx32 " <- does not match preamble (0x%08" PRIx32 ")\n", indent + 1, DEBUG_WARN("%s%" PRIu32 " 0x%08" PRIx32 ": 0x%08" PRIx32 " <- does not match preamble (0x%08" PRIx32 ")\n",
num_entry, addr, cidr, CID_PREAMBLE); indent + 1, num_entry, addr, cidr, CID_PREAMBLE);
return; return;
} }
@ -586,8 +586,8 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, const size_t re
arm_component_lut[i].arch_id != arch_id) arm_component_lut[i].arch_id != arch_id)
continue; continue;
DEBUG_INFO("%s%" PRIu32 " 0x%" PRIx32 ": %s - %s %s (PIDR = 0x%08" PRIx32 "%08" PRIx32 DEBUG_INFO("%s%" PRIu32 " 0x%" PRIx32 ": %s - %s %s (PIDR = 0x%08" PRIx32 "%08" PRIx32 " DEVTYPE = 0x%02x "
" DEVTYPE = 0x%02x ARCHID = 0x%04x)\n", "ARCHID = 0x%04x)\n",
indent + 1, num_entry, addr, cidc_debug_strings[cid_class], arm_component_lut[i].type, indent + 1, num_entry, addr, cidc_debug_strings[cid_class], arm_component_lut[i].type,
arm_component_lut[i].full, (uint32_t)(pidr >> 32U), (uint32_t)pidr, dev_type, arch_id); arm_component_lut[i].full, (uint32_t)(pidr >> 32U), (uint32_t)pidr, dev_type, arch_id);
@ -612,8 +612,9 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, const size_t re
break; break;
} }
if (arm_component_lut[i].arch == aa_end) { if (arm_component_lut[i].arch == aa_end) {
DEBUG_WARN("%s%" PRIu32 " 0x%" PRIx32 ": %s - Unknown (PIDR = 0x%08" PRIx32 "%08" PRIx32 DEBUG_WARN("%s%" PRIu32 " 0x%" PRIx32 ": %s - Unknown (PIDR = 0x%08" PRIx32 "%08" PRIx32 " DEVTYPE = "
" DEVTYPE = 0x%02x ARCHID = 0x%04x)\n", "0x%02x ARCHID = "
"0x%04x)\n",
indent, num_entry, addr, cidc_debug_strings[cid_class], (uint32_t)(pidr >> 32U), (uint32_t)pidr, indent, num_entry, addr, cidc_debug_strings[cid_class], (uint32_t)(pidr >> 32U), (uint32_t)pidr,
dev_type, arch_id); dev_type, arch_id);
} }
@ -682,44 +683,82 @@ static void rp_rescue_setup(ADIv5_DP_t *dp)
void adiv5_dp_init(ADIv5_DP_t *dp) void adiv5_dp_init(ADIv5_DP_t *dp)
{ {
/* designer code is in the same format in IDCODE and DPIDR */
/* common handling */
/* /*
* the code in the DPIDR/IDCODE is in the form * Assume DP v1 or later.
* Bits 10:7 - JEP-106 Continuation code * this may not be true for JTAG-DP
* Bits 6:0 - JEP-106 Identity code * in such cases (DPv0) DPIDR is not implemented
* here we convert it to our internal representation, See JEP-106 code list * and reads are UNPREDICTABLE.
* note, this is the code of the designer not the implementer, we expect it to be ARM *
* for SWD-DP, we are guaranteed to be DP v1 or later.
*/ */
const uint16_t designer = (dp->debug_port_id & ADIV5_DP_DPIDR_DESIGNER_MASK) >> ADIV5_DP_DPIDR_DESIGNER_OFFSET; volatile uint32_t dpidr;
dp->designer_code = volatile struct exception e;
(designer & ADIV5_DP_DESIGNER_JEP106_CONT_MASK) << 1U | (designer & ADIV5_DP_DESIGNER_JEP106_CODE_MASK); TRY_CATCH (e, EXCEPTION_ALL) {
dpidr = adiv5_dp_read(dp, ADIV5_DP_DPIDR);
/* on JTAG IDCODE this is actually the version */
dp->revision = (dp->debug_port_id & ADIV5_DP_DPIDR_REVISION_MASK) >> ADIV5_DP_DPIDR_REVISION_OFFSET;
if (dp->version > 0) {
/* debug_port_id is valid DPIDR */
dp->partno = (dp->debug_port_id & ADIV5_DP_DPIDR_PARTNO_MASK) >> ADIV5_DP_DPIDR_PARTNO_OFFSET;
dp->mindp = !!(dp->debug_port_id & ADIV5_DP_DPIDR_MINDP);
} else {
/* called from JTAG scan, debug_port_id is JTAG TAP IDCODE */
dp->partno = (dp->debug_port_id & JTAG_IDCODE_PARTNO_MASK) >> JTAG_IDCODE_PARTNO_OFFSET;
dp->mindp = false;
} }
if (e.type) {
/* Check for a valid designer */ DEBUG_WARN("DP not responding!...\n");
if (dp->designer_code == 0) {
DEBUG_WARN("Invalid DP ID %08" PRIx32 "\n", dp->debug_port_id);
free(dp); free(dp);
return; return;
} }
DEBUG_INFO("DP ID 0x%08" PRIx32 " (v%d %srev%d) designer 0x%" PRIx32 " partno 0x%" PRIx32 "\n", dp->debug_port_id, dp->version = (dpidr & ADIV5_DP_DPIDR_VERSION_MASK) >> ADIV5_DP_DPIDR_VERSION_OFFSET;
dp->version, dp->mindp ? "MINDP " : "", dp->revision, dp->designer_code, dp->partno); if (dp->version > 0 && (dpidr & 1U)) {
/*
* the code in the DPIDR is in the form
* Bits 10:7 - JEP-106 Continuation code
* Bits 6:0 - JEP-106 Identity code
* here we convert it to our internal representation, See JEP-106 code list
*
* note: this is the code of the designer not the implementer, we expect it to be ARM
*/
const uint16_t designer = (dpidr & ADIV5_DP_DPIDR_DESIGNER_MASK) >> ADIV5_DP_DPIDR_DESIGNER_OFFSET;
dp->designer_code =
(designer & ADIV5_DP_DESIGNER_JEP106_CONT_MASK) << 1U | (designer & ADIV5_DP_DESIGNER_JEP106_CODE_MASK);
dp->partno = (dpidr & ADIV5_DP_DPIDR_PARTNO_MASK) >> ADIV5_DP_DPIDR_PARTNO_OFFSET;
if (dp->version >= 2 && dp->target_id != 0) dp->mindp = !!(dpidr & ADIV5_DP_DPIDR_MINDP);
DEBUG_INFO("TARGETID 0x%08" PRIx32 "\n", dp->target_id);
/* Check for a valid DPIDR / designer */
if (dp->designer_code != 0) {
DEBUG_INFO("DP DPIDR 0x%08" PRIx32 " (v%d %srev%d) designer 0x%" PRIx32 " partno 0x%" PRIx32 "\n", dpidr,
dp->version, dp->mindp ? "MINDP " : "",
(dpidr & ADIV5_DP_DPIDR_REVISION_MASK) >> ADIV5_DP_DPIDR_REVISION_OFFSET, dp->designer_code,
dp->partno);
} else {
DEBUG_WARN("Invalid DPIDR %08" PRIx32 " assuming DP version 0\n", dpidr);
dp->version = 0;
}
}
if (dp->version == 0) {
/* DP v0 */
DEBUG_WARN("DPv0 detected, no designer code available\n", dpidr);
dp->designer_code = 0;
dp->partno = 0;
dp->mindp = 0;
}
if (dp->version >= 2) {
adiv5_dp_write(dp, ADIV5_DP_SELECT, 2); /* TARGETID is on bank 2 */
const uint32_t targetid = adiv5_dp_read(dp, ADIV5_DP_TARGETID);
adiv5_dp_write(dp, ADIV5_DP_SELECT, 0);
/* Use TARGETID register to identify target */
const uint16_t tdesigner = (targetid & ADIV5_DP_TARGETID_TDESIGNER_MASK) >> ADIV5_DP_TARGETID_TDESIGNER_OFFSET;
/* convert it to our internal representation, See JEP-106 code list */
dp->target_designer_code =
(tdesigner & ADIV5_DP_DESIGNER_JEP106_CONT_MASK) << 1U | (tdesigner & ADIV5_DP_DESIGNER_JEP106_CODE_MASK);
dp->target_partno = (targetid & ADIV5_DP_TARGETID_TPARTNO_MASK) >> ADIV5_DP_TARGETID_TPARTNO_OFFSET;
DEBUG_INFO("TARGETID 0x%08" PRIx32 " designer 0x%" PRIx32 " partno 0x%" PRIx32 "\n", targetid,
dp->target_designer_code, dp->target_partno);
dp->targetsel = dp->instance << ADIV5_DP_TARGETSEL_TINSTANCE_OFFSET |
(targetid & (ADIV5_DP_TARGETID_TDESIGNER_MASK | ADIV5_DP_TARGETID_TPARTNO_MASK)) | 1U;
}
if (dp->designer_code == JEP106_MANUFACTURER_RASPBERRY && dp->partno == 0x2) { if (dp->designer_code == JEP106_MANUFACTURER_RASPBERRY && dp->partno == 0x2) {
rp_rescue_setup(dp); rp_rescue_setup(dp);
@ -744,7 +783,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
#endif #endif
volatile uint32_t ctrlstat = 0; volatile uint32_t ctrlstat = 0;
volatile struct exception e;
TRY_CATCH (e, EXCEPTION_TIMEOUT) { TRY_CATCH (e, EXCEPTION_TIMEOUT) {
ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT);
} }

View File

@ -235,9 +235,6 @@ typedef struct ADIv5_AP_s ADIv5_AP_t;
typedef struct ADIv5_DP_s { typedef struct ADIv5_DP_s {
int refcnt; int refcnt;
uint32_t debug_port_id;
uint32_t target_id; /* present on DPv2 or later */
void (*seq_out)(uint32_t tms_states, size_t clock_cycles); void (*seq_out)(uint32_t tms_states, size_t clock_cycles);
void (*seq_out_parity)(uint32_t tms_states, size_t clock_cycles); void (*seq_out_parity)(uint32_t tms_states, size_t clock_cycles);
uint32_t (*seq_in)(size_t clock_cycles); uint32_t (*seq_in)(size_t clock_cycles);
@ -267,14 +264,21 @@ typedef struct ADIv5_DP_s {
uint8_t dp_jd_index; uint8_t dp_jd_index;
uint8_t fault; uint8_t fault;
/* targetsel DPv2 */
uint8_t instance;
uint32_t targetsel;
uint8_t version; uint8_t version;
uint8_t revision;
bool mindp; bool mindp;
/* DP designer (not implementer!) and partno */ /* DP designer (not implementer!) and partno */
uint16_t designer_code; uint16_t designer_code;
uint16_t partno; uint16_t partno;
/* TARGETID designer and partno, present on DPv2 */
uint16_t target_designer_code;
uint16_t target_partno;
} ADIv5_DP_t; } ADIv5_DP_t;
struct ADIv5_AP_s { struct ADIv5_AP_s {

View File

@ -48,14 +48,14 @@ void adiv5_jtag_dp_handler(uint8_t jd_index)
} }
dp->dp_jd_index = jd_index; dp->dp_jd_index = jd_index;
/* JTAG routine passes IDCODE to port ID and version = 0 */
dp->debug_port_id = jtag_devs[jd_index].jd_idcode;
if ((PC_HOSTED == 0) || (!platform_jtag_dp_init(dp))) { if ((PC_HOSTED == 0) || (!platform_jtag_dp_init(dp))) {
dp->dp_read = fw_adiv5_jtagdp_read; dp->dp_read = fw_adiv5_jtagdp_read;
dp->error = adiv5_jtagdp_error; dp->error = adiv5_jtagdp_error;
dp->low_access = fw_adiv5_jtagdp_low_access; dp->low_access = fw_adiv5_jtagdp_low_access;
dp->abort = adiv5_jtagdp_abort; dp->abort = adiv5_jtagdp_abort;
} }
adiv5_dp_init(dp); adiv5_dp_init(dp);
} }

View File

@ -70,7 +70,9 @@ bool firmware_dp_low_write(ADIv5_DP_t *dp, uint16_t addr, const uint32_t data)
int adiv5_swdp_scan(uint32_t targetid) int adiv5_swdp_scan(uint32_t targetid)
{ {
volatile struct exception e; volatile struct exception e;
target_list_free(); target_list_free();
ADIv5_DP_t idp = { ADIv5_DP_t idp = {
.dp_low_write = firmware_dp_low_write, .dp_low_write = firmware_dp_low_write,
.error = firmware_swdp_error, .error = firmware_swdp_error,
@ -79,8 +81,10 @@ int adiv5_swdp_scan(uint32_t targetid)
.abort = firmware_swdp_abort, .abort = firmware_swdp_abort,
}; };
ADIv5_DP_t *initial_dp = &idp; ADIv5_DP_t *initial_dp = &idp;
if (swdptap_init(initial_dp)) if (swdptap_init(initial_dp))
return -1; return -1;
/* DORMANT-> SWD sequence*/ /* DORMANT-> SWD sequence*/
initial_dp->seq_out(0xFFFFFFFF, 32); initial_dp->seq_out(0xFFFFFFFF, 32);
initial_dp->seq_out(0xFFFFFFFF, 32); initial_dp->seq_out(0xFFFFFFFF, 32);
@ -93,26 +97,33 @@ int adiv5_swdp_scan(uint32_t targetid)
* 0x1a Arm CoreSight SW-DP activation sequence * 0x1a Arm CoreSight SW-DP activation sequence
* 20 bits start of reset another reset sequence*/ * 20 bits start of reset another reset sequence*/
initial_dp->seq_out(0x1a0, 12); initial_dp->seq_out(0x1a0, 12);
bool scan_multidrop = true; bool scan_multidrop = true;
if (!targetid || !initial_dp->dp_low_write) { volatile uint32_t dp_targetid = targetid;
/* No targetID given on the command line or probe can not
* handle multi-drop. Try to read ID */ if (!dp_targetid) {
/* No targetID given on the command line Try to read ID */
scan_multidrop = false;
dp_line_reset(initial_dp); dp_line_reset(initial_dp);
volatile uint32_t dp_dpidr;
TRY_CATCH (e, EXCEPTION_ALL) { TRY_CATCH (e, EXCEPTION_ALL) {
initial_dp->debug_port_id = initial_dp->dp_read(initial_dp, ADIV5_DP_DPIDR); dp_dpidr = initial_dp->dp_read(initial_dp, ADIV5_DP_DPIDR);
} }
if (e.type || initial_dp->fault) { if (e.type || initial_dp->fault) {
scan_multidrop = false;
DEBUG_WARN("Trying old JTAG to SWD sequence\n"); DEBUG_WARN("Trying old JTAG to SWD sequence\n");
initial_dp->seq_out(0xFFFFFFFF, 32); initial_dp->seq_out(0xFFFFFFFF, 32);
initial_dp->seq_out(0xFFFFFFFF, 32); initial_dp->seq_out(0xFFFFFFFF, 32);
initial_dp->seq_out(0xE79E, 16); /* 0b0111100111100111 */ initial_dp->seq_out(0xE79E, 16); /* 0b0111100111100111 */
dp_line_reset(initial_dp); dp_line_reset(initial_dp);
initial_dp->fault = 0; initial_dp->fault = 0;
TRY_CATCH (e, EXCEPTION_ALL) { TRY_CATCH (e, EXCEPTION_ALL) {
initial_dp->debug_port_id = initial_dp->dp_read(initial_dp, ADIV5_DP_DPIDR); dp_dpidr = initial_dp->dp_read(initial_dp, ADIV5_DP_DPIDR);
} }
if (e.type || initial_dp->fault) { if (e.type || initial_dp->fault) {
DEBUG_WARN("No usable DP found\n"); DEBUG_WARN("No usable DP found\n");
@ -120,68 +131,64 @@ int adiv5_swdp_scan(uint32_t targetid)
} }
} }
initial_dp->version = const uint8_t dp_version = (dp_dpidr & ADIV5_DP_DPIDR_VERSION_MASK) >> ADIV5_DP_DPIDR_VERSION_OFFSET;
(initial_dp->debug_port_id & ADIV5_DP_DPIDR_VERSION_MASK) >> ADIV5_DP_DPIDR_VERSION_OFFSET; if (dp_version >= 2) {
if (initial_dp->version >= 2) {
scan_multidrop = true; scan_multidrop = true;
/* Read TargetID. Can be done with device in WFI, sleep or reset!*/ /* Read TargetID. Can be done with device in WFI, sleep or reset!*/
adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 2); /* TARGETID is on bank 2 */ adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 2); /* TARGETID is on bank 2 */
initial_dp->target_id = adiv5_dp_read(initial_dp, ADIV5_DP_TARGETID); dp_targetid = adiv5_dp_read(initial_dp, ADIV5_DP_TARGETID);
adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 0); adiv5_dp_write(initial_dp, ADIV5_DP_SELECT, 0);
const uint16_t tdesigner = const uint16_t tdesigner =
(initial_dp->target_id & ADIV5_DP_TARGETID_TDESIGNER_MASK) >> ADIV5_DP_TARGETID_TDESIGNER_OFFSET; (dp_targetid & ADIV5_DP_TARGETID_TDESIGNER_MASK) >> ADIV5_DP_TARGETID_TDESIGNER_OFFSET;
const uint16_t tpartno = const uint16_t tpartno = (dp_targetid & ADIV5_DP_TARGETID_TPARTNO_MASK) >> ADIV5_DP_TARGETID_TPARTNO_OFFSET;
(initial_dp->target_id & ADIV5_DP_TARGETID_TPARTNO_MASK) >> ADIV5_DP_TARGETID_TPARTNO_OFFSET;
/* convert it to our internal representation, See JEP-106 code list */ /* convert it to our internal representation, See JEP-106 code list */
const uint16_t designer_code = (tdesigner & ADIV5_DP_DESIGNER_JEP106_CONT_MASK) << 1U | const uint16_t designer_code = (tdesigner & ADIV5_DP_DESIGNER_JEP106_CONT_MASK) << 1U |
(tdesigner & ADIV5_DP_DESIGNER_JEP106_CODE_MASK); (tdesigner & ADIV5_DP_DESIGNER_JEP106_CODE_MASK);
if (designer_code == JEP106_MANUFACTURER_RASPBERRY && tpartno == 0x2) {
if (designer_code == JEP106_MANUFACTURER_RASPBERRY && tpartno == 0x1002) {
/* RP2040 */ /* RP2040 */
/* Release evt. handing RESCUE DP reset*/ /* Release evt. handing RESCUE DP reset*/
adiv5_dp_write(initial_dp, ADIV5_DP_CTRLSTAT, 0); adiv5_dp_write(initial_dp, ADIV5_DP_CTRLSTAT, 0);
} }
}
}
if (!initial_dp->dp_low_write) { if (!initial_dp->dp_low_write) {
DEBUG_WARN("CMSIS_DAP < V1.2 can not handle multi-drop!\n"); DEBUG_WARN("CMSIS_DAP < V1.2 can not handle multi-drop!\n");
/* E.g. CMSIS_DAP < V1.2 can not handle multi-drop!*/ /* E.g. CMSIS_DAP < V1.2 can not handle multi-drop!*/
scan_multidrop = false; scan_multidrop = false;
} }
} else {
scan_multidrop = false; DEBUG_WARN("scan_multidrop: %s\n", scan_multidrop ? "true" : "false");
}
} else { const volatile size_t max_dp = (scan_multidrop) ? 16U : 1U;
initial_dp->target_id = targetid; for (volatile size_t i = 0; i < max_dp; i++) {
}
const volatile size_t nr_dps = (scan_multidrop) ? 16U : 1U;
volatile uint32_t dp_targetid;
volatile uint32_t dp_debug_port_id;
for (volatile size_t i = 0; i < nr_dps; i++) {
if (scan_multidrop) { if (scan_multidrop) {
dp_line_reset(initial_dp); dp_line_reset(initial_dp);
dp_targetid =
initial_dp->dp_low_write(initial_dp, ADIV5_DP_TARGETSEL,
(i << ADIV5_DP_TARGETSEL_TINSTANCE_OFFSET) | (i << ADIV5_DP_TARGETSEL_TINSTANCE_OFFSET) |
(initial_dp->target_id & (ADIV5_DP_TARGETSEL_TPARTNO_MASK | ADIV5_DP_TARGETSEL_TDESIGNER_MASK | 1U)); (dp_targetid & (ADIV5_DP_TARGETSEL_TPARTNO_MASK | ADIV5_DP_TARGETSEL_TDESIGNER_MASK | 1U)));
initial_dp->dp_low_write(initial_dp, ADIV5_DP_TARGETSEL, dp_targetid);
TRY_CATCH (e, EXCEPTION_ALL) { TRY_CATCH (e, EXCEPTION_ALL) {
dp_debug_port_id = initial_dp->dp_read(initial_dp, ADIV5_DP_DPIDR); initial_dp->dp_read(initial_dp, ADIV5_DP_DPIDR);
} }
if (e.type || initial_dp->fault) { if (e.type || initial_dp->fault)
continue; continue;
} }
} else {
dp_debug_port_id = initial_dp->debug_port_id;
dp_targetid = initial_dp->target_id;
}
ADIv5_DP_t *dp = calloc(1, sizeof(*dp)); ADIv5_DP_t *dp = calloc(1, sizeof(*dp));
if (!dp) { /* calloc failed: heap exhaustion */ if (!dp) { /* calloc failed: heap exhaustion */
DEBUG_WARN("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);
continue; continue;
} }
memcpy(dp, initial_dp, sizeof(ADIv5_DP_t)); memcpy(dp, initial_dp, sizeof(ADIv5_DP_t));
dp->version = (dp_debug_port_id & ADIV5_DP_DPIDR_VERSION_MASK) >> ADIV5_DP_DPIDR_VERSION_OFFSET; dp->instance = i;
dp->debug_port_id = dp_debug_port_id;
dp->target_id = dp_targetid;
adiv5_dp_init(dp); adiv5_dp_init(dp);
} }
return target_list ? 1U : 0U; return target_list ? 1U : 0U;
@ -192,9 +199,8 @@ uint32_t firmware_swdp_read(ADIv5_DP_t *dp, uint16_t addr)
if (addr & ADIV5_APnDP) { if (addr & ADIV5_APnDP) {
adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0); adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0);
return adiv5_dp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); return adiv5_dp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0);
} else { } else
return firmware_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0); return firmware_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0);
}
} }
uint32_t firmware_swdp_error(ADIv5_DP_t *dp) uint32_t firmware_swdp_error(ADIv5_DP_t *dp)
@ -204,7 +210,7 @@ uint32_t firmware_swdp_error(ADIv5_DP_t *dp)
* With DP Change, another target needs selection. * With DP Change, another target needs selection.
* => Reselect with right target! */ * => Reselect with right target! */
dp_line_reset(dp); dp_line_reset(dp);
dp->dp_low_write(dp, ADIV5_DP_TARGETSEL, dp->target_id); dp->dp_low_write(dp, ADIV5_DP_TARGETSEL, dp->targetsel);
dp->dp_read(dp, ADIV5_DP_DPIDR); dp->dp_read(dp, ADIV5_DP_DPIDR);
/* Exception here is unexpected, so do not catch */ /* Exception here is unexpected, so do not catch */
} }

View File

@ -278,24 +278,20 @@ bool cortexm_probe(ADIv5_AP_t *ap)
target *t; target *t;
t = target_new(); t = target_new();
if (!t) { if (!t)
return false; return false;
}
adiv5_ap_ref(ap); adiv5_ap_ref(ap);
if (ap->dp->version >= 2 && ap->dp->target_id != 0) { if (ap->dp->version >= 2 && ap->dp->target_designer_code != 0) {
/* Use TARGETID register to identify target */ /* Use TARGETID register to identify target */
const uint16_t tdesigner = t->designer_code = ap->dp->target_designer_code;
(ap->dp->target_id & ADIV5_DP_TARGETID_TDESIGNER_MASK) >> ADIV5_DP_TARGETID_TDESIGNER_OFFSET; t->part_id = ap->dp->target_partno;
/* convert it to our internal representation, See JEP-106 code list */
t->designer_code =
(tdesigner & ADIV5_DP_DESIGNER_JEP106_CONT_MASK) << 1U | (tdesigner & ADIV5_DP_DESIGNER_JEP106_CODE_MASK);
t->part_id = (ap->dp->target_id & ADIV5_DP_TARGETID_TPARTNO_MASK) >> ADIV5_DP_TARGETID_TPARTNO_OFFSET;
} else { } else {
/* Use AP DESIGNER and AP PARTNO to identify target */ /* Use AP DESIGNER and AP PARTNO to identify target */
t->designer_code = ap->designer_code; t->designer_code = ap->designer_code;
t->part_id = ap->partno; t->part_id = ap->partno;
} }
struct cortexm_priv *priv = calloc(1, sizeof(*priv)); struct cortexm_priv *priv = calloc(1, sizeof(*priv));
if (!priv) { /* calloc failed: heap exhaustion */ if (!priv) { /* calloc failed: heap exhaustion */
DEBUG_WARN("calloc: failed in %s\n", __func__); DEBUG_WARN("calloc: failed in %s\n", __func__);

View File

@ -511,12 +511,13 @@ bool stm32l4_probe(target *t)
{ {
ADIv5_AP_t *ap = cortexm_ap(t); ADIv5_AP_t *ap = cortexm_ap(t);
uint32_t device_id; uint32_t device_id;
if (ap->dp->version >= 2 && ap->dp->target_id > 1) { /* STM32L552 has invalid TARGETID 1 */ if (ap->dp->version >= 2 && ap->dp->target_partno > 1) { /* STM32L552 has invalid TARGETID 1 */
/* FIXME: this does not look correct, nothing in TARGETID register has offset 16 */ /* FIXME: ids likely no longer match and need fixing */
device_id = (ap->dp->target_id >> 16U) & 0xfffU; device_id = ap->dp->target_partno;
} else { } else {
uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS; uint32_t idcode_reg = STM32L4_DBGMCU_IDCODE_PHYS;
if (ap->dp->debug_port_id == 0x0be12477U) /* FIXME: we probaly want to check if this is a C-M33 via cpuid */
if (ap->dp->partno == 0xbe)
idcode_reg = STM32L5_DBGMCU_IDCODE_PHYS; idcode_reg = STM32L5_DBGMCU_IDCODE_PHYS;
device_id = target_mem_read32(t, idcode_reg) & 0xfffU; device_id = target_mem_read32(t, idcode_reg) & 0xfffU;
DEBUG_INFO("Idcode %08" PRIx32 "\n", device_id); DEBUG_INFO("Idcode %08" PRIx32 "\n", device_id);