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, see <http://www.gnu.org/licenses/>. *
16 ***************************************************************************/
18 /* 2014-12: Addition of the SWD protocol support is based on the initial work
19 * on bcm2835gpio.c by Paul Fertser and modifications by Jean-Christian de Rivaz. */
23 * This driver implements a bitbang jtag interface using gpio lines via
25 * The aim of this driver implementation is use system GPIOs but avoid the
26 * need for a additional kernel driver.
27 * (Note memory mapped IO is another option, however it doesn't mix well with
28 * the kernel gpiolib driver - which makes sense I guess.)
30 * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst
31 * must be also be specified. The required jtag gpios are specified via the
32 * sysfsgpio_jtag_nums command or the relevant sysfsgpio_XXX_num commang.
33 * The srst and trst gpios are set via the sysfsgpio_srst_num and
34 * sysfsgpio_trst_num respectively. GPIO numbering follows the kernel
35 * convention of starting from 0.
37 * The gpios should not be in use by another entity, and must not be requested
38 * by a kernel driver without also being exported by it (otherwise they can't
39 * be exported by sysfs).
41 * The sysfs gpio interface can only manipulate one gpio at a time, so the
42 * bitbang write handler remembers the last state for tck, tms, tdi to avoid
44 * For speed the sysfs "value" entry is opened at init and held open.
45 * This results in considerable gains over open-write-close (45s vs 900s)
47 * Further work could address:
48 * -srst and trst open drain/ push pull
49 * -configurable active high/low for srst & trst
55 #include <helper/time_support.h>
56 #include <jtag/interface.h>
57 #include <transport/transport.h>
61 * Helper func to determine if gpio number valid
63 * Assume here that there will be less than 10000 gpios on a system
65 static bool is_gpio_valid(int gpio
)
67 return gpio
>= 0 && gpio
< 10000;
71 * Helper func to open, write to and close a file
72 * name and valstr must be null terminated.
74 * Returns negative on failure.
76 static int open_write_close(const char *name
, const char *valstr
)
79 int fd
= open(name
, O_WRONLY
);
83 ret
= write(fd
, valstr
, strlen(valstr
));
90 * Helper func to unexport gpio from sysfs
92 static void unexport_sysfs_gpio(int gpio
)
96 if (!is_gpio_valid(gpio
))
99 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
100 if (open_write_close("/sys/class/gpio/unexport", gpiostr
) < 0)
101 LOG_ERROR("Couldn't unexport gpio %d", gpio
);
105 * Exports and sets up direction for gpio.
106 * If the gpio is an output, it is initialized according to init_high,
107 * otherwise it is ignored.
109 * If the gpio is already exported we just show a warning and continue; if
110 * openocd happened to crash (or was killed by user) then the gpios will not
111 * have been cleaned up.
113 static int setup_sysfs_gpio(int gpio
, int is_output
, int init_high
)
115 struct timeval timeout
, now
;
120 if (!is_gpio_valid(gpio
))
123 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
124 ret
= open_write_close("/sys/class/gpio/export", gpiostr
);
126 if (errno
== EBUSY
) {
127 LOG_WARNING("gpio %d is already exported", gpio
);
129 LOG_ERROR("Couldn't export gpio %d", gpio
);
130 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
135 gettimeofday(&timeout
, NULL
);
136 timeval_add_time(&timeout
, 0, 500000);
138 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", gpio
);
140 ret
= open_write_close(buf
, is_output
? (init_high
? "high" : "low") : "in");
141 if (ret
>= 0 || errno
!= EACCES
)
143 gettimeofday(&now
, NULL
);
144 if (timeval_compare(&now
, &timeout
) >= 0)
149 LOG_ERROR("Couldn't set direction for gpio %d", gpio
);
150 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
151 unexport_sysfs_gpio(gpio
);
155 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/value", gpio
);
157 ret
= open(buf
, O_RDWR
| O_NONBLOCK
| O_SYNC
);
158 if (ret
>= 0 || errno
!= EACCES
)
160 gettimeofday(&now
, NULL
);
161 if (timeval_compare(&now
, &timeout
) >= 0)
166 LOG_ERROR("Couldn't open value for gpio %d", gpio
);
167 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
168 unexport_sysfs_gpio(gpio
);
174 /* gpio numbers for each gpio. Negative values are invalid */
175 static int tck_gpio
= -1;
176 static int tms_gpio
= -1;
177 static int tdi_gpio
= -1;
178 static int tdo_gpio
= -1;
179 static int trst_gpio
= -1;
180 static int srst_gpio
= -1;
181 static int swclk_gpio
= -1;
182 static int swdio_gpio
= -1;
185 * file descriptors for /sys/class/gpio/gpioXX/value
186 * Set up during init.
188 static int tck_fd
= -1;
189 static int tms_fd
= -1;
190 static int tdi_fd
= -1;
191 static int tdo_fd
= -1;
192 static int trst_fd
= -1;
193 static int srst_fd
= -1;
194 static int swclk_fd
= -1;
195 static int swdio_fd
= -1;
197 static int last_swclk
;
198 static int last_swdio
;
199 static bool last_stored
;
200 static bool swdio_input
;
202 static void sysfsgpio_swdio_drive(bool is_output
)
207 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", swdio_gpio
);
208 ret
= open_write_close(buf
, is_output
? "high" : "in");
210 LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio
);
211 LOG_ERROR("sysfsgpio: %s", strerror(errno
));
215 swdio_input
= !is_output
;
218 static int sysfsgpio_swdio_read(void)
222 /* important to seek to signal sysfs of new read */
223 lseek(swdio_fd
, 0, SEEK_SET
);
224 int ret
= read(swdio_fd
, &buf
, sizeof(buf
));
227 LOG_WARNING("reading swdio failed");
231 return buf
[0] != '0';
234 static int sysfsgpio_swd_write(int swclk
, int swdio
)
236 const char one
[] = "1";
237 const char zero
[] = "0";
239 size_t bytes_written
;
242 if (!last_stored
|| (swdio
!= last_swdio
)) {
243 bytes_written
= write(swdio_fd
, swdio
? &one
: &zero
, 1);
244 if (bytes_written
!= 1)
245 LOG_WARNING("writing swdio failed");
249 /* write swclk last */
250 if (!last_stored
|| (swclk
!= last_swclk
)) {
251 bytes_written
= write(swclk_fd
, swclk
? &one
: &zero
, 1);
252 if (bytes_written
!= 1)
253 LOG_WARNING("writing swclk failed");
264 * Bitbang interface read of TDO
266 * The sysfs value will read back either '0' or '1'. The trick here is to call
267 * lseek to bypass buffering in the sysfs kernel driver.
269 static bb_value_t
sysfsgpio_read(void)
273 /* important to seek to signal sysfs of new read */
274 lseek(tdo_fd
, 0, SEEK_SET
);
275 int ret
= read(tdo_fd
, &buf
, sizeof(buf
));
278 LOG_WARNING("reading tdo failed");
282 return buf
[0] == '0' ? BB_LOW
: BB_HIGH
;
286 * Bitbang interface write of TCK, TMS, TDI
288 * Seeing as this is the only function where the outputs are changed,
289 * we can cache the old value to avoid needlessly writing it.
291 static int sysfsgpio_write(int tck
, int tms
, int tdi
)
293 const char one
[] = "1";
294 const char zero
[] = "0";
300 static int first_time
;
301 size_t bytes_written
;
310 if (tdi
!= last_tdi
) {
311 bytes_written
= write(tdi_fd
, tdi
? &one
: &zero
, 1);
312 if (bytes_written
!= 1)
313 LOG_WARNING("writing tdi failed");
316 if (tms
!= last_tms
) {
317 bytes_written
= write(tms_fd
, tms
? &one
: &zero
, 1);
318 if (bytes_written
!= 1)
319 LOG_WARNING("writing tms failed");
323 if (tck
!= last_tck
) {
324 bytes_written
= write(tck_fd
, tck
? &one
: &zero
, 1);
325 if (bytes_written
!= 1)
326 LOG_WARNING("writing tck failed");
337 * Bitbang interface to manipulate reset lines SRST and TRST
339 * (1) assert or (0) deassert reset lines
341 static int sysfsgpio_reset(int trst
, int srst
)
343 LOG_DEBUG("sysfsgpio_reset");
344 const char one
[] = "1";
345 const char zero
[] = "0";
346 size_t bytes_written
;
348 /* assume active low */
350 bytes_written
= write(srst_fd
, srst
? &zero
: &one
, 1);
351 if (bytes_written
!= 1)
352 LOG_WARNING("writing srst failed");
355 /* assume active low */
357 bytes_written
= write(trst_fd
, trst
? &zero
: &one
, 1);
358 if (bytes_written
!= 1)
359 LOG_WARNING("writing trst failed");
365 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums
)
368 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
369 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
370 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
371 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
372 } else if (CMD_ARGC
!= 0) {
373 return ERROR_COMMAND_SYNTAX_ERROR
;
377 "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
378 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
383 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck
)
386 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
388 command_print(CMD
, "SysfsGPIO num: tck = %d", tck_gpio
);
392 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms
)
395 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
397 command_print(CMD
, "SysfsGPIO num: tms = %d", tms_gpio
);
401 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo
)
404 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
406 command_print(CMD
, "SysfsGPIO num: tdo = %d", tdo_gpio
);
410 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi
)
413 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
415 command_print(CMD
, "SysfsGPIO num: tdi = %d", tdi_gpio
);
419 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst
)
422 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
424 command_print(CMD
, "SysfsGPIO num: srst = %d", srst_gpio
);
428 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst
)
431 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
433 command_print(CMD
, "SysfsGPIO num: trst = %d", trst_gpio
);
437 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums
)
440 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
441 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
442 } else if (CMD_ARGC
!= 0) {
443 return ERROR_COMMAND_SYNTAX_ERROR
;
447 "SysfsGPIO nums: swclk = %d, swdio = %d",
448 swclk_gpio
, swdio_gpio
);
453 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk
)
456 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
458 command_print(CMD
, "SysfsGPIO num: swclk = %d", swclk_gpio
);
462 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio
)
465 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
467 command_print(CMD
, "SysfsGPIO num: swdio = %d", swdio_gpio
);
471 static const struct command_registration sysfsgpio_command_handlers
[] = {
473 .name
= "sysfsgpio_jtag_nums",
474 .handler
= &sysfsgpio_handle_jtag_gpionums
,
475 .mode
= COMMAND_CONFIG
,
476 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
477 .usage
= "[tck tms tdi tdo]",
480 .name
= "sysfsgpio_tck_num",
481 .handler
= &sysfsgpio_handle_jtag_gpionum_tck
,
482 .mode
= COMMAND_CONFIG
,
483 .help
= "gpio number for tck.",
487 .name
= "sysfsgpio_tms_num",
488 .handler
= &sysfsgpio_handle_jtag_gpionum_tms
,
489 .mode
= COMMAND_CONFIG
,
490 .help
= "gpio number for tms.",
494 .name
= "sysfsgpio_tdo_num",
495 .handler
= &sysfsgpio_handle_jtag_gpionum_tdo
,
496 .mode
= COMMAND_CONFIG
,
497 .help
= "gpio number for tdo.",
501 .name
= "sysfsgpio_tdi_num",
502 .handler
= &sysfsgpio_handle_jtag_gpionum_tdi
,
503 .mode
= COMMAND_CONFIG
,
504 .help
= "gpio number for tdi.",
508 .name
= "sysfsgpio_srst_num",
509 .handler
= &sysfsgpio_handle_jtag_gpionum_srst
,
510 .mode
= COMMAND_CONFIG
,
511 .help
= "gpio number for srst.",
515 .name
= "sysfsgpio_trst_num",
516 .handler
= &sysfsgpio_handle_jtag_gpionum_trst
,
517 .mode
= COMMAND_CONFIG
,
518 .help
= "gpio number for trst.",
522 .name
= "sysfsgpio_swd_nums",
523 .handler
= &sysfsgpio_handle_swd_gpionums
,
524 .mode
= COMMAND_CONFIG
,
525 .help
= "gpio numbers for swclk, swdio. (in that order)",
526 .usage
= "[swclk swdio]",
529 .name
= "sysfsgpio_swclk_num",
530 .handler
= &sysfsgpio_handle_swd_gpionum_swclk
,
531 .mode
= COMMAND_CONFIG
,
532 .help
= "gpio number for swclk.",
536 .name
= "sysfsgpio_swdio_num",
537 .handler
= &sysfsgpio_handle_swd_gpionum_swdio
,
538 .mode
= COMMAND_CONFIG
,
539 .help
= "gpio number for swdio.",
542 COMMAND_REGISTRATION_DONE
545 static int sysfsgpio_init(void);
546 static int sysfsgpio_quit(void);
548 static const char * const sysfsgpio_transports
[] = { "jtag", "swd", NULL
};
550 static struct jtag_interface sysfsgpio_interface
= {
551 .supported
= DEBUG_CAP_TMS_SEQ
,
552 .execute_queue
= bitbang_execute_queue
,
555 struct adapter_driver sysfsgpio_adapter_driver
= {
557 .transports
= sysfsgpio_transports
,
558 .commands
= sysfsgpio_command_handlers
,
560 .init
= sysfsgpio_init
,
561 .quit
= sysfsgpio_quit
,
562 .reset
= sysfsgpio_reset
,
564 .jtag_ops
= &sysfsgpio_interface
,
565 .swd_ops
= &bitbang_swd
,
568 static struct bitbang_interface sysfsgpio_bitbang
= {
569 .read
= sysfsgpio_read
,
570 .write
= sysfsgpio_write
,
571 .swdio_read
= sysfsgpio_swdio_read
,
572 .swdio_drive
= sysfsgpio_swdio_drive
,
573 .swd_write
= sysfsgpio_swd_write
,
577 /* helper func to close and cleanup files only if they were valid/ used */
578 static void cleanup_fd(int fd
, int gpio
)
584 unexport_sysfs_gpio(gpio
);
588 static void cleanup_all_fds(void)
590 if (transport_is_jtag()) {
591 cleanup_fd(tck_fd
, tck_gpio
);
592 cleanup_fd(tms_fd
, tms_gpio
);
593 cleanup_fd(tdi_fd
, tdi_gpio
);
594 cleanup_fd(tdo_fd
, tdo_gpio
);
595 cleanup_fd(trst_fd
, trst_gpio
);
597 if (transport_is_swd()) {
598 cleanup_fd(swclk_fd
, swclk_gpio
);
599 cleanup_fd(swdio_fd
, swdio_gpio
);
601 cleanup_fd(srst_fd
, srst_gpio
);
604 static bool sysfsgpio_jtag_mode_possible(void)
606 if (!is_gpio_valid(tck_gpio
))
608 if (!is_gpio_valid(tms_gpio
))
610 if (!is_gpio_valid(tdi_gpio
))
612 if (!is_gpio_valid(tdo_gpio
))
617 static bool sysfsgpio_swd_mode_possible(void)
619 if (!is_gpio_valid(swclk_gpio
))
621 if (!is_gpio_valid(swdio_gpio
))
626 static int sysfsgpio_init(void)
628 bitbang_interface
= &sysfsgpio_bitbang
;
630 LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver");
633 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
634 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
635 * For SWD, SWCLK and SWDIO are configures as output high.
638 if (transport_is_jtag()) {
639 if (!sysfsgpio_jtag_mode_possible()) {
640 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode");
641 return ERROR_JTAG_INIT_FAILED
;
644 tck_fd
= setup_sysfs_gpio(tck_gpio
, 1, 0);
648 tms_fd
= setup_sysfs_gpio(tms_gpio
, 1, 1);
652 tdi_fd
= setup_sysfs_gpio(tdi_gpio
, 1, 0);
656 tdo_fd
= setup_sysfs_gpio(tdo_gpio
, 0, 0);
660 /* assume active low*/
661 if (trst_gpio
>= 0) {
662 trst_fd
= setup_sysfs_gpio(trst_gpio
, 1, 1);
668 if (transport_is_swd()) {
669 if (!sysfsgpio_swd_mode_possible()) {
670 LOG_ERROR("Require swclk and swdio gpio for SWD mode");
671 return ERROR_JTAG_INIT_FAILED
;
674 swclk_fd
= setup_sysfs_gpio(swclk_gpio
, 1, 0);
678 swdio_fd
= setup_sysfs_gpio(swdio_gpio
, 1, 0);
683 /* assume active low*/
684 if (srst_gpio
>= 0) {
685 srst_fd
= setup_sysfs_gpio(srst_gpio
, 1, 1);
694 return ERROR_JTAG_INIT_FAILED
;
697 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)