OpenOCD
jtag_dpi.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /*
4  * JTAG to DPI driver
5  *
6  * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
7  *
8  * Copyright (C) 2019-2020, Ampere Computing LLC
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  */
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 #include <jtag/interface.h>
19 #ifdef HAVE_ARPA_INET_H
20 #include <arpa/inet.h>
21 #endif
22 
23 #ifndef _WIN32
24 #include <netinet/tcp.h>
25 #endif
26 
27 #define SERVER_ADDRESS "127.0.0.1"
28 #define SERVER_PORT 5555
29 
30 static uint16_t server_port = SERVER_PORT;
31 static char *server_address;
32 
33 static int sockfd;
34 static struct sockaddr_in serv_addr;
35 
36 static uint8_t *last_ir_buf;
37 static int last_ir_num_bits;
38 
39 static int write_sock(char *buf, size_t len)
40 {
41  if (!buf) {
42  LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
43  __func__, __FILE__, __LINE__);
44  return ERROR_FAIL;
45  }
46  if (write(sockfd, buf, len) != (ssize_t)len) {
47  LOG_ERROR("%s: %s, file %s, line %d", __func__,
48  strerror(errno), __FILE__, __LINE__);
49  return ERROR_FAIL;
50  }
51  return ERROR_OK;
52 }
53 
54 static int read_sock(char *buf, size_t len)
55 {
56  if (!buf) {
57  LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
58  __func__, __FILE__, __LINE__);
59  return ERROR_FAIL;
60  }
61  if (read(sockfd, buf, len) != (ssize_t)len) {
62  LOG_ERROR("%s: %s, file %s, line %d", __func__,
63  strerror(errno), __FILE__, __LINE__);
64  return ERROR_FAIL;
65  }
66  return ERROR_OK;
67 }
68 
74 static int jtag_dpi_reset(int trst, int srst)
75 {
76  char *buf = "reset\n";
77  int ret = ERROR_OK;
78 
79  LOG_DEBUG_IO("JTAG DRIVER DEBUG: reset trst: %i srst %i", trst, srst);
80 
81  if (trst == 1) {
82  /* reset the JTAG TAP controller */
83  ret = write_sock(buf, strlen(buf));
84  if (ret != ERROR_OK) {
85  LOG_ERROR("write_sock() fail, file %s, line %d",
86  __FILE__, __LINE__);
87  }
88  }
89 
90  if (srst == 1) {
91  /* System target reset not supported */
92  LOG_ERROR("DPI SRST not supported");
93  ret = ERROR_FAIL;
94  }
95 
96  return ret;
97 }
98 
107 static int jtag_dpi_scan(struct scan_command *cmd)
108 {
109  char buf[20];
110  uint8_t *data_buf;
111  int num_bits, bytes;
112  int ret = ERROR_OK;
113 
114  num_bits = jtag_build_buffer(cmd, &data_buf);
115  if (!data_buf) {
116  LOG_ERROR("jtag_build_buffer call failed, data_buf == NULL, "
117  "file %s, line %d", __FILE__, __LINE__);
118  return ERROR_FAIL;
119  }
120 
121  bytes = DIV_ROUND_UP(num_bits, 8);
122  if (cmd->ir_scan) {
123  free(last_ir_buf);
124  last_ir_buf = (uint8_t *)malloc(bytes * sizeof(uint8_t));
125  if (!last_ir_buf) {
126  LOG_ERROR("%s: malloc fail, file %s, line %d",
127  __func__, __FILE__, __LINE__);
128  ret = ERROR_FAIL;
129  goto out;
130  }
131  memcpy(last_ir_buf, data_buf, bytes);
132  last_ir_num_bits = num_bits;
133  }
134  snprintf(buf, sizeof(buf), "%s %d\n", cmd->ir_scan ? "ib" : "db", num_bits);
135  ret = write_sock(buf, strlen(buf));
136  if (ret != ERROR_OK) {
137  LOG_ERROR("write_sock() fail, file %s, line %d",
138  __FILE__, __LINE__);
139  goto out;
140  }
141  ret = write_sock((char *)data_buf, bytes);
142  if (ret != ERROR_OK) {
143  LOG_ERROR("write_sock() fail, file %s, line %d",
144  __FILE__, __LINE__);
145  goto out;
146  }
147  ret = read_sock((char *)data_buf, bytes);
148  if (ret != ERROR_OK) {
149  LOG_ERROR("read_sock() fail, file %s, line %d",
150  __FILE__, __LINE__);
151  goto out;
152  }
153 
154  ret = jtag_read_buffer(data_buf, cmd);
155  if (ret != ERROR_OK) {
156  LOG_ERROR("jtag_read_buffer() fail, file %s, line %d",
157  __FILE__, __LINE__);
158  goto out;
159  }
160 
161 out:
162  free(data_buf);
163  return ret;
164 }
165 
166 static int jtag_dpi_runtest(unsigned int num_cycles)
167 {
168  char buf[20];
169  uint8_t *data_buf = last_ir_buf, *read_scan;
170  int num_bits = last_ir_num_bits, bytes;
171  int ret = ERROR_OK;
172 
173  if (!data_buf) {
174  LOG_ERROR("%s: NULL 'data_buf' argument, file %s, line %d",
175  __func__, __FILE__, __LINE__);
176  return ERROR_FAIL;
177  }
178  if (num_bits <= 0) {
179  LOG_ERROR("%s: 'num_bits' invalid value, file %s, line %d",
180  __func__, __FILE__, __LINE__);
181  return ERROR_FAIL;
182  }
183 
184  bytes = DIV_ROUND_UP(num_bits, 8);
185  read_scan = (uint8_t *)malloc(bytes * sizeof(uint8_t));
186  if (!read_scan) {
187  LOG_ERROR("%s: malloc fail, file %s, line %d",
188  __func__, __FILE__, __LINE__);
189  return ERROR_FAIL;
190  }
191  snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
192  for (unsigned int cycle = 0; cycle < num_cycles; cycle += num_bits + 6) {
193  ret = write_sock(buf, strlen(buf));
194  if (ret != ERROR_OK) {
195  LOG_ERROR("write_sock() fail, file %s, line %d",
196  __FILE__, __LINE__);
197  goto out;
198  }
199  ret = write_sock((char *)data_buf, bytes);
200  if (ret != ERROR_OK) {
201  LOG_ERROR("write_sock() fail, file %s, line %d",
202  __FILE__, __LINE__);
203  goto out;
204  }
205  ret = read_sock((char *)read_scan, bytes);
206  if (ret != ERROR_OK) {
207  LOG_ERROR("read_sock() fail, file %s, line %d",
208  __FILE__, __LINE__);
209  goto out;
210  }
211  }
212 
213 out:
214  free(read_scan);
215  return ret;
216 }
217 
218 static int jtag_dpi_stableclocks(unsigned int num_cycles)
219 {
220  return jtag_dpi_runtest(num_cycles);
221 }
222 
223 static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue)
224 {
225  struct jtag_command *cmd;
226  int ret = ERROR_OK;
227 
228  for (cmd = cmd_queue; ret == ERROR_OK && cmd;
229  cmd = cmd->next) {
230  switch (cmd->type) {
231  case JTAG_RUNTEST:
232  ret = jtag_dpi_runtest(cmd->cmd.runtest->num_cycles);
233  break;
234  case JTAG_STABLECLOCKS:
235  ret = jtag_dpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
236  break;
237  case JTAG_TLR_RESET:
238  /* Enter Test-Logic-Reset state by asserting TRST */
239  if (cmd->cmd.statemove->end_state == TAP_RESET)
240  jtag_dpi_reset(1, 0);
241  break;
242  case JTAG_PATHMOVE:
243  /* unsupported */
244  break;
245  case JTAG_TMS:
246  /* unsupported */
247  break;
248  case JTAG_SLEEP:
249  jtag_sleep(cmd->cmd.sleep->us);
250  break;
251  case JTAG_SCAN:
252  ret = jtag_dpi_scan(cmd->cmd.scan);
253  break;
254  default:
255  LOG_ERROR("BUG: unknown JTAG command type 0x%X",
256  cmd->type);
257  ret = ERROR_FAIL;
258  break;
259  }
260  }
261 
262  return ret;
263 }
264 
265 static int jtag_dpi_init(void)
266 {
267  sockfd = socket(AF_INET, SOCK_STREAM, 0);
268  if (sockfd < 0) {
269  LOG_ERROR("socket: %s, function %s, file %s, line %d",
270  strerror(errno), __func__, __FILE__, __LINE__);
271  return ERROR_FAIL;
272  }
273 
274  memset(&serv_addr, 0, sizeof(serv_addr));
275 
276  serv_addr.sin_family = AF_INET;
277  serv_addr.sin_port = htons(server_port);
278 
279  if (!server_address) {
280  server_address = strdup(SERVER_ADDRESS);
281  if (!server_address) {
282  LOG_ERROR("%s: strdup fail, file %s, line %d",
283  __func__, __FILE__, __LINE__);
284  return ERROR_FAIL;
285  }
286  }
287 
288  serv_addr.sin_addr.s_addr = inet_addr(server_address);
289 
290  if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
291  LOG_ERROR("inet_addr error occurred");
292  return ERROR_FAIL;
293  }
294 
295  if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
296  close(sockfd);
297  LOG_ERROR("Can't connect to %s : %" PRIu16, server_address, server_port);
298  return ERROR_FAIL;
299  }
300  if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
301  /* This increases performance dramatically for local
302  * connections, which is the most likely arrangement
303  * for a DPI connection. */
304  int flag = 1;
305  setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
306  }
307 
308  LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
309 
310  return ERROR_OK;
311 }
312 
313 static int jtag_dpi_quit(void)
314 {
315  free(server_address);
317 
318  return close(sockfd);
319 }
320 
321 COMMAND_HANDLER(jtag_dpi_set_port)
322 {
323  if (CMD_ARGC > 1)
325  else if (CMD_ARGC == 0)
326  LOG_INFO("Using server port %" PRIu16, server_port);
327  else {
329  LOG_INFO("Set server port to %" PRIu16, server_port);
330  }
331 
332  return ERROR_OK;
333 }
334 
335 COMMAND_HANDLER(jtag_dpi_set_address)
336 {
337  if (CMD_ARGC > 1)
339  else if (CMD_ARGC == 0) {
340  if (!server_address) {
341  server_address = strdup(SERVER_ADDRESS);
342  if (!server_address) {
343  LOG_ERROR("%s: strdup fail, file %s, line %d",
344  __func__, __FILE__, __LINE__);
345  return ERROR_FAIL;
346  }
347  }
348  LOG_INFO("Using server address %s", server_address);
349  } else {
350  free(server_address);
351  server_address = strdup(CMD_ARGV[0]);
352  if (!server_address) {
353  LOG_ERROR("%s: strdup fail, file %s, line %d",
354  __func__, __FILE__, __LINE__);
355  return ERROR_FAIL;
356  }
357  LOG_INFO("Set server address to %s", server_address);
358  }
359 
360  return ERROR_OK;
361 }
362 
363 static const struct command_registration jtag_dpi_subcommand_handlers[] = {
364  {
365  .name = "set_port",
366  .handler = &jtag_dpi_set_port,
367  .mode = COMMAND_CONFIG,
368  .help = "set the port of the DPI server",
369  .usage = "[port]",
370  },
371  {
372  .name = "set_address",
373  .handler = &jtag_dpi_set_address,
374  .mode = COMMAND_CONFIG,
375  .help = "set the address of the DPI server",
376  .usage = "[address]",
377  },
379 };
380 
381 static const struct command_registration jtag_dpi_command_handlers[] = {
382  {
383  .name = "jtag_dpi",
384  .mode = COMMAND_ANY,
385  .help = "perform jtag_dpi management",
387  .usage = "",
388  },
390 };
391 
392 static struct jtag_interface jtag_dpi_interface = {
394  .execute_queue = jtag_dpi_execute_queue,
395 };
396 
398  .name = "jtag_dpi",
399  .transport_ids = TRANSPORT_JTAG,
400  .transport_preferred_id = TRANSPORT_JTAG,
401  .commands = jtag_dpi_command_handlers,
402  .init = jtag_dpi_init,
403  .quit = jtag_dpi_quit,
404  .reset = jtag_dpi_reset,
405  .jtag_ops = &jtag_dpi_interface,
406 };
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:400
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:440
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:251
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
Definition: commands.c:192
int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
Definition: commands.c:230
@ JTAG_TLR_RESET
Definition: commands.h:137
@ JTAG_SCAN
Definition: commands.h:129
@ JTAG_PATHMOVE
Definition: commands.h:140
@ JTAG_STABLECLOCKS
Definition: commands.h:142
@ JTAG_RUNTEST
Definition: commands.h:138
@ JTAG_SLEEP
Definition: commands.h:141
@ JTAG_TMS
Definition: commands.h:143
#define DEBUG_CAP_TMS_SEQ
Definition: interface.h:188
void jtag_sleep(uint32_t us)
Definition: jtag/core.c:1075
@ TAP_RESET
Definition: jtag.h:56
static struct jtag_interface jtag_dpi_interface
Definition: jtag_dpi.c:392
static int jtag_dpi_runtest(unsigned int num_cycles)
Definition: jtag_dpi.c:166
static int jtag_dpi_reset(int trst, int srst)
jtag_dpi_reset - ask to reset the JTAG device
Definition: jtag_dpi.c:74
static int last_ir_num_bits
Definition: jtag_dpi.c:37
static const struct command_registration jtag_dpi_command_handlers[]
Definition: jtag_dpi.c:381
static int jtag_dpi_stableclocks(unsigned int num_cycles)
Definition: jtag_dpi.c:218
static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue)
Definition: jtag_dpi.c:223
static const struct command_registration jtag_dpi_subcommand_handlers[]
Definition: jtag_dpi.c:363
static uint8_t * last_ir_buf
Definition: jtag_dpi.c:36
static int write_sock(char *buf, size_t len)
Definition: jtag_dpi.c:39
static uint16_t server_port
Definition: jtag_dpi.c:30
COMMAND_HANDLER(jtag_dpi_set_port)
Definition: jtag_dpi.c:321
static int read_sock(char *buf, size_t len)
Definition: jtag_dpi.c:54
static int jtag_dpi_quit(void)
Definition: jtag_dpi.c:313
#define SERVER_ADDRESS
Definition: jtag_dpi.c:27
static int jtag_dpi_scan(struct scan_command *cmd)
jtag_dpi_scan - launches a DR-scan or IR-scan
Definition: jtag_dpi.c:107
#define SERVER_PORT
Definition: jtag_dpi.c:28
static struct sockaddr_in serv_addr
Definition: jtag_dpi.c:34
static int sockfd
Definition: jtag_dpi.c:33
static int jtag_dpi_init(void)
Definition: jtag_dpi.c:265
static char * server_address
Definition: jtag_dpi.c:31
struct adapter_driver jtag_dpi_adapter_driver
Definition: jtag_dpi.c:397
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:103
#define ERROR_FAIL
Definition: log.h:175
#define LOG_ERROR(expr ...)
Definition: log.h:134
#define LOG_INFO(expr ...)
Definition: log.h:128
#define ERROR_OK
Definition: log.h:169
int flag
Definition: mips64.c:29
Represents a driver for a debugging interface.
Definition: interface.h:208
const char *const name
The name of the interface driver.
Definition: interface.h:210
const char * name
Definition: command.h:234
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:239
Represents a driver for a debugging interface.
Definition: interface.h:183
unsigned int supported
Bit vector listing capabilities exposed by this driver.
Definition: interface.h:187
The scan_command provide a means of encapsulating a set of scan_field structures that should be scann...
Definition: commands.h:35
#define TRANSPORT_JTAG
Definition: transport.h:19
#define DIV_ROUND_UP(m, n)
Rounds m up to the nearest multiple of n using division.
Definition: types.h:79
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1