jtag_scan: Rework chain detection
Fixme: stlinkv2/hosted probably does only handle STM devices. Check if jtag_devs.c really needed.
This commit is contained in:
parent
e1a1865de9
commit
2d4a503135
|
@ -31,7 +31,6 @@ SRC = \
|
||||||
gdb_hostio.c \
|
gdb_hostio.c \
|
||||||
gdb_packet.c \
|
gdb_packet.c \
|
||||||
hex_utils.c \
|
hex_utils.c \
|
||||||
jtag_devs.c \
|
|
||||||
jtag_scan.c \
|
jtag_scan.c \
|
||||||
lmi.c \
|
lmi.c \
|
||||||
lpc_common.c \
|
lpc_common.c \
|
||||||
|
|
|
@ -59,7 +59,7 @@ ifneq ($(HOSTED_BMP_ONLY), 1)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VPATH += platforms/pc
|
VPATH += platforms/pc
|
||||||
SRC += timing.c cl_utils.c utils.c
|
SRC += timing.c cl_utils.c utils.c jtag_devs.c
|
||||||
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
|
SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c
|
||||||
ifneq ($(HOSTED_BMP_ONLY), 1)
|
ifneq ($(HOSTED_BMP_ONLY), 1)
|
||||||
SRC += bmp_libusb.c stlinkv2.c
|
SRC += bmp_libusb.c stlinkv2.c
|
||||||
|
|
|
@ -88,19 +88,23 @@
|
||||||
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8)
|
||||||
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
|
#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC)
|
||||||
|
|
||||||
/* Known designers seen in SYSROM-PIDR. Ignore Bit 0 from
|
/* Known designers seen in SYSROM-PIDR and JTAG IDCode.
|
||||||
* the designer bits to get JEDEC Ids with bit 7 ignored.*/
|
* Ignore Bit 0 from the designer bits to get JEDEC Ids.
|
||||||
|
* Should get it's one file as not only related to Adiv5!
|
||||||
|
*/
|
||||||
#define AP_DESIGNER_FREESCALE 0x00e
|
#define AP_DESIGNER_FREESCALE 0x00e
|
||||||
#define AP_DESIGNER_TEXAS 0x017
|
#define AP_DESIGNER_TEXAS 0x017
|
||||||
#define AP_DESIGNER_ATMEL 0x01f
|
#define AP_DESIGNER_ATMEL 0x01f
|
||||||
#define AP_DESIGNER_STM 0x020
|
#define AP_DESIGNER_STM 0x020
|
||||||
#define AP_DESIGNER_CYPRESS 0x034
|
#define AP_DESIGNER_CYPRESS 0x034
|
||||||
#define AP_DESIGNER_INFINEON 0x041
|
#define AP_DESIGNER_INFINEON 0x041
|
||||||
|
#define DESIGNER_XILINX 0x049
|
||||||
#define AP_DESIGNER_NORDIC 0x244
|
#define AP_DESIGNER_NORDIC 0x244
|
||||||
#define AP_DESIGNER_ARM 0x43b
|
#define AP_DESIGNER_ARM 0x43b
|
||||||
/*LPC845 with designer 501. Strange!? */
|
/*LPC845 with designer 501. Strange!? */
|
||||||
#define AP_DESIGNER_SPECULAR 0x501
|
#define AP_DESIGNER_SPECULAR 0x501
|
||||||
#define AP_DESIGNER_CS 0x555
|
#define AP_DESIGNER_CS 0x555
|
||||||
|
#define DESIGNER_XAMBALA 0x61e
|
||||||
#define AP_DESIGNER_ENERGY_MICRO 0x673
|
#define AP_DESIGNER_ENERGY_MICRO 0x673
|
||||||
#define AP_DESIGNER_GIGADEVICE 0x751
|
#define AP_DESIGNER_GIGADEVICE 0x751
|
||||||
#define AP_DESIGNER_RASPBERRY 0x927
|
#define AP_DESIGNER_RASPBERRY 0x927
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
* Copyright (C) 2011 Black Sphere Technologies Ltd.
|
||||||
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
|
||||||
|
* Copyright (C) 2021 Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de)
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,16 +26,14 @@
|
||||||
|
|
||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "jtagtap.h"
|
#include "jtagtap.h"
|
||||||
#include "jtag_scan.h"
|
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "adiv5.h"
|
#include "adiv5.h"
|
||||||
#include "jtag_devs.h"
|
|
||||||
|
|
||||||
struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1];
|
struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1];
|
||||||
int jtag_dev_count;
|
int jtag_dev_count;
|
||||||
|
|
||||||
/* bucket of ones for don't care TDI */
|
/* bucket of ones for don't care TDI */
|
||||||
static const uint8_t ones[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
|
static const uint8_t ones[] = {0xff, 0xFF, 0xFF, 0xFF};
|
||||||
|
|
||||||
#if PC_HOSTED == 0
|
#if PC_HOSTED == 0
|
||||||
void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev)
|
void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev)
|
||||||
|
@ -47,36 +46,32 @@ void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Scan JTAG chain for devices, store IR length and IDCODE (if present).
|
/* Scan JTAG chain for devices, store IR length and IDCODE (if present).
|
||||||
* Reset TAP state machine.
|
|
||||||
* Select Shift-IR state.
|
|
||||||
* Each device is assumed to shift out IR at 0x01. (this may not always be true)
|
|
||||||
* Shift in ones until we read two consecutive ones, then we have shifted out the
|
|
||||||
* IRs of all devices.
|
|
||||||
*
|
*
|
||||||
* After this process all the IRs are loaded with the BYPASS command.
|
* https://www.fpga4fun.com/JTAG3.html
|
||||||
* Select Shift-DR state.
|
* Count the number of devices in the JTAG chain
|
||||||
* Shift in ones and count zeros shifted out. Should be one for each device.
|
*
|
||||||
* Check this against device count obtained by IR scan above.
|
* shift enough ones in IR
|
||||||
|
* shift enough zeros in DR
|
||||||
|
* Now shift out ones and stop if first '1' is seen. This gets the number
|
||||||
|
* of devices
|
||||||
|
*
|
||||||
|
* Assume max 32 devices with max IR len 16 = 512 bits = 16 loops * 32 bit
|
||||||
*
|
*
|
||||||
* Reset the TAP state machine again. This should load all IRs with IDCODE.
|
* Reset the TAP state machine again. This should load all IRs with IDCODE.
|
||||||
* For each device, shift out one bit. If this is zero IDCODE isn't present,
|
* Read 32 bit IDCODE for all devices.
|
||||||
* continue to next device. If this is one shift out the remaining 31 bits
|
*/
|
||||||
* of the IDCODE register.
|
|
||||||
*/
|
|
||||||
int jtag_scan(const uint8_t *irlens)
|
int jtag_scan(const uint8_t *irlens)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
uint32_t j;
|
void (*jd_handlers[JTAG_MAX_DEVS])(uint8_t jd_index, uint32_t j_idcode);
|
||||||
|
|
||||||
target_list_free();
|
target_list_free();
|
||||||
|
|
||||||
jtag_dev_count = 0;
|
memset(jd_handlers, 0, sizeof(jd_handlers));
|
||||||
memset(&jtag_devs, 0, sizeof(jtag_devs));
|
|
||||||
|
|
||||||
/* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is
|
/* Run throught the SWD to JTAG sequence for the case where an
|
||||||
* in SW-DP mode.
|
* attached SWJ-DP is in SW-DP mode.
|
||||||
*/
|
*/
|
||||||
DEBUG_INFO("Resetting TAP\n");
|
|
||||||
#if PC_HOSTED == 1
|
#if PC_HOSTED == 1
|
||||||
if (platform_jtagtap_init()) {
|
if (platform_jtagtap_init()) {
|
||||||
DEBUG_WARN("JTAG not available\n");
|
DEBUG_WARN("JTAG not available\n");
|
||||||
|
@ -86,139 +81,146 @@ int jtag_scan(const uint8_t *irlens)
|
||||||
jtagtap_init();
|
jtagtap_init();
|
||||||
#endif
|
#endif
|
||||||
jtag_proc.jtagtap_reset();
|
jtag_proc.jtagtap_reset();
|
||||||
|
#define LOOPS 16
|
||||||
if (irlens) {
|
jtagtap_shift_ir();
|
||||||
DEBUG_WARN("Given list of IR lengths, skipping probe\n");
|
i = LOOPS;
|
||||||
DEBUG_INFO("Change state to Shift-IR\n");
|
uint8_t ir_chain[64], *din = ir_chain;
|
||||||
jtagtap_shift_ir();
|
while (i--) {
|
||||||
j = 0;
|
jtag_proc.jtagtap_tdi_tdo_seq(din, (i == 0) ? 1 : 0, ones,
|
||||||
while((jtag_dev_count <= JTAG_MAX_DEVS) &&
|
sizeof(ones) * 8);
|
||||||
(jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) {
|
din += sizeof(ones);
|
||||||
uint32_t irout;
|
|
||||||
if(*irlens == 0)
|
|
||||||
break;
|
|
||||||
jtag_proc.jtagtap_tdi_tdo_seq((uint8_t*)&irout, 0, ones, *irlens);
|
|
||||||
if (!(irout & 1)) {
|
|
||||||
DEBUG_WARN("check failed: IR[0] != 1\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
jtag_devs[jtag_dev_count].ir_len = *irlens;
|
|
||||||
jtag_devs[jtag_dev_count].ir_prescan = j;
|
|
||||||
jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count;
|
|
||||||
j += *irlens;
|
|
||||||
irlens++;
|
|
||||||
jtag_dev_count++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
DEBUG_INFO("Change state to Shift-IR\n");
|
|
||||||
jtagtap_shift_ir();
|
|
||||||
|
|
||||||
DEBUG_INFO("Scanning out IRs\n");
|
|
||||||
if(!jtag_proc.jtagtap_next(0, 1)) {
|
|
||||||
DEBUG_WARN("jtag_scan: Sanity check failed: IR[0] shifted out "
|
|
||||||
"as 0\n");
|
|
||||||
jtag_dev_count = -1;
|
|
||||||
return -1; /* must be 1 */
|
|
||||||
}
|
|
||||||
jtag_devs[0].ir_len = 1; j = 1;
|
|
||||||
while((jtag_dev_count <= JTAG_MAX_DEVS) &&
|
|
||||||
(jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) {
|
|
||||||
if(jtag_proc.jtagtap_next(0, 1)) {
|
|
||||||
if(jtag_devs[jtag_dev_count].ir_len == 1) break;
|
|
||||||
jtag_devs[++jtag_dev_count].ir_len = 1;
|
|
||||||
jtag_devs[jtag_dev_count].ir_prescan = j;
|
|
||||||
jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count;
|
|
||||||
} else jtag_devs[jtag_dev_count].ir_len++;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
if(jtag_dev_count > JTAG_MAX_DEVS) {
|
|
||||||
DEBUG_WARN("jtag_scan: Maximum device count exceeded\n");
|
|
||||||
jtag_dev_count = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(jtag_devs[jtag_dev_count].ir_len > JTAG_MAX_IR_LEN) {
|
|
||||||
DEBUG_WARN("jtag_scan: Maximum IR length exceeded\n");
|
|
||||||
jtag_dev_count = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!(ir_chain[0] & 1)) {
|
||||||
DEBUG_INFO("Return to Run-Test/Idle\n");
|
DEBUG_WARN("Unexpected IR chain!\n");
|
||||||
jtag_proc.jtagtap_next(1, 1);
|
|
||||||
jtagtap_return_idle();
|
|
||||||
|
|
||||||
/* All devices should be in BYPASS now */
|
|
||||||
|
|
||||||
/* Count device on chain */
|
|
||||||
DEBUG_INFO("Change state to Shift-DR\n");
|
|
||||||
jtagtap_shift_dr();
|
|
||||||
for(i = 0; (jtag_proc.jtagtap_next(0, 1) == 0) && (i <= jtag_dev_count); i++)
|
|
||||||
jtag_devs[i].dr_postscan = jtag_dev_count - i - 1;
|
|
||||||
|
|
||||||
if(i != jtag_dev_count) {
|
|
||||||
DEBUG_WARN("jtag_scan: Sanity check failed: "
|
|
||||||
"BYPASS dev count doesn't match IR scan\n");
|
|
||||||
jtag_dev_count = -1;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_INFO("Return to Run-Test/Idle\n");
|
|
||||||
jtag_proc.jtagtap_next(1, 1);
|
|
||||||
jtagtap_return_idle();
|
|
||||||
if(!jtag_dev_count) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
jtagtap_return_idle();
|
||||||
/* Fill in the ir_postscan fields */
|
jtagtap_shift_dr();
|
||||||
for(i = jtag_dev_count - 1; i; i--)
|
i = LOOPS;
|
||||||
jtag_devs[i-1].ir_postscan = jtag_devs[i].ir_postscan +
|
uint8_t zeros[] = {0, 0, 0, 0};
|
||||||
jtag_devs[i].ir_len;
|
while(i--) {
|
||||||
|
jtag_proc.jtagtap_tdi_seq(0, zeros, sizeof(zeros) * 8);
|
||||||
/* Reset jtagtap: should take all devs to IDCODE */
|
}
|
||||||
|
int num_devices = 0;
|
||||||
|
while (!jtag_proc.jtagtap_next(0,1) && (i++ < 6))
|
||||||
|
num_devices++;
|
||||||
jtag_proc.jtagtap_reset();
|
jtag_proc.jtagtap_reset();
|
||||||
jtagtap_shift_dr();
|
jtagtap_shift_dr();
|
||||||
for(i = 0; i < jtag_dev_count; i++) {
|
jtag_dev_count = num_devices;
|
||||||
if(!jtag_proc.jtagtap_next(0, 1)) continue;
|
if (!num_devices)
|
||||||
jtag_devs[i].jd_idcode = 1;
|
return 0;
|
||||||
for(j = 2; j; j <<= 1)
|
DEBUG_TARGET("Found %d devices\n", num_devices);
|
||||||
if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].jd_idcode |= j;
|
int irbit = 1;
|
||||||
|
int j = 0;
|
||||||
|
for (i = 0; i < num_devices; i++) {
|
||||||
|
uint8_t id[4];
|
||||||
|
jtag_proc.jtagtap_tdi_tdo_seq(id, 0, ones, 32);
|
||||||
|
if (!(id[0] & 1)) {
|
||||||
|
DEBUG_WARN("Invalid IDCode!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
uint32_t idcode = id[3] << 24 | id[2] << 16 | id[1] << 8 | id[0];
|
||||||
|
unsigned int designer = ((id[1] & 0xf) << 8) | (id[0] >> 1);
|
||||||
|
unsigned int product = id[2] | ((id[3] & 0xf) << 8);
|
||||||
|
unsigned int expected_irlen = 0;
|
||||||
|
switch (designer) {
|
||||||
|
case AP_DESIGNER_ARM:
|
||||||
|
switch (product) {
|
||||||
|
case 0xba0:
|
||||||
|
jtag_devs[i].jd_descr = "ADIv5 JTAG-DP port";
|
||||||
|
jd_handlers[i] = adiv5_jtag_dp_handler;
|
||||||
|
expected_irlen = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
jtag_devs[i].jd_descr = "ARM";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_STM:
|
||||||
|
expected_irlen = 5;
|
||||||
|
jtag_devs[i].jd_descr = "STM32 BSD";
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_ATMEL:
|
||||||
|
if ((product >= 0x940) & (product < 0x990)) {
|
||||||
|
jtag_devs[i].jd_descr = "ATMEL AVR8";
|
||||||
|
expected_irlen = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jtag_devs[i].jd_descr = "ATMEL";
|
||||||
|
break;
|
||||||
|
case DESIGNER_XILINX:
|
||||||
|
if (!irlens) {
|
||||||
|
/* Guessed irlen for XILINX devices is wrong.
|
||||||
|
* IR data contains status bits!
|
||||||
|
*/
|
||||||
|
DEBUG_WARN("Please provide irlens as chain contains XILINX devices!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
jtag_devs[i].jd_descr = "XILINX";
|
||||||
|
break;
|
||||||
|
case DESIGNER_XAMBALA:
|
||||||
|
expected_irlen = 5;
|
||||||
|
jtag_devs[i].jd_descr = "RVDBG013";
|
||||||
|
break;
|
||||||
|
case AP_DESIGNER_GIGADEVICE:
|
||||||
|
expected_irlen = 5;
|
||||||
|
jtag_devs[i].jd_descr = "GIGADEVICE BSD";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!jtag_devs[i].jd_descr) {
|
||||||
|
DEBUG_WARN("Unhandled designer %x\n", designer);
|
||||||
|
jtag_devs[i].jd_descr = "Unknow";
|
||||||
|
}
|
||||||
|
bool bit;
|
||||||
|
int guessed_irlen = 0;
|
||||||
|
int advance = irbit;
|
||||||
|
do {
|
||||||
|
/* Guess IR length from the IR scan after JTAG Reset
|
||||||
|
* First bit should be '1', following bits are '0', if not used
|
||||||
|
* for instruction capture, as for Xilinx parts.
|
||||||
|
*/
|
||||||
|
bit = (ir_chain[advance / 8] & (1 << (advance & 7)));
|
||||||
|
guessed_irlen++;
|
||||||
|
advance++;
|
||||||
|
} while (!bit && (advance < (JTAG_MAX_DEVS * 16)));
|
||||||
|
if (irlens) { /* Allow to overwrite from the command line!*/
|
||||||
|
if (*irlens != guessed_irlen) {
|
||||||
|
DEBUG_TARGET("Provides irlen %d vs guessed %d for device %d\n",
|
||||||
|
*irlens, guessed_irlen, i + 1);
|
||||||
|
}
|
||||||
|
expected_irlen = *irlens++;
|
||||||
|
}
|
||||||
|
if (!expected_irlen) {
|
||||||
|
expected_irlen = guessed_irlen++;
|
||||||
|
}
|
||||||
|
jtag_devs[i].ir_len = expected_irlen;
|
||||||
|
jtag_devs[i].ir_prescan = j;
|
||||||
|
jtag_devs[i].jd_dev = i;
|
||||||
|
jtag_devs[i].jd_idcode = idcode;
|
||||||
|
jtag_devs[i].dr_postscan = jtag_dev_count - i - 1;
|
||||||
|
jtag_devs[i].current_ir = -1;
|
||||||
|
j += expected_irlen;
|
||||||
|
irbit += expected_irlen;
|
||||||
|
DEBUG_INFO("%2d: IDCODE: 0x%08" PRIx32 ", IR len %d %s%s\n", i + 1,
|
||||||
|
idcode,jtag_devs[i].ir_len, jtag_devs[i].jd_descr,
|
||||||
|
(jd_handlers[i]) ? "" : " (Unhandled) ");
|
||||||
|
}
|
||||||
|
jtag_proc.jtagtap_reset();
|
||||||
|
/* Fill in the ir_postscan fields */
|
||||||
|
for(i = jtag_dev_count - 1; i; i--) {
|
||||||
|
jtag_devs[i-1].ir_postscan = jtag_devs[i].ir_postscan +
|
||||||
|
jtag_devs[i].ir_len;
|
||||||
}
|
}
|
||||||
DEBUG_INFO("Return to Run-Test/Idle\n");
|
|
||||||
jtag_proc.jtagtap_next(1, 1);
|
|
||||||
jtagtap_return_idle();
|
|
||||||
#if PC_HOSTED == 1
|
#if PC_HOSTED == 1
|
||||||
/*Transfer needed device information to firmware jtag_devs*/
|
/*Transfer needed device information to firmware jtag_devs*/
|
||||||
for(i = 0; i < jtag_dev_count; i++)
|
|
||||||
platform_add_jtag_dev(i, &jtag_devs[i]);
|
|
||||||
for(i = 0; i < jtag_dev_count; i++) {
|
for(i = 0; i < jtag_dev_count; i++) {
|
||||||
DEBUG_INFO("Idcode 0x%08" PRIx32, jtag_devs[i].jd_idcode);
|
platform_add_jtag_dev(i, &jtag_devs[i]);
|
||||||
for(j = 0; dev_descr[j].idcode; j++) {
|
|
||||||
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
|
|
||||||
dev_descr[j].idcode) {
|
|
||||||
DEBUG_INFO(": %s",
|
|
||||||
(dev_descr[j].descr) ? dev_descr[j].descr : "unknown");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DEBUG_INFO("\n");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Check for known devices and handle accordingly */
|
/* Check for known devices and handle accordingly */
|
||||||
for(i = 0; i < jtag_dev_count; i++)
|
for(i = 0; i < jtag_dev_count; i++)
|
||||||
for(j = 0; dev_descr[j].idcode; j++)
|
/* Call handler to initialise/probe device further */
|
||||||
if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) ==
|
if (jd_handlers[i])
|
||||||
dev_descr[j].idcode) {
|
jd_handlers[i](i, jtag_devs[i].jd_idcode);
|
||||||
jtag_devs[i].current_ir = -1;
|
|
||||||
/* Save description in table */
|
|
||||||
jtag_devs[i].jd_descr = dev_descr[j].descr;
|
|
||||||
/* Call handler to initialise/probe device further */
|
|
||||||
if(dev_descr[j].handler)
|
|
||||||
dev_descr[j].handler(i, jtag_devs[i].jd_idcode);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return jtag_dev_count;
|
return jtag_dev_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue