drivers/bcm2835gpio: Migrate to adapter gpio commands
[openocd.git] / src / jtag / drivers / jtag_dpi.c
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
69 /**
70 * jtag_dpi_reset - ask to reset the JTAG device
71 * @param trst 1 if TRST is to be asserted
72 * @param srst 1 if SRST is to be asserted
73 */
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
99 /**
100 * jtag_dpi_scan - launches a DR-scan or IR-scan
101 * @param cmd the command to launch
102 *
103 * Launch a JTAG IR-scan or DR-scan
104 *
105 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
106 */
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(int 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 while (cycles > 0) {
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 cycles -= num_bits + 6;
213 }
214
215 out:
216 free(read_scan);
217 return ret;
218 }
219
220 static int jtag_dpi_stableclocks(int cycles)
221 {
222 return jtag_dpi_runtest(cycles);
223 }
224
225 static int jtag_dpi_execute_queue(void)
226 {
227 struct jtag_command *cmd;
228 int ret = ERROR_OK;
229
230 for (cmd = jtag_command_queue; ret == ERROR_OK && cmd;
231 cmd = cmd->next) {
232 switch (cmd->type) {
233 case JTAG_RUNTEST:
234 ret = jtag_dpi_runtest(cmd->cmd.runtest->num_cycles);
235 break;
236 case JTAG_STABLECLOCKS:
237 ret = jtag_dpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
238 break;
239 case JTAG_TLR_RESET:
240 /* Enter Test-Logic-Reset state by asserting TRST */
241 if (cmd->cmd.statemove->end_state == TAP_RESET)
242 jtag_dpi_reset(1, 0);
243 break;
244 case JTAG_PATHMOVE:
245 /* unsupported */
246 break;
247 case JTAG_TMS:
248 /* unsupported */
249 break;
250 case JTAG_SLEEP:
251 jtag_sleep(cmd->cmd.sleep->us);
252 break;
253 case JTAG_SCAN:
254 ret = jtag_dpi_scan(cmd->cmd.scan);
255 break;
256 default:
257 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
258 cmd->type);
259 ret = ERROR_FAIL;
260 break;
261 }
262 }
263
264 return ret;
265 }
266
267 static int jtag_dpi_init(void)
268 {
269 sockfd = socket(AF_INET, SOCK_STREAM, 0);
270 if (sockfd < 0) {
271 LOG_ERROR("socket: %s, function %s, file %s, line %d",
272 strerror(errno), __func__, __FILE__, __LINE__);
273 return ERROR_FAIL;
274 }
275
276 memset(&serv_addr, 0, sizeof(serv_addr));
277
278 serv_addr.sin_family = AF_INET;
279 serv_addr.sin_port = htons(server_port);
280
281 if (!server_address) {
282 server_address = strdup(SERVER_ADDRESS);
283 if (!server_address) {
284 LOG_ERROR("%s: strdup fail, file %s, line %d",
285 __func__, __FILE__, __LINE__);
286 return ERROR_FAIL;
287 }
288 }
289
290 serv_addr.sin_addr.s_addr = inet_addr(server_address);
291
292 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
293 LOG_ERROR("inet_addr error occurred");
294 return ERROR_FAIL;
295 }
296
297 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
298 close(sockfd);
299 LOG_ERROR("Can't connect to %s : %" PRIu16, server_address, server_port);
300 return ERROR_FAIL;
301 }
302 if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
303 /* This increases performance dramatically for local
304 * connections, which is the most likely arrangement
305 * for a DPI connection. */
306 int flag = 1;
307 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
308 }
309
310 LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
311
312 return ERROR_OK;
313 }
314
315 static int jtag_dpi_quit(void)
316 {
317 free(server_address);
318 server_address = NULL;
319
320 return close(sockfd);
321 }
322
323 COMMAND_HANDLER(jtag_dpi_set_port)
324 {
325 if (CMD_ARGC > 1)
326 return ERROR_COMMAND_SYNTAX_ERROR;
327 else if (CMD_ARGC == 0)
328 LOG_INFO("Using server port %" PRIu16, server_port);
329 else {
330 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], server_port);
331 LOG_INFO("Set server port to %" PRIu16, server_port);
332 }
333
334 return ERROR_OK;
335 }
336
337 COMMAND_HANDLER(jtag_dpi_set_address)
338 {
339 if (CMD_ARGC > 1)
340 return ERROR_COMMAND_SYNTAX_ERROR;
341 else if (CMD_ARGC == 0) {
342 if (!server_address) {
343 server_address = strdup(SERVER_ADDRESS);
344 if (!server_address) {
345 LOG_ERROR("%s: strdup fail, file %s, line %d",
346 __func__, __FILE__, __LINE__);
347 return ERROR_FAIL;
348 }
349 }
350 LOG_INFO("Using server address %s", server_address);
351 } else {
352 free(server_address);
353 server_address = strdup(CMD_ARGV[0]);
354 if (!server_address) {
355 LOG_ERROR("%s: strdup fail, file %s, line %d",
356 __func__, __FILE__, __LINE__);
357 return ERROR_FAIL;
358 }
359 LOG_INFO("Set server address to %s", server_address);
360 }
361
362 return ERROR_OK;
363 }
364
365 static const struct command_registration jtag_dpi_subcommand_handlers[] = {
366 {
367 .name = "set_port",
368 .handler = &jtag_dpi_set_port,
369 .mode = COMMAND_CONFIG,
370 .help = "set the port of the DPI server",
371 .usage = "[port]",
372 },
373 {
374 .name = "set_address",
375 .handler = &jtag_dpi_set_address,
376 .mode = COMMAND_CONFIG,
377 .help = "set the address of the DPI server",
378 .usage = "[address]",
379 },
380 COMMAND_REGISTRATION_DONE
381 };
382
383 static const struct command_registration jtag_dpi_command_handlers[] = {
384 {
385 .name = "jtag_dpi",
386 .mode = COMMAND_ANY,
387 .help = "perform jtag_dpi management",
388 .chain = jtag_dpi_subcommand_handlers,
389 .usage = "",
390 },
391 COMMAND_REGISTRATION_DONE
392 };
393
394 static struct jtag_interface jtag_dpi_interface = {
395 .supported = DEBUG_CAP_TMS_SEQ,
396 .execute_queue = jtag_dpi_execute_queue,
397 };
398
399 struct adapter_driver jtag_dpi_adapter_driver = {
400 .name = "jtag_dpi",
401 .transports = jtag_only,
402 .commands = jtag_dpi_command_handlers,
403 .init = jtag_dpi_init,
404 .quit = jtag_dpi_quit,
405 .reset = jtag_dpi_reset,
406 .jtag_ops = &jtag_dpi_interface,
407 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)