This is an automated email from Gerrit. "Daniel Anselmi <danse...@gmx.ch>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7369
-- gerrit commit d599cc818038b70ab39b0113439a6047223820fb Author: Daniel Anselmi <danse...@gmx.ch> Date: Mon Nov 21 04:15:02 2022 +0100 ipdbg/pld: ipdbg can get tap and hub/ir from pld driver. Change-Id: I13eeb9fee895d65cd48544da4704fcc9b528b869 Signed-off-by: Daniel Anselmi <danse...@gmx.ch> diff --git a/doc/openocd.texi b/doc/openocd.texi index f1081d51fc..b8ac705b6e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -11624,7 +11624,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 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. Command options: @@ -11633,15 +11633,28 @@ Command options: @item @option{-tap @var{tapname}} targeting the TAP @var{tapname}. @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}. -@item @option{-port @var{number}} tcp port number where the JTAG-Host is listening. -@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{-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{-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. 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 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 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 shift data through vir can be configured. @end itemize @end deffn +or +@deffn {Command} {ipdbg} [@option{-start|-stop}] @option{-pld @var{num} [@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{num} [@var{user}]} the information from the pld-driver is used and the options @option{-tap} and @option{-hub} are not required. +The defined driver @var{num} gets selected. (The number can be shown by the @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 0 which selects the first @verb{|USERx|} instruction is adequate. + +The remaining options are described in the previous command. +@end deffn Examples: @example diff --git a/src/pld/certus.c b/src/pld/certus.c index 805b42de19..b8dd768e02 100644 --- a/src/pld/certus.c +++ b/src/pld/certus.c @@ -376,9 +376,11 @@ static const struct command_registration certus_command_handler[] = { COMMAND_REGISTRATION_DONE }; + struct pld_driver certus_pld = { .name = "certus", .commands = certus_command_handler, .pld_device_command = &certus_pld_device_command, .load = &certus_load_command, + .get_ipdbg_hub = lattice_get_ipdbg_hub, }; diff --git a/src/pld/ecp2_3.c b/src/pld/ecp2_3.c index 987094c6dc..3eabab3b35 100644 --- a/src/pld/ecp2_3.c +++ b/src/pld/ecp2_3.c @@ -516,4 +516,5 @@ struct pld_driver ecp2_3_pld = { .commands = ecp2_3_command_handler, .pld_device_command = &ecp2_3_pld_device_command, .load = &ecp2_3_load, + .get_ipdbg_hub = lattice_get_ipdbg_hub, }; diff --git a/src/pld/ecp5.c b/src/pld/ecp5.c index 11e0996ee9..d98d6ac06e 100644 --- a/src/pld/ecp5.c +++ b/src/pld/ecp5.c @@ -426,4 +426,5 @@ struct pld_driver ecp5_pld = { .commands = ecp5_command_handler, .pld_device_command = &ecp5_pld_device_command, .load = &ecp5_load_command, + .get_ipdbg_hub = lattice_get_ipdbg_hub, }; diff --git a/src/pld/efinix.c b/src/pld/efinix.c index ae6f08bc55..7e16d1c4aa 100644 --- a/src/pld/efinix.c +++ b/src/pld/efinix.c @@ -17,6 +17,10 @@ #define PROGRAM 0x4 #define ENTERUSER 0x7 +#define USER1 0x8 +#define USER2 0x9 +#define USER3 0xa +#define USER4 0xb #define NO_FORCE 0 #define FORCE 1 @@ -201,6 +205,38 @@ static int trion_load(struct pld_device *pld_device, const char *filename) 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 trion_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; + + 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 4"); + return ERROR_FAIL; + } + return ERROR_OK; +} + PLD_DEVICE_COMMAND_HANDLER(trion_pld_device_command) { if (CMD_ARGC != 2) @@ -239,4 +275,5 @@ struct pld_driver trion_pld = { .commands = trion_command_handler, .pld_device_command = &trion_pld_device_command, .load = &trion_load, + .get_ipdbg_hub = efinix_get_ipdbg_hub, }; diff --git a/src/pld/gowin.c b/src/pld/gowin.c index 4b140f7563..8d55c40e20 100644 --- a/src/pld/gowin.c +++ b/src/pld/gowin.c @@ -28,6 +28,9 @@ #define ERASE_FLASH 0x75 #define ENABLE_2ND_FLASH 0x78 +#define USER1 0x42 +//#define USER2 + #define STAUS_MASK_MEMORY_ERASE (0x00000001 << 5) #define STAUS_MASK_SYSTEM_EDIT_MODE (0x00000001 << 7) @@ -470,6 +473,29 @@ static int gowin_reload_command(struct pld_device *pld_device) 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) { int dev_id; @@ -603,4 +629,5 @@ struct pld_driver gowin_pld = { .commands = gowin_command_handler, .pld_device_command = &gowin_pld_device_command, .load = &gowin_load_to_sram, + .get_ipdbg_hub = gowin_get_ipdbg_hub, }; diff --git a/src/pld/intel.c b/src/pld/intel.c index d13f49386a..e9b3176eb9 100644 --- a/src/pld/intel.c +++ b/src/pld/intel.c @@ -19,6 +19,8 @@ #include "raw_bit.h" #define BYPASS 0x3FF +#define USER1 0x00C +#define USER2 0x00E enum family_e {cycloneiii, cycloneiv, @@ -339,6 +341,29 @@ static int intel_load(struct pld_device *pld_device, const char *filename) 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 == 1) { + hub->user_ir_code = USER1; + } else if (user_num == 2) { + hub->user_ir_code = USER2; + } else { + LOG_ERROR("intel devices only have user register 1 & 2"); + return ERROR_FAIL; + } + return ERROR_OK; +} + COMMAND_HANDLER(intel_set_bscan_command_handler) { int dev_id; @@ -473,5 +498,6 @@ struct pld_driver intel_pld = { .commands = intel_command_handler, .pld_device_command = &intel_pld_device_command, .load = &intel_load, + .get_ipdbg_hub = intel_get_ipdbg_hub, }; diff --git a/src/pld/lattice.c b/src/pld/lattice.c index db0ec2c52d..78dd923305 100644 --- a/src/pld/lattice.c +++ b/src/pld/lattice.c @@ -11,6 +11,9 @@ #include "lattice.h" +#define USER1 0x32 +#define USER2 0x38 + void lattice_set_instr(struct jtag_tap *tap, uint8_t new_instr, tap_state_t endstate) { @@ -102,3 +105,26 @@ int lattice_preload(struct jtag_tap *tap, uint8_t preload_cmd, size_t length) free(buffer); 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; +} diff --git a/src/pld/lattice.h b/src/pld/lattice.h index 8f6f1ca882..95c09ddfc9 100644 --- a/src/pld/lattice.h +++ b/src/pld/lattice.h @@ -9,6 +9,7 @@ #define OPENOCD_PLD_LATTICE_H #include <jtag/jtag.h> +#include "pld.h" struct lattice_pld_device { struct jtag_tap *tap; @@ -27,5 +28,5 @@ int lattice_read_u64_register(struct jtag_tap *tap, uint8_t cmd, uint64_t *in_va int lattice_get_preload_length(uint32_t id, const struct lattice_devices_preload_length_elem *elems, size_t num_elems, size_t *length); int lattice_preload(struct jtag_tap *tap, uint8_t preload_cmd, size_t length); - +int lattice_get_ipdbg_hub(int user_num, struct pld_device *pld_device, struct pld_ipdbg_hub *hub); #endif /* OPENOCD_PLD_LATTICE_H */ diff --git a/src/pld/pld.h b/src/pld/pld.h index a7cd20f641..b3c102290d 100644 --- a/src/pld/pld.h +++ b/src/pld/pld.h @@ -15,11 +15,17 @@ struct pld_device; #define __PLD_DEVICE_COMMAND(name) \ COMMAND_HELPER(name, struct pld_device *pld) +struct pld_ipdbg_hub { + struct jtag_tap *tap; + unsigned int user_ir_code; +}; + struct pld_driver { const char *name; __PLD_DEVICE_COMMAND((*pld_device_command)); const struct command_registration *commands; 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_DEVICE_COMMAND_HANDLER(name) \ diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c index 98fd58adbb..8524f28826 100644 --- a/src/pld/virtex2.c +++ b/src/pld/virtex2.c @@ -13,6 +13,11 @@ #include "xilinx_bit.h" #include "pld.h" +#define USER1 0x02 +#define USER2 0x03 +#define USER3 0x22 +#define USER4 0x23 + static int virtex2_set_instr(struct jtag_tap *tap, uint32_t new_instr) { if (!tap) @@ -162,6 +167,38 @@ static int virtex2_load(struct pld_device *pld_device, const char *filename) return ERROR_OK; } +static int virtex2_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; + + 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 4"); + return ERROR_FAIL; + } + return ERROR_OK; +} + COMMAND_HANDLER(virtex2_handle_read_stat_command) { struct pld_device *device; @@ -238,4 +275,5 @@ struct pld_driver virtex2_pld = { .commands = virtex2_command_handler, .pld_device_command = &virtex2_pld_device_command, .load = &virtex2_load, + .get_ipdbg_hub = virtex2_get_ipdbg_hub, }; diff --git a/src/server/ipdbg.c b/src/server/ipdbg.c index f4a6f6cdcc..ec76bdaf9e 100644 --- a/src/server/ipdbg.c +++ b/src/server/ipdbg.c @@ -10,11 +10,12 @@ #include <jtag/jtag.h> #include <server/server.h> #include <target/target.h> +#include <pld/pld.h> #include "ipdbg.h" #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_MIN_DR_LENGTH 11 #define IPDBG_MAX_DR_LENGTH 13 @@ -90,7 +91,7 @@ static void ipdbg_zero_rd_idx(struct ipdbg_fifo *fifo) return; size_t ri = fifo->rd_idx; - for (size_t idx = 0 ; idx < fifo->count ; ++idx) + for (size_t idx = 0; idx < fifo->count; ++idx) fifo->buffer[idx] = fifo->buffer[ri++]; fifo->rd_idx = 0; } @@ -149,7 +150,7 @@ static int ipdbg_max_tools_from_data_register_length(uint8_t data_register_lengt static struct ipdbg_service *ipdbg_find_service(struct ipdbg_hub *hub, uint8_t tool) { struct ipdbg_service *service; - for (service = ipdbg_first_service ; service ; service = service->next) { + for (service = ipdbg_first_service; service; service = service->next) { if (service->hub == hub && service->tool == tool) break; } @@ -160,7 +161,7 @@ static void ipdbg_add_service(struct ipdbg_service *service) { struct ipdbg_service *iservice; if (ipdbg_first_service) { - for (iservice = ipdbg_first_service ; iservice->next; iservice = iservice->next) + for (iservice = ipdbg_first_service; iservice->next; iservice = iservice->next) ; iservice->next = service; } else @@ -192,7 +193,7 @@ static int ipdbg_remove_service(struct ipdbg_service *service) return ERROR_OK; } - for (struct ipdbg_service *iservice = ipdbg_first_service ; iservice->next ; iservice = iservice->next) { + for (struct ipdbg_service *iservice = ipdbg_first_service; iservice->next; iservice = iservice->next) { if (service == iservice->next) { iservice->next = service->next; return ERROR_OK; @@ -205,7 +206,7 @@ static struct ipdbg_hub *ipdbg_find_hub(struct jtag_tap *tap, uint32_t user_instruction, struct ipdbg_virtual_ir_info *virtual_ir) { struct ipdbg_hub *hub = NULL; - for (hub = ipdbg_first_hub ; hub ; hub = hub->next) { + for (hub = ipdbg_first_hub; hub; hub = hub->next) { if (hub->tap == tap && hub->user_instruction == user_instruction) { if ((!virtual_ir && !hub->virtual_ir) || (virtual_ir && hub->virtual_ir && @@ -223,7 +224,7 @@ static void ipdbg_add_hub(struct ipdbg_hub *hub) { struct ipdbg_hub *ihub; if (ipdbg_first_hub) { - for (ihub = ipdbg_first_hub ; ihub->next; ihub = ihub->next) + for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) ; ihub->next = hub; } else @@ -281,7 +282,7 @@ static int ipdbg_remove_hub(struct ipdbg_hub *hub) return ERROR_OK; } - for (struct ipdbg_hub *ihub = ipdbg_first_hub ; ihub->next ; ihub = ihub->next) { + for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) { if (hub == ihub->next) { ihub->next = hub->next; return ERROR_OK; @@ -447,7 +448,7 @@ static int ipdbg_polling_callback(void *priv) /* transfer dn buffers to jtag-hub */ unsigned int num_transfers = 0; - for (size_t tool = 0 ; tool < hub->max_tools ; ++tool) { + for (size_t tool = 0; tool < hub->max_tools; ++tool) { struct connection *conn = hub->connections[tool]; if (conn && conn->priv) { struct ipdbg_connection *connection = conn->priv; @@ -475,7 +476,7 @@ static int ipdbg_polling_callback(void *priv) } /* write from up fifos to sockets */ - for (size_t tool = 0 ; tool < hub->max_tools ; ++tool) { + for (size_t tool = 0; tool < hub->max_tools; ++tool) { struct connection *conn = hub->connections[tool]; if (conn && conn->priv) { struct ipdbg_connection *connection = conn->priv; @@ -695,6 +696,8 @@ COMMAND_HANDLER(handle_ipdbg_command) uint32_t virtual_ir_length = 5; uint32_t virtual_ir_value = 0x11; struct ipdbg_virtual_ir_info *virtual_ir = NULL; + int pld_dev_id; + int user_num = 1; if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS)) return ERROR_COMMAND_SYNTAX_ERROR; @@ -721,6 +724,28 @@ COMMAND_HANDLER(handle_ipdbg_command) IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH); return ERROR_FAIL; } + } else if (strcmp(CMD_ARGV[i], "-pld") == 0) { + COMMAND_PARSE_ADDITIONAL_NUMBER(int, i, pld_dev_id, "choose pld driver instance"); + COMMAND_PARSE_OPTIONAL_NUMBER(int, i, user_num); + struct pld_device *device = get_pld_device_by_num(pld_dev_id); + if (!device || !device->driver) { + command_print(CMD, "pld device '#%s' is out of bounds", CMD_ARGV[i + 1]); + return ERROR_FAIL; + } + struct pld_ipdbg_hub pld_hub; + struct pld_driver *driver = device->driver; + 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) { COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value); COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length); --