adiv5: Recover from bad AP access.
E.g. AP1 on a STM32WLE5 points to a ROM table, but access to the ROM table via AP1 hangs forever. - Substantial reduce timeout when wait for a response. Valid access should succeed fast. - Abort AP access to free DP for other accesses - Don't throw exception, only set dp->fault - React on higher level
This commit is contained in:
parent
b887a8d355
commit
0c63903071
|
@ -144,6 +144,7 @@ void remotePacketProcessSWD(uint8_t i, char *packet)
|
|||
if (i==2) {
|
||||
remote_dp.dp_read = firmware_swdp_read;
|
||||
remote_dp.low_access = firmware_swdp_low_access;
|
||||
remote_dp.abort = firmware_swdp_abort;
|
||||
swdptap_init(&remote_dp);
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
} else {
|
||||
|
@ -194,6 +195,7 @@ void remotePacketProcessJTAG(uint8_t i, char *packet)
|
|||
case REMOTE_INIT: /* JS = initialise ============================= */
|
||||
remote_dp.dp_read = fw_adiv5_jtagdp_read;
|
||||
remote_dp.low_access = fw_adiv5_jtagdp_low_access;
|
||||
remote_dp.abort = adiv5_jtagdp_abort;
|
||||
jtagtap_init();
|
||||
_respond(REMOTE_RESP_OK, 0);
|
||||
break;
|
||||
|
|
|
@ -414,16 +414,11 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion,
|
|||
if (addr == 0) /* No rom table on this AP */
|
||||
return;
|
||||
volatile uint32_t cidr;
|
||||
volatile struct exception e;
|
||||
TRY_CATCH (e, EXCEPTION_TIMEOUT) {
|
||||
cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||
}
|
||||
if (e.type) {
|
||||
DEBUG_WARN("CIDR read timeout on AP%d, aborting.\n", num_entry);
|
||||
adiv5_dp_abort(ap->dp, ADIV5_DP_ABORT_DAPABORT);
|
||||
cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET);
|
||||
if (ap->dp->fault) {
|
||||
DEBUG_WARN("CIDR read timeout on AP%d, aborting.\n", ap->apsel);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE)
|
||||
return;
|
||||
#if defined(ENABLE_DEBUG)
|
||||
|
@ -603,6 +598,15 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
|
|||
|
||||
if(!tmpap.idr) /* IDR Invalid */
|
||||
return NULL;
|
||||
tmpap.csw = adiv5_ap_read(&tmpap, ADIV5_AP_CSW) &
|
||||
~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK);
|
||||
|
||||
if (tmpap.csw & ADIV5_AP_CSW_TRINPROG) {
|
||||
DEBUG_WARN("AP %d: Transaction in progress. AP is not be usable!\n",
|
||||
apsel);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* It's valid to so create a heap copy */
|
||||
ap = malloc(sizeof(*ap));
|
||||
if (!ap) { /* malloc failed: heap exhaustion */
|
||||
|
@ -612,14 +616,6 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
|
|||
|
||||
memcpy(ap, &tmpap, sizeof(*ap));
|
||||
|
||||
ap->csw = adiv5_ap_read(ap, ADIV5_AP_CSW) &
|
||||
~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK);
|
||||
|
||||
if (ap->csw & ADIV5_AP_CSW_TRINPROG) {
|
||||
DEBUG_WARN("AP transaction in progress. Target may not be usable.\n");
|
||||
ap->csw &= ~ADIV5_AP_CSW_TRINPROG;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_DEBUG)
|
||||
uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG);
|
||||
DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32
|
||||
|
|
|
@ -310,4 +310,5 @@ uint32_t fw_adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr);
|
|||
uint32_t firmware_swdp_error(ADIv5_DP_t *dp);
|
||||
|
||||
void firmware_swdp_abort(ADIv5_DP_t *dp, uint32_t abort);
|
||||
void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort);
|
||||
#endif
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp);
|
||||
|
||||
static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort);
|
||||
|
||||
void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode)
|
||||
{
|
||||
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
|
||||
|
@ -87,23 +85,25 @@ uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
|||
|
||||
jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, APnDP ? IR_APACC : IR_DPACC);
|
||||
|
||||
platform_timeout_set(&timeout, 2000);
|
||||
platform_timeout_set(&timeout, 20);
|
||||
do {
|
||||
jtag_dev_shift_dr(&jtag_proc, dp->dp_jd_index, (uint8_t*)&response,
|
||||
(uint8_t*)&request, 35);
|
||||
ack = response & 0x07;
|
||||
} while(!platform_timeout_is_expired(&timeout) && (ack == JTAGDP_ACK_WAIT));
|
||||
|
||||
if (ack == JTAGDP_ACK_WAIT)
|
||||
raise_exception(EXCEPTION_TIMEOUT, "JTAG-DP ACK timeout");
|
||||
|
||||
if (ack == JTAGDP_ACK_WAIT) {
|
||||
dp->abort(dp, ADIV5_DP_ABORT_DAPABORT);
|
||||
dp->fault = 1;
|
||||
return 0;
|
||||
}
|
||||
if((ack != JTAGDP_ACK_OK))
|
||||
raise_exception(EXCEPTION_ERROR, "JTAG-DP invalid ACK");
|
||||
|
||||
return (uint32_t)(response >> 3);
|
||||
}
|
||||
|
||||
static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort)
|
||||
void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort)
|
||||
{
|
||||
uint64_t request = (uint64_t)abort << 3;
|
||||
jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, IR_ABORT);
|
||||
|
|
|
@ -93,6 +93,8 @@ int adiv5_swdp_scan(uint32_t targetid)
|
|||
initial_dp->error = firmware_swdp_error;
|
||||
if (!initial_dp->low_access)
|
||||
initial_dp->low_access = firmware_swdp_low_access;
|
||||
if (!initial_dp->abort)
|
||||
initial_dp->abort = firmware_swdp_abort;
|
||||
/* DORMANT-> SWD sequence*/
|
||||
initial_dp->seq_out(0xFFFFFFFF, 32);
|
||||
initial_dp->seq_out(0xFFFFFFFF, 32);
|
||||
|
@ -241,7 +243,7 @@ uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
|||
|
||||
if((addr & ADIV5_APnDP) && dp->fault) return 0;
|
||||
|
||||
platform_timeout_set(&timeout, 2000);
|
||||
platform_timeout_set(&timeout, 20);
|
||||
do {
|
||||
dp->seq_out(request, 8);
|
||||
ack = dp->seq_in(3);
|
||||
|
@ -251,8 +253,11 @@ uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
|
|||
}
|
||||
} while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout));
|
||||
|
||||
if (ack == SWDP_ACK_WAIT)
|
||||
raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout");
|
||||
if (ack == SWDP_ACK_WAIT) {
|
||||
dp->abort(dp, ADIV5_DP_ABORT_DAPABORT);
|
||||
dp->fault = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(ack == SWDP_ACK_FAULT) {
|
||||
dp->fault = 1;
|
||||
|
|
Loading…
Reference in New Issue