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:
parent
c04b98435a
commit
ce6477886f
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,10 +199,9 @@ 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 */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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__);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue