application: add TDO finding

This commit is contained in:
King Kévin 2021-03-16 23:28:59 +01:00
parent 3362f3a499
commit 4d64cb35ed
1 changed files with 104 additions and 6 deletions

View File

@ -302,6 +302,7 @@ static void command_swd_scan(void* argument)
}
#define JTAG_SPEED 50 /**< time in us between clock edges (i.e. setting the clock speed) */
#define JTAG_PATTERN 0x0ff06699 /**< pattern to fin TDI pin */
static int8_t jtag_tms_ch = -1; /**< channel used for JTAG TCK output (-1 = not configured) */
static int8_t jtag_tck_ch = -1; /**< channel used for JTAG TMS output (-1 = not configured) */
static int8_t jtag_tdi_ch = -1; /**< channel used for JTAG TMS output (-1 = not configured) */
@ -374,9 +375,18 @@ static void command_jtag_scan(void* argument)
printf("searching JTAG on channels CH%02u-CH%02u\n", channel_start, channel_stop);
printf("searching for TDO using IDCODE scan on TCK/TMS (%u combinations): ", (channel_stop - channel_start + 1) * (channel_stop - channel_start));
//uint32_t tdo[CHANNEL_NUMBERS]; // the output bit stream for all channels
bool idcode[CHANNEL_NUMBERS]; // when an IDCODE has been found
//uint8_t found = 0; // number of JTAG ports found
uint8_t idcodes[CHANNEL_NUMBERS]; // how many IDCODEs have been found on channel
for (uint8_t i = 0; i < LENGTH(idcodes); i++) {
idcodes[i] = 0;
}
bool tck_ok[CHANNEL_NUMBERS]; // if channel is a possible TCK
for (uint8_t i = 0; i < LENGTH(tck_ok); i++) {
tck_ok[i] = false;
}
bool tms_ok[CHANNEL_NUMBERS]; // if channel is a possible TMS
for (uint8_t i = 0; i < LENGTH(tms_ok); i++) {
tms_ok[i] = false;
}
jtag_tdi_ch = -1; // we don't use TDI for now
for (uint8_t tck = channel_start; tck <= channel_stop; tck++) { // use channel as TCK output
for (uint8_t tms = channel_start; tms <= channel_stop; tms++) { // use channel as TMS output
@ -387,14 +397,14 @@ static void command_jtag_scan(void* argument)
gpio_mode_setup(channel_ports[tck], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, channel_pins[tck]); // set channel for TCK as output
jtag_tck_ch = tck; // remember which channel we use for TCK for the transaction
gpio_set(channel_ports[tms], channel_pins[tms]); // start high (to go to reset state)
gpio_mode_setup(channel_ports[tms], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, channel_pins[tms]); // set channel for TMS back to input
gpio_mode_setup(channel_ports[tms], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, channel_pins[tms]); // set channel for TMS as output
jtag_tms_ch = tms; // remember which channel we use for TMS for the transaction
jtag_transaction(0xffffffff, 0, 26); // ensure we are is reset state, even on SWD devices (needs 50 TMS hig);
jtag_transaction(0xffffffff, 0, 26); // continuation
jtag_transaction(0xE73C, 0, 16); // send sequence to switch any SWD device back to JTAG (this constant magic value)
// all other channel should already be inputs
jtag_transaction(0x3f | (0 << 6) | (1 << 7) | (0 << 8) | (0 << 9), 0, 6 + 1 + 1 + 1 + 1); // go back to JTAG TEST-LOGIC_RESET (5 bits should be enough to go from any state to RESET, but we a one just to be sure) -> RUN-TEST/IDLE -> SELECT-DR-SCAN -> CAPTURE-DR -> SHIFT-DR states
// initialize array
bool idcode[CHANNEL_NUMBERS]; // when a new IDCODE has been found
for (uint8_t i = 0; i < LENGTH(idcode); i++) {
idcode[i] = true;
}
@ -414,9 +424,12 @@ static void command_jtag_scan(void* argument)
} else if (0 == (jtag_tdo[tdo] & 0x1)) { // RAO bit is wrong
continue;
} else { // IDCODE received
printf("\npossible IDCODE found: TCK=CH%02u TMS=CH%02u TDI=CH%02u IDCODE=%+08x (", tck, tms, tdo, jtag_tdo[tdo]); // show finding
printf("\nIDCODE found: TCK=CH%02u TMS=CH%02u TDO=CH%02u CHAIN=%u IDCODE=%+08x (", tck, tms, tdo, idcodes[tdo] + 1, jtag_tdo[tdo]); // show finding
print_idcode(jtag_tdo[tdo]);
puts(")");
idcodes[tdo]++; // count the number of IDCODEs found
tck_ok[tck] = true; // remember we found TCK on this channel
tms_ok[tms] = true; // remember we found TMS on this channel
idcode_found = true; // remember we found an IDCODE
idcode_scan = true; // continue scanning for the next code
}
@ -434,6 +447,91 @@ static void command_jtag_scan(void* argument)
}
}
putc('\n'); // all combinations completed
// get max length of scan chain
uint8_t chain = 0;
for (uint8_t tdo = channel_start; tdo <= channel_stop; tdo++) {
if (idcodes[tdo] > chain) {
chain = idcodes[tdo];
}
}
if (0 == chain) {
puts("no IDCODE found\n");
return;
}
printf("searching for TDI using IDCODE feeding on TCK/TMS/TDO: ");
jtag_tdi_ch = -1; // we don't use TDI for now
for (uint8_t tck = channel_start; tck <= channel_stop; tck++) { // test channel as TCK output
if (!tck_ok[tck]) { // this is not one of the possibles TCK
continue;
}
for (uint8_t tms = channel_start; tms <= channel_stop; tms++) { // test channel as TMS output
if (tck == tms) { // don't use the same channel for TCK and TMS
continue;
}
if (!tms_ok[tms]) { // this is not one of the possible TMS
continue;
}
for (uint8_t tdi = channel_start; tdi <= channel_stop; tdi++) { // test channel as TDI
if (tck == tdi) { // don't use the same channel for TCK and TDI
continue;
}
if (tms == tdi) { // don't use the same channel for TMS and TDI
continue;
}
bool tdi_found = false; // if we found a TDI pin in this combination
gpio_set(channel_ports[tck], channel_pins[tck]); // clock is idle high
gpio_mode_setup(channel_ports[tck], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, channel_pins[tck]); // set channel for TCK as output
jtag_tck_ch = tck; // remember which channel we use for TCK for the transaction
gpio_set(channel_ports[tms], channel_pins[tms]); // start high (to go to reset state)
gpio_mode_setup(channel_ports[tms], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, channel_pins[tms]); // set channel for TMS as output
jtag_tms_ch = tms; // remember which channel we use for TMS for the transaction
gpio_set(channel_ports[tdi], channel_pins[tdi]); // start high (idle state)
gpio_mode_setup(channel_ports[tdi], GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, channel_pins[tdi]); // set channel for TMS back to input
jtag_tdi_ch = tdi; // remember which channel we use for TDI for the transaction
// all other channels are already inputs (to check TDO)
// switching from SWD to JTAG has already been done
jtag_transaction(0x3f | (0 << 6) | (1 << 7) | (0 << 8) | (0 << 9), 0, 6 + 1 + 1 + 1 + 1); // go to IDCODE state: back to JTAG TEST-LOGIC_RESET (5 bits should be enough to go from any state to RESET, but we a one just to be sure) -> RUN-TEST/IDLE -> SELECT-DR-SCAN -> CAPTURE-DR -> SHIFT-DR
for (uint8_t sequence = 0; sequence <= chain; sequence++) { // go through longest chain
jtag_transaction(0, JTAG_PATTERN, 32); // send pattern into chain
for (uint8_t tdo = channel_start; tdo <= channel_stop; tdo++) { // test channel as TDO
if (tck == tdo) { // don't use the same channel for TCK and TDO
continue;
}
if (tms == tdo) { // don't use the same channel for TMS and TDO
continue;
}
if (0 == idcodes[tdo]) { // we did not seen any IDCODE on this pin
continue;
}
if (sequence < idcodes[tdo]) { // we did not got through the chain yet, thus we don't expect the pattern
continue;
}
if (0 == jtag_tdo[tdo] || 0xffffffff == jtag_tdo[tdo]) { // we received nothing
continue;
}
if (JTAG_PATTERN == jtag_tdo[tdo]) { // we found out pattern
printf("\nJTAG found: TCK=CH%02u TMS=CH%02u TDO=CH%02u TDI=CH%02u CHAIN=%u", tck, tms, tdo, tdi, sequence);
tdi_found = true; // remember we found one and printed
}
}
}
if (tdi_found) {
putc('\n'); // continue dot pattern on new line
} else {
putc('.');
}
gpio_mode_setup(channel_ports[tck], GPIO_MODE_INPUT, GPIO_PUPD_NONE, channel_pins[tck]); // set channel for TCK back to input
jtag_tck_ch = -1; // clear channel configuration
gpio_mode_setup(channel_ports[tms], GPIO_MODE_INPUT, GPIO_PUPD_NONE, channel_pins[tms]); // set channel for TMS back to input
jtag_tms_ch = -1; // clear channel configuration
gpio_mode_setup(channel_ports[tdi], GPIO_MODE_INPUT, GPIO_PUPD_NONE, channel_pins[tdi]); // set channel for TDI back to input
jtag_tdi_ch = -1; // clear channel configuration
} // end test channel as TDI
} // end test channel as TMS
} // end test channel as TCK
putc('\n'); // all combinations completed
}
static void command_voltages(void* argument)