1 /***************************************************************************
2 * Copyright (C) 2012 by Creative Product Design, marc @ cpdesign.com.au *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
18 ***************************************************************************/
21 * This driver implements a bitbang jtag interface using gpio lines via
23 * The aim of this driver implementation is use system GPIOs but avoid the
24 * need for a additional kernel driver.
25 * (Note memory mapped IO is another option, however it doesn't mix well with
26 * the kernel gpiolib driver - which makes sense I guess.)
28 * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst
29 * must be also be specified. The required jtag gpios are specified via the
30 * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commang.
31 * The srst and trst gpios are set via the sysfsgpio_srst_num and
32 * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel
33 * convention of starting from 0.
35 * The gpios should not be in use by another entity, and must not be requested
36 * by a kernel driver without also being exported by it (otherwise they can't
37 * be exported by sysfs).
39 * The sysfs gpio interface can only manipulate one gpio at a time, so the
40 * bitbang write handler remembers the last state for tck, tms, tdi to avoid
42 * For speed the sysfs "value" entry is opened at init and held open.
43 * This results in considerable gains over open-write-close (45s vs 900s)
45 * Further work could address:
46 * -srst and trst open drain/ push pull
47 * -configurable active high/low for srst & trst
53 #include <jtag/interface.h>
57 * Helper func to determine if gpio number valid
59 * Assume here that there will be less than 1000 gpios on a system
61 static int is_gpio_valid(int gpio
)
63 return gpio
>= 0 && gpio
< 1000;
67 * Helper func to open, write to and close a file
68 * name and valstr must be null terminated.
70 * Returns negative on failure.
72 static int open_write_close(const char *name
, const char *valstr
)
75 int fd
= open(name
, O_WRONLY
);
79 ret
= write(fd
, valstr
, strlen(valstr
));
86 * Helper func to unexport gpio from sysfs
88 static void unexport_sysfs_gpio(int gpio
)
92 if (!is_gpio_valid(gpio
))
95 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
96 if (open_write_close("/sys/class/gpio/unexport", gpiostr
) < 0)
97 LOG_ERROR("Couldn't unexport gpio %d", gpio
);
103 * Exports and sets up direction for gpio.
104 * If the gpio is an output, it is initialized according to init_high,
105 * otherwise it is ignored.
107 * If the gpio is already exported we just show a warning and continue; if
108 * openocd happened to crash (or was killed by user) then the gpios will not
109 * have been cleaned up.
111 static int setup_sysfs_gpio(int gpio
, int is_output
, int init_high
)
117 if (!is_gpio_valid(gpio
))
120 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
121 ret
= open_write_close("/sys/class/gpio/export", gpiostr
);
123 if (errno
== EBUSY
) {
124 LOG_WARNING("gpio %d is already exported", gpio
);
126 LOG_ERROR("Couldn't export gpio %d", gpio
);
127 perror("sysfsgpio: ");
132 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", gpio
);
133 ret
= open_write_close(buf
, is_output
? (init_high
? "high" : "low") : "in");
135 LOG_ERROR("Couldn't set direction for gpio %d", gpio
);
136 perror("sysfsgpio: ");
137 unexport_sysfs_gpio(gpio
);
141 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/value", gpio
);
143 ret
= open(buf
, O_WRONLY
| O_NONBLOCK
| O_SYNC
);
145 ret
= open(buf
, O_RDONLY
| O_NONBLOCK
| O_SYNC
);
148 unexport_sysfs_gpio(gpio
);
154 * file descriptors for /sys/class/gpio/gpioXX/value
155 * Set up during init.
157 static int tck_fd
= -1;
158 static int tms_fd
= -1;
159 static int tdi_fd
= -1;
160 static int tdo_fd
= -1;
161 static int trst_fd
= -1;
162 static int srst_fd
= -1;
165 * Bitbang interface read of TDO
167 * The sysfs value will read back either '0' or '1'. The trick here is to call
168 * lseek to bypass buffering in the sysfs kernel driver.
170 static int sysfsgpio_read(void)
174 /* important to seek to signal sysfs of new read */
175 lseek(tdo_fd
, 0, SEEK_SET
);
176 int ret
= read(tdo_fd
, &buf
, sizeof(buf
));
179 LOG_WARNING("reading tdo failed");
183 return buf
[0] == '1';
187 * Bitbang interface write of TCK, TMS, TDI
189 * Seeing as this is the only function where the outputs are changed,
190 * we can cache the old value to avoid needlessly writing it.
192 static void sysfsgpio_write(int tck
, int tms
, int tdi
)
194 const char one
[] = "1";
195 const char zero
[] = "0";
201 static int first_time
;
202 size_t bytes_written
;
211 if (tdi
!= last_tdi
) {
212 bytes_written
= write(tdi_fd
, tdi
? &one
: &zero
, 1);
213 if (bytes_written
!= 1)
214 LOG_WARNING("writing tdi failed");
217 if (tms
!= last_tms
) {
218 bytes_written
= write(tms_fd
, tms
? &one
: &zero
, 1);
219 if (bytes_written
!= 1)
220 LOG_WARNING("writing tms failed");
224 if (tck
!= last_tck
) {
225 bytes_written
= write(tck_fd
, tck
? &one
: &zero
, 1);
226 if (bytes_written
!= 1)
227 LOG_WARNING("writing tck failed");
236 * Bitbang interface to manipulate reset lines SRST and TRST
238 * (1) assert or (0) deassert reset lines
240 static void sysfsgpio_reset(int trst
, int srst
)
242 const char one
[] = "1";
243 const char zero
[] = "0";
244 size_t bytes_written
;
246 /* assume active low */
248 bytes_written
= write(srst_fd
, srst
? &zero
: &one
, 1);
249 if (bytes_written
!= 1)
250 LOG_WARNING("writing srst failed");
253 /* assume active low */
255 bytes_written
= write(trst_fd
, trst
? &zero
: &one
, 1);
256 if (bytes_written
!= 1)
257 LOG_WARNING("writing trst failed");
261 /* gpio numbers for each gpio. Negative values are invalid */
262 static int tck_gpio
= -1;
263 static int tms_gpio
= -1;
264 static int tdi_gpio
= -1;
265 static int tdo_gpio
= -1;
266 static int trst_gpio
= -1;
267 static int srst_gpio
= -1;
269 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums
)
272 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
273 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
274 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
275 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
276 } else if (CMD_ARGC
!= 0) {
277 return ERROR_COMMAND_SYNTAX_ERROR
;
280 command_print(CMD_CTX
,
281 "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
282 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
287 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck
)
290 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
292 command_print(CMD_CTX
, "SysfsGPIO num: tck = %d", tck_gpio
);
296 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms
)
299 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
301 command_print(CMD_CTX
, "SysfsGPIO num: tms = %d", tms_gpio
);
305 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo
)
308 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
310 command_print(CMD_CTX
, "SysfsGPIO num: tdo = %d", tdo_gpio
);
314 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi
)
317 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
319 command_print(CMD_CTX
, "SysfsGPIO num: tdi = %d", tdi_gpio
);
323 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst
)
326 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
328 command_print(CMD_CTX
, "SysfsGPIO num: srst = %d", srst_gpio
);
332 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst
)
335 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
337 command_print(CMD_CTX
, "SysfsGPIO num: trst = %d", trst_gpio
);
341 static const struct command_registration sysfsgpio_command_handlers
[] = {
343 .name
= "sysfsgpio_jtag_nums",
344 .handler
= &sysfsgpio_handle_jtag_gpionums
,
345 .mode
= COMMAND_CONFIG
,
346 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
347 .usage
= "(tck tms tdi tdo)* ",
350 .name
= "sysfsgpio_tck_num",
351 .handler
= &sysfsgpio_handle_jtag_gpionum_tck
,
352 .mode
= COMMAND_CONFIG
,
353 .help
= "gpio number for tck.",
356 .name
= "sysfsgpio_tms_num",
357 .handler
= &sysfsgpio_handle_jtag_gpionum_tms
,
358 .mode
= COMMAND_CONFIG
,
359 .help
= "gpio number for tms.",
362 .name
= "sysfsgpio_tdo_num",
363 .handler
= &sysfsgpio_handle_jtag_gpionum_tdo
,
364 .mode
= COMMAND_CONFIG
,
365 .help
= "gpio number for tdo.",
368 .name
= "sysfsgpio_tdi_num",
369 .handler
= &sysfsgpio_handle_jtag_gpionum_tdi
,
370 .mode
= COMMAND_CONFIG
,
371 .help
= "gpio number for tdi.",
374 .name
= "sysfsgpio_srst_num",
375 .handler
= &sysfsgpio_handle_jtag_gpionum_srst
,
376 .mode
= COMMAND_CONFIG
,
377 .help
= "gpio number for srst.",
380 .name
= "sysfsgpio_trst_num",
381 .handler
= &sysfsgpio_handle_jtag_gpionum_trst
,
382 .mode
= COMMAND_CONFIG
,
383 .help
= "gpio number for trst.",
385 COMMAND_REGISTRATION_DONE
388 static int sysfsgpio_init(void);
389 static int sysfsgpio_quit(void);
391 struct jtag_interface sysfsgpio_interface
= {
393 .supported
= DEBUG_CAP_TMS_SEQ
,
394 .execute_queue
= bitbang_execute_queue
,
395 .transports
= jtag_only
,
396 .commands
= sysfsgpio_command_handlers
,
397 .init
= sysfsgpio_init
,
398 .quit
= sysfsgpio_quit
,
401 static struct bitbang_interface sysfsgpio_bitbang
= {
402 .read
= sysfsgpio_read
,
403 .write
= sysfsgpio_write
,
404 .reset
= sysfsgpio_reset
,
408 /* helper func to close and cleanup files only if they were valid/ used */
409 static void cleanup_fd(int fd
, int gpio
)
415 unexport_sysfs_gpio(gpio
);
419 static void cleanup_all_fds(void)
421 cleanup_fd(tck_fd
, tck_gpio
);
422 cleanup_fd(tms_fd
, tms_gpio
);
423 cleanup_fd(tdi_fd
, tdi_gpio
);
424 cleanup_fd(tdo_fd
, tdo_gpio
);
425 cleanup_fd(trst_fd
, trst_gpio
);
426 cleanup_fd(srst_fd
, srst_gpio
);
429 static int sysfsgpio_init(void)
431 bitbang_interface
= &sysfsgpio_bitbang
;
433 LOG_INFO("SysfsGPIO JTAG bitbang driver");
435 if (!(is_gpio_valid(tck_gpio
)
436 && is_gpio_valid(tms_gpio
)
437 && is_gpio_valid(tdi_gpio
)
438 && is_gpio_valid(tdo_gpio
))) {
439 if (!is_gpio_valid(tck_gpio
))
440 LOG_ERROR("gpio num for tck is invalid");
441 if (!is_gpio_valid(tms_gpio
))
442 LOG_ERROR("gpio num for tms is invalid");
443 if (!is_gpio_valid(tdo_gpio
))
444 LOG_ERROR("gpio num for tdo is invalid");
445 if (!is_gpio_valid(tdi_gpio
))
446 LOG_ERROR("gpio num for tdi is invalid");
448 LOG_ERROR("Require tck, tms, tdi and tdo gpios to all be specified");
449 return ERROR_JTAG_INIT_FAILED
;
452 if (!is_gpio_valid(trst_gpio
) && !is_gpio_valid(srst_gpio
)) {
453 LOG_ERROR("Require at least one of trst or srst gpios to be specified");
454 return ERROR_JTAG_INIT_FAILED
;
458 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
459 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
461 tck_fd
= setup_sysfs_gpio(tck_gpio
, 1, 0);
465 tms_fd
= setup_sysfs_gpio(tms_gpio
, 1, 1);
469 tdi_fd
= setup_sysfs_gpio(tdi_gpio
, 1, 0);
473 tdo_fd
= setup_sysfs_gpio(tdo_gpio
, 0, 0);
477 /* assume active low*/
479 trst_fd
= setup_sysfs_gpio(trst_gpio
, 1, 1);
484 /* assume active low*/
486 srst_fd
= setup_sysfs_gpio(srst_gpio
, 1, 1);
495 return ERROR_JTAG_INIT_FAILED
;
498 static int sysfsgpio_quit(void)
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)