ipdbg/pld: ipdbg can get tap and hub/ir from pld driver.
To start a ipdbg server one needs to know the tap and the instruction code to reach the IPDBG-Hub. This instruction is vendor/family specific. Knowledge which can be provided by the pld driver. Change-Id: I13eeb9fee895d65cd48544da4704fcc9b528b869 Signed-off-by: Daniel Anselmi <danselmi@gmx.ch> Reviewed-on: https://review.openocd.org/c/openocd/+/7369 Tested-by: jenkins Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
parent
373d7eaa70
commit
a27907aed1
|
@ -8674,9 +8674,10 @@ The load command for the FPGA @var{pld_name} will use a length for the preload o
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
@deffn {FPGA Driver} {efinix}
|
@deffn {FPGA Driver} {efinix} [@option{-family} <name>]
|
||||||
Both families (Trion and Titanium) sold by Efinix are supported as both use the same protocol for In-System Configuration.
|
Both families (Trion and Titanium) sold by Efinix are supported as both use the same protocol for In-System Configuration.
|
||||||
This driver can be used to load the bitstream into the FPGA.
|
This driver can be used to load the bitstream into the FPGA.
|
||||||
|
For the option @option{-family} @var{name} is one of @var{trion|titanium}.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
|
|
||||||
|
@ -11834,7 +11835,7 @@ In a session using JTAG for its transport protocol, OpenOCD supports the functio
|
||||||
of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the
|
of a JTAG-Host. The JTAG-Host is needed to connect the circuit over JTAG to the
|
||||||
control-software. For more details see @url{http://ipdbg.org}.
|
control-software. For more details see @url{http://ipdbg.org}.
|
||||||
|
|
||||||
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-port @var{number}}] [@option{-tool @var{number}}] [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}]
|
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-tap @var{tapname}} @option{-hub @var{ir_value} [@var{dr_length}]} [@option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]}] [@option{-port @var{number}}] [@option{-tool @var{number}}]
|
||||||
Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order.
|
Starts or stops a IPDBG JTAG-Host server. Arguments can be specified in any order.
|
||||||
|
|
||||||
Command options:
|
Command options:
|
||||||
|
@ -11843,15 +11844,28 @@ Command options:
|
||||||
@item @option{-tap @var{tapname}} targeting the TAP @var{tapname}.
|
@item @option{-tap @var{tapname}} targeting the TAP @var{tapname}.
|
||||||
@item @option{-hub @var{ir_value}} states that the JTAG hub is
|
@item @option{-hub @var{ir_value}} states that the JTAG hub is
|
||||||
reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}.
|
reachable with dr-scans while the JTAG instruction register has the value @var{ir_value}.
|
||||||
@item @option{-port @var{number}} tcp port number where the JTAG-Host is listening.
|
@item @option{-port @var{number}} tcp port number where the JTAG-Host will listen. The default is 4242 which is used when the option is not given.
|
||||||
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub.
|
@item @option{-tool @var{number}} number of the tool/feature. These corresponds to the ports "data_(up/down)_(0..6)" at the JtagHub. The default is 1 which is used when the option is not given.
|
||||||
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is only reachable if there is a
|
@item @option{-vir [@var{vir_value} [@var{length} [@var{instr_code}]]]} On some devices, the user data-register is reachable if there is a
|
||||||
specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
|
specific value in a second dr. This second dr is called vir (virtual ir). With this parameter given, the IPDBG satisfies this condition prior an
|
||||||
access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second
|
access to the IPDBG-Hub. The value shifted into the vir is given by the first parameter @var{vir_value} (default: 0x11). The second
|
||||||
parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to
|
parameter @var{length} is the length of the vir data register (default: 5). With the @var{instr_code} (default: 0x00e) parameter the ir value to
|
||||||
shift data through vir can be configured.
|
shift data through vir can be configured.
|
||||||
@end itemize
|
@end itemize
|
||||||
@end deffn
|
@end deffn
|
||||||
|
or
|
||||||
|
@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{name} [@var{user}]} [@option{-port @var{number}}] [@option{-tool @var{number}}]
|
||||||
|
Also starts or stops a IPDBG JTAG-Host server. The pld drivers are able to provide the tap and hub/IR for the IPDBG JTAG-Host server.
|
||||||
|
With the @option{-pld @var{name} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required.
|
||||||
|
The defined driver for the pld @var{name} gets selected. (The pld devices names can be shown by the command @command{pld devices}).
|
||||||
|
|
||||||
|
The @verb{|USERx|} instructions are vendor specific and don't change between families of the same vendor.
|
||||||
|
So if there's a pld driver for your vendor it should work with your FPGA even when the driver is not compatible with your device for the remaining features. If your device/vendor is not supported you have to use the previous command.
|
||||||
|
|
||||||
|
With [@var{user}] one can select a different @verb{|USERx|}-Instruction. If the IPDBG JTAG-Hub is used without modification the default value of 1 which selects the first @verb{|USERx|} instruction is adequate.
|
||||||
|
|
||||||
|
The remaining options are described in the previous command.
|
||||||
|
@end deffn
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@example
|
@example
|
||||||
|
@ -11866,6 +11880,13 @@ ipdbg -start -tap 10m50.tap -hub 0x00C -vir -port 60000 -tool 1
|
||||||
Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1).
|
Starts a server listening on tcp-port 60000 which connects to tool 1 (data_up_1/data_down_1).
|
||||||
The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5).
|
The connection is through the TAP of a Intel MAX10 virtual jtag component (sld_instance_index is 0; sld_ir_width is smaller than 5).
|
||||||
|
|
||||||
|
@example
|
||||||
|
ipdbg -start -pld xc7.pld -port 5555 -tool 0
|
||||||
|
@end example
|
||||||
|
Starts a server listening on tcp-port 5555 which connects to tool 0 (data_up_0/data_down_0).
|
||||||
|
The TAP and ir value used to reach the JTAG Hub is given by the pld driver.
|
||||||
|
|
||||||
|
|
||||||
@node Utility Commands
|
@node Utility Commands
|
||||||
@chapter Utility Commands
|
@chapter Utility Commands
|
||||||
@cindex Utility Commands
|
@cindex Utility Commands
|
||||||
|
|
|
@ -16,13 +16,29 @@
|
||||||
|
|
||||||
#define PROGRAM 0x4
|
#define PROGRAM 0x4
|
||||||
#define ENTERUSER 0x7
|
#define ENTERUSER 0x7
|
||||||
|
#define USER1 0x8
|
||||||
|
#define USER2 0x9
|
||||||
|
#define USER3 0xa
|
||||||
|
#define USER4 0xb
|
||||||
|
|
||||||
|
enum efinix_family_e {
|
||||||
|
EFINIX_TRION,
|
||||||
|
EFINIX_TITANIUM,
|
||||||
|
EFINIX_UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
#define TRAILING_ZEROS 4000
|
#define TRAILING_ZEROS 4000
|
||||||
#define RUNTEST_START_CYCLES 100
|
#define RUNTEST_START_CYCLES 100
|
||||||
#define RUNTEST_FINISH_CYCLES 100
|
#define RUNTEST_FINISH_CYCLES 100
|
||||||
|
|
||||||
|
struct efinix_device {
|
||||||
|
uint32_t idcode;
|
||||||
|
int num_user;
|
||||||
|
};
|
||||||
|
|
||||||
struct efinix_pld_device {
|
struct efinix_pld_device {
|
||||||
struct jtag_tap *tap;
|
struct jtag_tap *tap;
|
||||||
|
enum efinix_family_e family;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
|
static int efinix_read_bit_file(struct raw_bit_file *bit_file, const char *filename)
|
||||||
|
@ -188,9 +204,54 @@ static int efinix_load(struct pld_device *pld_device, const char *filename)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int efinix_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct efinix_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
if (!pld_device_info || !pld_device_info->tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
hub->tap = pld_device_info->tap;
|
||||||
|
|
||||||
|
if (pld_device_info->family == EFINIX_UNKNOWN) {
|
||||||
|
LOG_ERROR("family unknown, please specify for 'pld create'");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
int num_user = 2; /* trion */
|
||||||
|
if (pld_device_info->family == EFINIX_TITANIUM)
|
||||||
|
num_user = 4;
|
||||||
|
|
||||||
|
if (user_num > num_user) {
|
||||||
|
LOG_ERROR("Devices has only user register 1 to %d", num_user);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (user_num) {
|
||||||
|
case 1:
|
||||||
|
hub->user_ir_code = USER1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
hub->user_ir_code = USER2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
hub->user_ir_code = USER3;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
hub->user_ir_code = USER4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOG_ERROR("efinix devices only have user register 1 to %d", num_user);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
|
PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 4)
|
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
if (strcmp(CMD_ARGV[2], "-chain-position") != 0)
|
||||||
|
@ -202,12 +263,28 @@ PLD_CREATE_COMMAND_HANDLER(efinix_pld_create_command)
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum efinix_family_e family = EFINIX_UNKNOWN;
|
||||||
|
if (CMD_ARGC == 6) {
|
||||||
|
if (strcmp(CMD_ARGV[4], "-family") != 0)
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
|
||||||
|
if (strcmp(CMD_ARGV[5], "trion") == 0) {
|
||||||
|
family = EFINIX_TRION;
|
||||||
|
} else if (strcmp(CMD_ARGV[5], "titanium") == 0) {
|
||||||
|
family = EFINIX_TITANIUM;
|
||||||
|
} else {
|
||||||
|
command_print(CMD, "unknown family");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
|
struct efinix_pld_device *efinix_info = malloc(sizeof(struct efinix_pld_device));
|
||||||
if (!efinix_info) {
|
if (!efinix_info) {
|
||||||
LOG_ERROR("Out of memory");
|
LOG_ERROR("Out of memory");
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
efinix_info->tap = tap;
|
efinix_info->tap = tap;
|
||||||
|
efinix_info->family = family;
|
||||||
|
|
||||||
pld->driver_priv = efinix_info;
|
pld->driver_priv = efinix_info;
|
||||||
|
|
||||||
|
@ -218,4 +295,5 @@ struct pld_driver efinix_pld = {
|
||||||
.name = "efinix",
|
.name = "efinix",
|
||||||
.pld_create_command = &efinix_pld_create_command,
|
.pld_create_command = &efinix_pld_create_command,
|
||||||
.load = &efinix_load,
|
.load = &efinix_load,
|
||||||
|
.get_ipdbg_hub = efinix_get_ipdbg_hub,
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
#define ERASE_FLASH 0x75
|
#define ERASE_FLASH 0x75
|
||||||
#define ENABLE_2ND_FLASH 0x78
|
#define ENABLE_2ND_FLASH 0x78
|
||||||
|
|
||||||
|
#define USER1 0x42
|
||||||
|
#define USER2 0x43
|
||||||
|
|
||||||
#define STAUS_MASK_MEMORY_ERASE BIT(5)
|
#define STAUS_MASK_MEMORY_ERASE BIT(5)
|
||||||
#define STAUS_MASK_SYSTEM_EDIT_MODE BIT(7)
|
#define STAUS_MASK_SYSTEM_EDIT_MODE BIT(7)
|
||||||
|
|
||||||
|
@ -449,6 +452,29 @@ static int gowin_reload_command(struct pld_device *pld_device)
|
||||||
return gowin_reload(gowin_info->tap);
|
return gowin_reload(gowin_info->tap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int gowin_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct gowin_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
if (!pld_device_info || !pld_device_info->tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
hub->tap = pld_device_info->tap;
|
||||||
|
|
||||||
|
if (user_num == 1) {
|
||||||
|
hub->user_ir_code = USER1;
|
||||||
|
} else if (user_num == 2) {
|
||||||
|
hub->user_ir_code = USER2;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("gowin devices only have user register 1 & 2");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(gowin_read_status_command_handler)
|
COMMAND_HANDLER(gowin_read_status_command_handler)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 1)
|
if (CMD_ARGC != 1)
|
||||||
|
@ -568,4 +594,5 @@ struct pld_driver gowin_pld = {
|
||||||
.commands = gowin_command_handler,
|
.commands = gowin_command_handler,
|
||||||
.pld_create_command = &gowin_pld_create_command,
|
.pld_create_command = &gowin_pld_create_command,
|
||||||
.load = &gowin_load_to_sram,
|
.load = &gowin_load_to_sram,
|
||||||
|
.get_ipdbg_hub = gowin_get_ipdbg_hub,
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
#include "raw_bit.h"
|
#include "raw_bit.h"
|
||||||
|
|
||||||
#define BYPASS 0x3FF
|
#define BYPASS 0x3FF
|
||||||
|
#define USER0 0x00C
|
||||||
|
#define USER1 0x00E
|
||||||
|
|
||||||
enum intel_family_e {
|
enum intel_family_e {
|
||||||
INTEL_CYCLONEIII,
|
INTEL_CYCLONEIII,
|
||||||
|
@ -337,6 +339,29 @@ static int intel_load(struct pld_device *pld_device, const char *filename)
|
||||||
return jtag_execute_queue();
|
return jtag_execute_queue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int intel_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct intel_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
if (!pld_device_info || !pld_device_info->tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
hub->tap = pld_device_info->tap;
|
||||||
|
|
||||||
|
if (user_num == 0) {
|
||||||
|
hub->user_ir_code = USER0;
|
||||||
|
} else if (user_num == 1) {
|
||||||
|
hub->user_ir_code = USER1;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("intel devices only have user register 0 & 1");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(intel_set_bscan_command_handler)
|
COMMAND_HANDLER(intel_set_bscan_command_handler)
|
||||||
{
|
{
|
||||||
unsigned int boundary_scan_length;
|
unsigned int boundary_scan_length;
|
||||||
|
@ -472,4 +497,5 @@ struct pld_driver intel_pld = {
|
||||||
.commands = intel_command_handler,
|
.commands = intel_command_handler,
|
||||||
.pld_create_command = &intel_pld_create_command,
|
.pld_create_command = &intel_pld_create_command,
|
||||||
.load = &intel_load,
|
.load = &intel_load,
|
||||||
|
.get_ipdbg_hub = intel_get_ipdbg_hub,
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
#include "certus.h"
|
#include "certus.h"
|
||||||
|
|
||||||
#define PRELOAD 0x1C
|
#define PRELOAD 0x1C
|
||||||
|
#define USER1 0x32
|
||||||
|
#define USER2 0x38
|
||||||
|
|
||||||
|
|
||||||
struct lattice_devices_elem {
|
struct lattice_devices_elem {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
|
@ -316,6 +319,29 @@ static int lattice_load_command(struct pld_device *pld_device, const char *filen
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int lattice_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct lattice_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
if (!pld_device_info || !pld_device_info->tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
hub->tap = pld_device_info->tap;
|
||||||
|
|
||||||
|
if (user_num == 1) {
|
||||||
|
hub->user_ir_code = USER1;
|
||||||
|
} else if (user_num == 2) {
|
||||||
|
hub->user_ir_code = USER2;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("lattice devices only have user register 1 & 2");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
|
PLD_CREATE_COMMAND_HANDLER(lattice_pld_create_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
if (CMD_ARGC != 4 && CMD_ARGC != 6)
|
||||||
|
@ -524,4 +550,5 @@ struct pld_driver lattice_pld = {
|
||||||
.commands = lattice_command_handler,
|
.commands = lattice_command_handler,
|
||||||
.pld_create_command = &lattice_pld_create_command,
|
.pld_create_command = &lattice_pld_create_command,
|
||||||
.load = &lattice_load_command,
|
.load = &lattice_load_command,
|
||||||
|
.get_ipdbg_hub = lattice_get_ipdbg_hub,
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,11 +15,17 @@ struct pld_device;
|
||||||
#define __PLD_CREATE_COMMAND(name) \
|
#define __PLD_CREATE_COMMAND(name) \
|
||||||
COMMAND_HELPER(name, struct pld_device *pld)
|
COMMAND_HELPER(name, struct pld_device *pld)
|
||||||
|
|
||||||
|
struct pld_ipdbg_hub {
|
||||||
|
struct jtag_tap *tap;
|
||||||
|
unsigned int user_ir_code;
|
||||||
|
};
|
||||||
|
|
||||||
struct pld_driver {
|
struct pld_driver {
|
||||||
const char *name;
|
const char *name;
|
||||||
__PLD_CREATE_COMMAND((*pld_create_command));
|
__PLD_CREATE_COMMAND((*pld_create_command));
|
||||||
const struct command_registration *commands;
|
const struct command_registration *commands;
|
||||||
int (*load)(struct pld_device *pld_device, const char *filename);
|
int (*load)(struct pld_device *pld_device, const char *filename);
|
||||||
|
int (*get_ipdbg_hub)(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
#define PLD_CREATE_COMMAND_HANDLER(name) \
|
||||||
|
|
|
@ -306,6 +306,26 @@ COMMAND_HANDLER(virtex2_handle_read_stat_command)
|
||||||
return ERROR_OK;
|
return ERROR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int xilinx_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub)
|
||||||
|
{
|
||||||
|
if (!pld_device)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
struct virtex2_pld_device *pld_device_info = pld_device->driver_priv;
|
||||||
|
|
||||||
|
if (!pld_device_info || !pld_device_info->tap)
|
||||||
|
return ERROR_FAIL;
|
||||||
|
|
||||||
|
hub->tap = pld_device_info->tap;
|
||||||
|
if (user_num < 1 || (unsigned int)user_num > pld_device_info->command_set.num_user) {
|
||||||
|
LOG_ERROR("device has only user register 1 to %d", pld_device_info->command_set.num_user);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hub->user_ir_code = pld_device_info->command_set.user[user_num - 1];
|
||||||
|
return ERROR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
|
COMMAND_HANDLER(virtex2_handle_set_instuction_codes_command)
|
||||||
{
|
{
|
||||||
if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
|
if (CMD_ARGC < 6 || CMD_ARGC > (6 + VIRTEX2_MAX_USER_INSTRUCTIONS))
|
||||||
|
@ -439,4 +459,5 @@ struct pld_driver virtex2_pld = {
|
||||||
.commands = virtex2_command_handler,
|
.commands = virtex2_command_handler,
|
||||||
.pld_create_command = &virtex2_pld_create_command,
|
.pld_create_command = &virtex2_pld_create_command,
|
||||||
.load = &virtex2_load,
|
.load = &virtex2_load,
|
||||||
|
.get_ipdbg_hub = xilinx_get_ipdbg_hub,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,11 +10,12 @@
|
||||||
#include <jtag/jtag.h>
|
#include <jtag/jtag.h>
|
||||||
#include <server/server.h>
|
#include <server/server.h>
|
||||||
#include <target/target.h>
|
#include <target/target.h>
|
||||||
|
#include <pld/pld.h>
|
||||||
|
|
||||||
#include "ipdbg.h"
|
#include "ipdbg.h"
|
||||||
|
|
||||||
#define IPDBG_BUFFER_SIZE 16384
|
#define IPDBG_BUFFER_SIZE 16384
|
||||||
#define IPDBG_MIN_NUM_OF_OPTIONS 4
|
#define IPDBG_MIN_NUM_OF_OPTIONS 2
|
||||||
#define IPDBG_MAX_NUM_OF_OPTIONS 14
|
#define IPDBG_MAX_NUM_OF_OPTIONS 14
|
||||||
#define IPDBG_MIN_DR_LENGTH 11
|
#define IPDBG_MIN_DR_LENGTH 11
|
||||||
#define IPDBG_MAX_DR_LENGTH 13
|
#define IPDBG_MAX_DR_LENGTH 13
|
||||||
|
@ -716,6 +717,7 @@ COMMAND_HANDLER(handle_ipdbg_command)
|
||||||
uint32_t virtual_ir_length = 5;
|
uint32_t virtual_ir_length = 5;
|
||||||
uint32_t virtual_ir_value = 0x11;
|
uint32_t virtual_ir_value = 0x11;
|
||||||
struct ipdbg_virtual_ir_info *virtual_ir = NULL;
|
struct ipdbg_virtual_ir_info *virtual_ir = NULL;
|
||||||
|
int user_num = 1;
|
||||||
|
|
||||||
if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
|
if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
|
||||||
return ERROR_COMMAND_SYNTAX_ERROR;
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
@ -742,6 +744,34 @@ COMMAND_HANDLER(handle_ipdbg_command)
|
||||||
IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH);
|
IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH);
|
||||||
return ERROR_FAIL;
|
return ERROR_FAIL;
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(CMD_ARGV[i], "-pld") == 0) {
|
||||||
|
++i;
|
||||||
|
if (i >= CMD_ARGC || CMD_ARGV[i][0] == '-')
|
||||||
|
return ERROR_COMMAND_SYNTAX_ERROR;
|
||||||
|
struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[i]);
|
||||||
|
if (!device || !device->driver) {
|
||||||
|
command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[i]);
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
COMMAND_PARSE_OPTIONAL_NUMBER(int, i, user_num);
|
||||||
|
struct pld_ipdbg_hub pld_hub;
|
||||||
|
struct pld_driver *driver = device->driver;
|
||||||
|
if (!driver->get_ipdbg_hub) {
|
||||||
|
command_print(CMD, "pld driver has no ipdbg support");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
if (driver->get_ipdbg_hub(user_num, device, &pld_hub) != ERROR_OK) {
|
||||||
|
command_print(CMD, "unable to retrieve hub from pld driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
if (!pld_hub.tap) {
|
||||||
|
command_print(CMD, "no tap received from pld driver");
|
||||||
|
return ERROR_FAIL;
|
||||||
|
}
|
||||||
|
hub_configured = true;
|
||||||
|
user_instruction = pld_hub.user_ir_code;
|
||||||
|
tap = pld_hub.tap;
|
||||||
|
|
||||||
} else if (strcmp(CMD_ARGV[i], "-vir") == 0) {
|
} else if (strcmp(CMD_ARGV[i], "-vir") == 0) {
|
||||||
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value);
|
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value);
|
||||||
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
|
COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
|
||||||
|
|
|
@ -20,4 +20,4 @@ jtag newtap $_CHIPNAME tap -irlen 5 -ignore-version \
|
||||||
-expected-id 0x00680A79 \
|
-expected-id 0x00680A79 \
|
||||||
-expected-id 0x00684A79
|
-expected-id 0x00684A79
|
||||||
|
|
||||||
pld create $_CHIPNAME.pld efinix -chain-position $_CHIPNAME.tap
|
pld create $_CHIPNAME.pld efinix -chain-position $_CHIPNAME.tap -family titanium
|
||||||
|
|
|
@ -14,4 +14,4 @@ jtag newtap $_CHIPNAME tap -irlen 4 -ignore-version \
|
||||||
-expected-id 0x00240A79 \
|
-expected-id 0x00240A79 \
|
||||||
-expected-id 0x00220A79
|
-expected-id 0x00220A79
|
||||||
|
|
||||||
pld create $_CHIPNAME.pld efinix -chain-position $_CHIPNAME.tap
|
pld create $_CHIPNAME.pld efinix -chain-position $_CHIPNAME.tap -family trion
|
||||||
|
|
Loading…
Reference in New Issue