application: improve SWD scan

This commit is contained in:
King Kévin 2021-03-22 11:56:48 +01:00
parent 7ef3e2494b
commit 6910f024f0
1 changed files with 49 additions and 29 deletions

View File

@ -263,39 +263,59 @@ static void command_swd_scan(void* argument)
putc('!');
continue;
}
// try enabling SWD
uint32_t data; // data to read/write over SWD
enum swd_ack_e ack; // SWD acknowledge response
// switch from JTAG to SWD (see ARM IHI 0074A B5.2.2)
swd_line_reset(); // put target in reset state
swd_jtag_to_swd(); // put target SWJ in SWD mode
swd_line_reset(); // put target in reset state
swd_idle_cycles(2); // idle before packet request
swd_packet_request(false, SWD_A_DP_DPIDR, true); // request DPIDR
swd_turnaround(1); // switch from writing to reading
ack = swd_acknowledge_response(); // get ack
if (SWD_ACK_OK != ack) { // no SWD on this combination
putc('.');
continue;
}
printf("\nSWD found: SWCLK=CH%02u SWDIO=CH%02u, ", swclk, swdio);
printf("SWD target DPIDR: ");
if (!swd_read(&data)) {
printf("parity error\n");
return;
}
swd_turnaround(1); // switch from reading to writing
printf("0x%08x ", data);
if (data & 0x1) {
puts("(");
print_idcode(data); // decode DPIDR
puts(")\n");
} else {
printf("(invalid: RAO != 1)\n");
// read DPIDR (see ARM IHI 0074A)
// connection, e.g. reading the DPIDR, is the only allowed action after line reset
uint8_t retry = 2; // number of times to retry reading DPIDR
while (retry) {
swd_line_reset(); // put target in reset state
swd_idle_cycles(2); // idle before packet request
swd_packet_request(false, SWD_A_DP_DPIDR, true); // request DPIDR
swd_turnaround(1); // switch from writing to reading
const enum swd_ack_e ack = swd_acknowledge_response(); // get ack
uint32_t data; // data to read/write over SWD
const bool parity = swd_read(&data); // read data no matter what
swd_turnaround(1); // switch from reading to writing
switch (ack) {
case SWD_ACK_OK: // expected answer
if (parity) { // parity is ok
printf("\nSWD found: SWCLK=CH%02u SWDIO=CH%02u, DPIDR=0x%08x", swclk, swdio, data);
found++; // remember we found an SWD combination
if (data & 0x1) {
puts(" (");
print_idcode(data); // decode DPIDR
puts(")");
} else {
puts(" (invalid LSb)");
}
} else {
printf("(invalid: RAO != 1)");
}
break;
case SWD_ACK_NOREPLY: // the is no SWD here
puts("no reply");
retry = 0; // no need to retry
break;
case SWD_ACK_WAIT: // not allowed for DPIDR
case SWD_ACK_FAULT: // not allowed for DPIDR
default: // invalid ACK
if (!swd_read(&data)) { // read the data
puts("parity error ");
}
printf("garbage data %+08x ", data);
swd_turnaround(1); // switch from reading to writing
break;
}
if (retry) {
retry--; // decrement retry count
}
}
puts("\n");
swd_release_pins(); // release pins
found++; // remember we found an SWD combination
}
}
} // end SWDIO
} // end SWCLK
gpio_set(GPIO_PORT(TARGET_EN), GPIO_PIN(TARGET_EN)); // disable level shifters
printf("\n%u SWD interface(s) found\n", found);