flash/stm32l4x: fix dual bank support for STM32L552xC devices
[openocd.git] / src / jtag / drivers / remote_bitbang.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Richard Uhler *
3 * ruhler@mit.edu *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #ifndef _WIN32
24 #include <sys/un.h>
25 #include <netdb.h>
26 #endif
27 #include "helper/system.h"
28 #include "helper/replacements.h"
29 #include <jtag/interface.h>
30 #include "bitbang.h"
31
32 /* arbitrary limit on host name length: */
33 #define REMOTE_BITBANG_HOST_MAX 255
34
35 static char *remote_bitbang_host;
36 static char *remote_bitbang_port;
37
38 static int remote_bitbang_fd;
39 static uint8_t remote_bitbang_send_buf[512];
40 static unsigned int remote_bitbang_send_buf_used;
41
42 /* Circular buffer. When start == end, the buffer is empty. */
43 static char remote_bitbang_recv_buf[64];
44 static unsigned int remote_bitbang_recv_buf_start;
45 static unsigned int remote_bitbang_recv_buf_end;
46
47 static bool remote_bitbang_buf_full(void)
48 {
49 return remote_bitbang_recv_buf_end ==
50 ((remote_bitbang_recv_buf_start + sizeof(remote_bitbang_recv_buf) - 1) %
51 sizeof(remote_bitbang_recv_buf));
52 }
53
54 /* Read any incoming data, placing it into the buffer. */
55 static int remote_bitbang_fill_buf(void)
56 {
57 socket_nonblock(remote_bitbang_fd);
58 while (!remote_bitbang_buf_full()) {
59 unsigned int contiguous_available_space;
60 if (remote_bitbang_recv_buf_end >= remote_bitbang_recv_buf_start) {
61 contiguous_available_space = sizeof(remote_bitbang_recv_buf) -
62 remote_bitbang_recv_buf_end;
63 if (remote_bitbang_recv_buf_start == 0)
64 contiguous_available_space -= 1;
65 } else {
66 contiguous_available_space = remote_bitbang_recv_buf_start -
67 remote_bitbang_recv_buf_end - 1;
68 }
69 ssize_t count = read_socket(remote_bitbang_fd,
70 remote_bitbang_recv_buf + remote_bitbang_recv_buf_end,
71 contiguous_available_space);
72 if (count > 0) {
73 remote_bitbang_recv_buf_end += count;
74 if (remote_bitbang_recv_buf_end == sizeof(remote_bitbang_recv_buf))
75 remote_bitbang_recv_buf_end = 0;
76 } else if (count == 0) {
77 return ERROR_OK;
78 } else if (count < 0) {
79 #ifdef _WIN32
80 if (WSAGetLastError() == WSAEWOULDBLOCK) {
81 #else
82 if (errno == EAGAIN) {
83 #endif
84 return ERROR_OK;
85 } else {
86 log_socket_error("remote_bitbang_fill_buf");
87 return ERROR_FAIL;
88 }
89 }
90 }
91
92 return ERROR_OK;
93 }
94
95 static int remote_bitbang_flush(void)
96 {
97 if (remote_bitbang_send_buf_used <= 0)
98 return ERROR_OK;
99
100 unsigned int offset = 0;
101 while (offset < remote_bitbang_send_buf_used) {
102 ssize_t written = write_socket(remote_bitbang_fd, remote_bitbang_send_buf + offset,
103 remote_bitbang_send_buf_used - offset);
104 if (written < 0) {
105 log_socket_error("remote_bitbang_putc");
106 remote_bitbang_send_buf_used = 0;
107 return ERROR_FAIL;
108 }
109 offset += written;
110 }
111 remote_bitbang_send_buf_used = 0;
112 return ERROR_OK;
113 }
114
115 typedef enum {
116 NO_FLUSH,
117 FLUSH_SEND_BUF
118 } flush_bool_t;
119
120 static int remote_bitbang_queue(int c, flush_bool_t flush)
121 {
122 remote_bitbang_send_buf[remote_bitbang_send_buf_used++] = c;
123 if (flush == FLUSH_SEND_BUF ||
124 remote_bitbang_send_buf_used >= ARRAY_SIZE(remote_bitbang_send_buf))
125 return remote_bitbang_flush();
126 return ERROR_OK;
127 }
128
129 static int remote_bitbang_quit(void)
130 {
131 if (remote_bitbang_queue('Q', FLUSH_SEND_BUF) == ERROR_FAIL)
132 return ERROR_FAIL;
133
134 if (close_socket(remote_bitbang_fd) != 0) {
135 log_socket_error("close_socket");
136 return ERROR_FAIL;
137 }
138
139 free(remote_bitbang_host);
140 free(remote_bitbang_port);
141
142 LOG_INFO("remote_bitbang interface quit");
143 return ERROR_OK;
144 }
145
146 static bb_value_t char_to_int(int c)
147 {
148 switch (c) {
149 case '0':
150 return BB_LOW;
151 case '1':
152 return BB_HIGH;
153 default:
154 remote_bitbang_quit();
155 LOG_ERROR("remote_bitbang: invalid read response: %c(%i)", c, c);
156 return BB_ERROR;
157 }
158 }
159
160 /* Get the next read response. */
161 static bb_value_t remote_bitbang_rread(void)
162 {
163 if (remote_bitbang_flush() != ERROR_OK)
164 return ERROR_FAIL;
165
166 /* Enable blocking access. */
167 socket_block(remote_bitbang_fd);
168 char c;
169 ssize_t count = read_socket(remote_bitbang_fd, &c, 1);
170 if (count == 1) {
171 return char_to_int(c);
172 } else {
173 remote_bitbang_quit();
174 LOG_ERROR("read_socket: count=%d", (int) count);
175 log_socket_error("read_socket");
176 return BB_ERROR;
177 }
178 }
179
180 static int remote_bitbang_sample(void)
181 {
182 if (remote_bitbang_fill_buf() != ERROR_OK)
183 return ERROR_FAIL;
184 assert(!remote_bitbang_buf_full());
185 return remote_bitbang_queue('R', NO_FLUSH);
186 }
187
188 static bb_value_t remote_bitbang_read_sample(void)
189 {
190 if (remote_bitbang_recv_buf_start == remote_bitbang_recv_buf_end) {
191 if (remote_bitbang_fill_buf() != ERROR_OK)
192 return ERROR_FAIL;
193 }
194 if (remote_bitbang_recv_buf_start != remote_bitbang_recv_buf_end) {
195 int c = remote_bitbang_recv_buf[remote_bitbang_recv_buf_start];
196 remote_bitbang_recv_buf_start =
197 (remote_bitbang_recv_buf_start + 1) % sizeof(remote_bitbang_recv_buf);
198 return char_to_int(c);
199 }
200 return remote_bitbang_rread();
201 }
202
203 static int remote_bitbang_write(int tck, int tms, int tdi)
204 {
205 char c = '0' + ((tck ? 0x4 : 0x0) | (tms ? 0x2 : 0x0) | (tdi ? 0x1 : 0x0));
206 return remote_bitbang_queue(c, NO_FLUSH);
207 }
208
209 static int remote_bitbang_reset(int trst, int srst)
210 {
211 char c = 'r' + ((trst ? 0x2 : 0x0) | (srst ? 0x1 : 0x0));
212 /* Always flush the send buffer on reset, because the reset call need not be
213 * followed by jtag_execute_queue(). */
214 return remote_bitbang_queue(c, FLUSH_SEND_BUF);
215 }
216
217 static int remote_bitbang_blink(int on)
218 {
219 char c = on ? 'B' : 'b';
220 return remote_bitbang_queue(c, FLUSH_SEND_BUF);
221 }
222
223 static struct bitbang_interface remote_bitbang_bitbang = {
224 .buf_size = sizeof(remote_bitbang_recv_buf) - 1,
225 .sample = &remote_bitbang_sample,
226 .read_sample = &remote_bitbang_read_sample,
227 .write = &remote_bitbang_write,
228 .blink = &remote_bitbang_blink,
229 };
230
231 static int remote_bitbang_init_tcp(void)
232 {
233 struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM };
234 struct addrinfo *result, *rp;
235 int fd = 0;
236
237 LOG_INFO("Connecting to %s:%s",
238 remote_bitbang_host ? remote_bitbang_host : "localhost",
239 remote_bitbang_port);
240
241 /* Obtain address(es) matching host/port */
242 int s = getaddrinfo(remote_bitbang_host, remote_bitbang_port, &hints, &result);
243 if (s != 0) {
244 LOG_ERROR("getaddrinfo: %s\n", gai_strerror(s));
245 return ERROR_FAIL;
246 }
247
248 /* getaddrinfo() returns a list of address structures.
249 Try each address until we successfully connect(2).
250 If socket(2) (or connect(2)) fails, we (close the socket
251 and) try the next address. */
252
253 for (rp = result; rp ; rp = rp->ai_next) {
254 fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
255 if (fd == -1)
256 continue;
257
258 if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1)
259 break; /* Success */
260
261 close(fd);
262 }
263
264 freeaddrinfo(result); /* No longer needed */
265
266 if (!rp) { /* No address succeeded */
267 log_socket_error("Failed to connect");
268 return ERROR_FAIL;
269 }
270
271 return fd;
272 }
273
274 static int remote_bitbang_init_unix(void)
275 {
276 if (!remote_bitbang_host) {
277 LOG_ERROR("host/socket not specified");
278 return ERROR_FAIL;
279 }
280
281 LOG_INFO("Connecting to unix socket %s", remote_bitbang_host);
282 int fd = socket(PF_UNIX, SOCK_STREAM, 0);
283 if (fd < 0) {
284 log_socket_error("socket");
285 return ERROR_FAIL;
286 }
287
288 struct sockaddr_un addr;
289 addr.sun_family = AF_UNIX;
290 strncpy(addr.sun_path, remote_bitbang_host, sizeof(addr.sun_path));
291 addr.sun_path[sizeof(addr.sun_path)-1] = '\0';
292
293 if (connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0) {
294 log_socket_error("connect");
295 return ERROR_FAIL;
296 }
297
298 return fd;
299 }
300
301 static int remote_bitbang_init(void)
302 {
303 bitbang_interface = &remote_bitbang_bitbang;
304
305 remote_bitbang_recv_buf_start = 0;
306 remote_bitbang_recv_buf_end = 0;
307
308 LOG_INFO("Initializing remote_bitbang driver");
309 if (!remote_bitbang_port)
310 remote_bitbang_fd = remote_bitbang_init_unix();
311 else
312 remote_bitbang_fd = remote_bitbang_init_tcp();
313
314 if (remote_bitbang_fd < 0)
315 return remote_bitbang_fd;
316
317 LOG_INFO("remote_bitbang driver initialized");
318 return ERROR_OK;
319 }
320
321 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_port_command)
322 {
323 if (CMD_ARGC == 1) {
324 uint16_t port;
325 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
326 free(remote_bitbang_port);
327 remote_bitbang_port = port == 0 ? NULL : strdup(CMD_ARGV[0]);
328 return ERROR_OK;
329 }
330 return ERROR_COMMAND_SYNTAX_ERROR;
331 }
332
333 COMMAND_HANDLER(remote_bitbang_handle_remote_bitbang_host_command)
334 {
335 if (CMD_ARGC == 1) {
336 free(remote_bitbang_host);
337 remote_bitbang_host = strdup(CMD_ARGV[0]);
338 return ERROR_OK;
339 }
340 return ERROR_COMMAND_SYNTAX_ERROR;
341 }
342
343 static const struct command_registration remote_bitbang_subcommand_handlers[] = {
344 {
345 .name = "port",
346 .handler = remote_bitbang_handle_remote_bitbang_port_command,
347 .mode = COMMAND_CONFIG,
348 .help = "Set the port to use to connect to the remote jtag.\n"
349 " if 0 or unset, use unix sockets to connect to the remote jtag.",
350 .usage = "port_number",
351 },
352 {
353 .name = "host",
354 .handler = remote_bitbang_handle_remote_bitbang_host_command,
355 .mode = COMMAND_CONFIG,
356 .help = "Set the host to use to connect to the remote jtag.\n"
357 " if port is 0 or unset, this is the name of the unix socket to use.",
358 .usage = "host_name",
359 },
360 COMMAND_REGISTRATION_DONE,
361 };
362
363 static const struct command_registration remote_bitbang_command_handlers[] = {
364 {
365 .name = "remote_bitbang",
366 .mode = COMMAND_ANY,
367 .help = "perform remote_bitbang management",
368 .chain = remote_bitbang_subcommand_handlers,
369 .usage = "",
370 },
371 COMMAND_REGISTRATION_DONE
372 };
373
374 static int remote_bitbang_execute_queue(void)
375 {
376 /* safety: the send buffer must be empty, no leftover characters from
377 * previous transactions */
378 assert(remote_bitbang_send_buf_used == 0);
379
380 /* process the JTAG command queue */
381 int ret = bitbang_execute_queue();
382 if (ret != ERROR_OK)
383 return ret;
384
385 /* flush not-yet-sent characters, if any */
386 return remote_bitbang_flush();
387 }
388
389 static struct jtag_interface remote_bitbang_interface = {
390 .execute_queue = &remote_bitbang_execute_queue,
391 };
392
393 struct adapter_driver remote_bitbang_adapter_driver = {
394 .name = "remote_bitbang",
395 .transports = jtag_only,
396 .commands = remote_bitbang_command_handlers,
397
398 .init = &remote_bitbang_init,
399 .quit = &remote_bitbang_quit,
400 .reset = &remote_bitbang_reset,
401
402 .jtag_ops = &remote_bitbang_interface,
403 };

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)