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 <jtag/interface.h>
59 * Helper func to determine if gpio number valid
61 * Assume here that there will be less than 1000 gpios on a system
63 static int is_gpio_valid(int gpio
)
65 return gpio
>= 0 && gpio
< 1000;
69 * Helper func to open, write to and close a file
70 * name and valstr must be null terminated.
72 * Returns negative on failure.
74 static int open_write_close(const char *name
, const char *valstr
)
77 int fd
= open(name
, O_WRONLY
);
81 ret
= write(fd
, valstr
, strlen(valstr
));
88 * Helper func to unexport gpio from sysfs
90 static void unexport_sysfs_gpio(int gpio
)
94 if (!is_gpio_valid(gpio
))
97 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
98 if (open_write_close("/sys/class/gpio/unexport", gpiostr
) < 0)
99 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
)
119 if (!is_gpio_valid(gpio
))
122 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
123 ret
= open_write_close("/sys/class/gpio/export", gpiostr
);
125 if (errno
== EBUSY
) {
126 LOG_WARNING("gpio %d is already exported", gpio
);
128 LOG_ERROR("Couldn't export gpio %d", gpio
);
129 perror("sysfsgpio: ");
134 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", gpio
);
135 ret
= open_write_close(buf
, is_output
? (init_high
? "high" : "low") : "in");
137 LOG_ERROR("Couldn't set direction for gpio %d", gpio
);
138 perror("sysfsgpio: ");
139 unexport_sysfs_gpio(gpio
);
143 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/value", gpio
);
144 ret
= open(buf
, O_RDWR
| O_NONBLOCK
| O_SYNC
);
146 LOG_ERROR("Couldn't open value for gpio %d", gpio
);
147 perror("sysfsgpio: ");
148 unexport_sysfs_gpio(gpio
);
154 /* gpio numbers for each gpio. Negative values are invalid */
155 static int tck_gpio
= -1;
156 static int tms_gpio
= -1;
157 static int tdi_gpio
= -1;
158 static int tdo_gpio
= -1;
159 static int trst_gpio
= -1;
160 static int srst_gpio
= -1;
161 static int swclk_gpio
= -1;
162 static int swdio_gpio
= -1;
165 * file descriptors for /sys/class/gpio/gpioXX/value
166 * Set up during init.
168 static int tck_fd
= -1;
169 static int tms_fd
= -1;
170 static int tdi_fd
= -1;
171 static int tdo_fd
= -1;
172 static int trst_fd
= -1;
173 static int srst_fd
= -1;
174 static int swclk_fd
= -1;
175 static int swdio_fd
= -1;
177 static int last_swclk
;
178 static int last_swdio
;
179 static bool last_stored
;
180 static bool swdio_input
;
182 static void sysfsgpio_swdio_drive(bool is_output
)
187 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", swdio_gpio
);
188 ret
= open_write_close(buf
, is_output
? "high" : "in");
190 LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio
);
191 perror("sysfsgpio: ");
195 swdio_input
= !is_output
;
198 static int sysfsgpio_swdio_read(void)
202 /* important to seek to signal sysfs of new read */
203 lseek(swdio_fd
, 0, SEEK_SET
);
204 int ret
= read(swdio_fd
, &buf
, sizeof(buf
));
207 LOG_WARNING("reading swdio failed");
211 return buf
[0] != '0';
214 static void sysfsgpio_swdio_write(int swclk
, int swdio
)
216 const char one
[] = "1";
217 const char zero
[] = "0";
219 size_t bytes_written
;
222 if (!last_stored
|| (swdio
!= last_swdio
)) {
223 bytes_written
= write(swdio_fd
, swdio
? &one
: &zero
, 1);
224 if (bytes_written
!= 1)
225 LOG_WARNING("writing swdio failed");
229 /* write swclk last */
230 if (!last_stored
|| (swclk
!= last_swclk
)) {
231 bytes_written
= write(swclk_fd
, swclk
? &one
: &zero
, 1);
232 if (bytes_written
!= 1)
233 LOG_WARNING("writing swclk failed");
242 * Bitbang interface read of TDO
244 * The sysfs value will read back either '0' or '1'. The trick here is to call
245 * lseek to bypass buffering in the sysfs kernel driver.
247 static int sysfsgpio_read(void)
251 /* important to seek to signal sysfs of new read */
252 lseek(tdo_fd
, 0, SEEK_SET
);
253 int ret
= read(tdo_fd
, &buf
, sizeof(buf
));
256 LOG_WARNING("reading tdo failed");
260 return buf
[0] != '0';
264 * Bitbang interface write of TCK, TMS, TDI
266 * Seeing as this is the only function where the outputs are changed,
267 * we can cache the old value to avoid needlessly writing it.
269 static void sysfsgpio_write(int tck
, int tms
, int tdi
)
272 sysfsgpio_swdio_write(tck
, tdi
);
276 const char one
[] = "1";
277 const char zero
[] = "0";
283 static int first_time
;
284 size_t bytes_written
;
293 if (tdi
!= last_tdi
) {
294 bytes_written
= write(tdi_fd
, tdi
? &one
: &zero
, 1);
295 if (bytes_written
!= 1)
296 LOG_WARNING("writing tdi failed");
299 if (tms
!= last_tms
) {
300 bytes_written
= write(tms_fd
, tms
? &one
: &zero
, 1);
301 if (bytes_written
!= 1)
302 LOG_WARNING("writing tms failed");
306 if (tck
!= last_tck
) {
307 bytes_written
= write(tck_fd
, tck
? &one
: &zero
, 1);
308 if (bytes_written
!= 1)
309 LOG_WARNING("writing tck failed");
318 * Bitbang interface to manipulate reset lines SRST and TRST
320 * (1) assert or (0) deassert reset lines
322 static void sysfsgpio_reset(int trst
, int srst
)
324 LOG_DEBUG("sysfsgpio_reset");
325 const char one
[] = "1";
326 const char zero
[] = "0";
327 size_t bytes_written
;
329 /* assume active low */
331 bytes_written
= write(srst_fd
, srst
? &zero
: &one
, 1);
332 if (bytes_written
!= 1)
333 LOG_WARNING("writing srst failed");
336 /* assume active low */
338 bytes_written
= write(trst_fd
, trst
? &zero
: &one
, 1);
339 if (bytes_written
!= 1)
340 LOG_WARNING("writing trst failed");
344 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums
)
347 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
348 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
349 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
350 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
351 } else if (CMD_ARGC
!= 0) {
352 return ERROR_COMMAND_SYNTAX_ERROR
;
355 command_print(CMD_CTX
,
356 "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
357 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
362 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck
)
365 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
367 command_print(CMD_CTX
, "SysfsGPIO num: tck = %d", tck_gpio
);
371 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms
)
374 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
376 command_print(CMD_CTX
, "SysfsGPIO num: tms = %d", tms_gpio
);
380 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo
)
383 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
385 command_print(CMD_CTX
, "SysfsGPIO num: tdo = %d", tdo_gpio
);
389 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi
)
392 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
394 command_print(CMD_CTX
, "SysfsGPIO num: tdi = %d", tdi_gpio
);
398 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst
)
401 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
403 command_print(CMD_CTX
, "SysfsGPIO num: srst = %d", srst_gpio
);
407 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst
)
410 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
412 command_print(CMD_CTX
, "SysfsGPIO num: trst = %d", trst_gpio
);
416 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums
)
419 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
420 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
421 } else if (CMD_ARGC
!= 0) {
422 return ERROR_COMMAND_SYNTAX_ERROR
;
425 command_print(CMD_CTX
,
426 "SysfsGPIO nums: swclk = %d, swdio = %d",
427 swclk_gpio
, swdio_gpio
);
432 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk
)
435 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
437 command_print(CMD_CTX
, "SysfsGPIO num: swclk = %d", swclk_gpio
);
441 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio
)
444 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
446 command_print(CMD_CTX
, "SysfsGPIO num: swdio = %d", swdio_gpio
);
450 static const struct command_registration sysfsgpio_command_handlers
[] = {
452 .name
= "sysfsgpio_jtag_nums",
453 .handler
= &sysfsgpio_handle_jtag_gpionums
,
454 .mode
= COMMAND_CONFIG
,
455 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
456 .usage
= "(tck tms tdi tdo)* ",
459 .name
= "sysfsgpio_tck_num",
460 .handler
= &sysfsgpio_handle_jtag_gpionum_tck
,
461 .mode
= COMMAND_CONFIG
,
462 .help
= "gpio number for tck.",
465 .name
= "sysfsgpio_tms_num",
466 .handler
= &sysfsgpio_handle_jtag_gpionum_tms
,
467 .mode
= COMMAND_CONFIG
,
468 .help
= "gpio number for tms.",
471 .name
= "sysfsgpio_tdo_num",
472 .handler
= &sysfsgpio_handle_jtag_gpionum_tdo
,
473 .mode
= COMMAND_CONFIG
,
474 .help
= "gpio number for tdo.",
477 .name
= "sysfsgpio_tdi_num",
478 .handler
= &sysfsgpio_handle_jtag_gpionum_tdi
,
479 .mode
= COMMAND_CONFIG
,
480 .help
= "gpio number for tdi.",
483 .name
= "sysfsgpio_srst_num",
484 .handler
= &sysfsgpio_handle_jtag_gpionum_srst
,
485 .mode
= COMMAND_CONFIG
,
486 .help
= "gpio number for srst.",
489 .name
= "sysfsgpio_trst_num",
490 .handler
= &sysfsgpio_handle_jtag_gpionum_trst
,
491 .mode
= COMMAND_CONFIG
,
492 .help
= "gpio number for trst.",
495 .name
= "sysfsgpio_swd_nums",
496 .handler
= &sysfsgpio_handle_swd_gpionums
,
497 .mode
= COMMAND_CONFIG
,
498 .help
= "gpio numbers for swclk, swdio. (in that order)",
499 .usage
= "(swclk swdio)* ",
502 .name
= "sysfsgpio_swclk_num",
503 .handler
= &sysfsgpio_handle_swd_gpionum_swclk
,
504 .mode
= COMMAND_CONFIG
,
505 .help
= "gpio number for swclk.",
508 .name
= "sysfsgpio_swdio_num",
509 .handler
= &sysfsgpio_handle_swd_gpionum_swdio
,
510 .mode
= COMMAND_CONFIG
,
511 .help
= "gpio number for swdio.",
513 COMMAND_REGISTRATION_DONE
516 static int sysfsgpio_init(void);
517 static int sysfsgpio_quit(void);
519 static const char * const sysfsgpio_transports
[] = { "jtag", "swd", NULL
};
521 struct jtag_interface sysfsgpio_interface
= {
523 .supported
= DEBUG_CAP_TMS_SEQ
,
524 .execute_queue
= bitbang_execute_queue
,
525 .transports
= sysfsgpio_transports
,
527 .commands
= sysfsgpio_command_handlers
,
528 .init
= sysfsgpio_init
,
529 .quit
= sysfsgpio_quit
,
532 static struct bitbang_interface sysfsgpio_bitbang
= {
533 .read
= sysfsgpio_read
,
534 .write
= sysfsgpio_write
,
535 .reset
= sysfsgpio_reset
,
536 .swdio_read
= sysfsgpio_swdio_read
,
537 .swdio_drive
= sysfsgpio_swdio_drive
,
541 /* helper func to close and cleanup files only if they were valid/ used */
542 static void cleanup_fd(int fd
, int gpio
)
548 unexport_sysfs_gpio(gpio
);
552 static void cleanup_all_fds(void)
554 cleanup_fd(tck_fd
, tck_gpio
);
555 cleanup_fd(tms_fd
, tms_gpio
);
556 cleanup_fd(tdi_fd
, tdi_gpio
);
557 cleanup_fd(tdo_fd
, tdo_gpio
);
558 cleanup_fd(trst_fd
, trst_gpio
);
559 cleanup_fd(srst_fd
, srst_gpio
);
562 static bool sysfsgpio_jtag_mode_possible(void)
564 if (!is_gpio_valid(tck_gpio
))
566 if (!is_gpio_valid(tms_gpio
))
568 if (!is_gpio_valid(tdi_gpio
))
570 if (!is_gpio_valid(tdo_gpio
))
575 static bool sysfsgpio_swd_mode_possible(void)
577 if (!is_gpio_valid(swclk_gpio
))
579 if (!is_gpio_valid(swdio_gpio
))
584 static int sysfsgpio_init(void)
586 bitbang_interface
= &sysfsgpio_bitbang
;
588 LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver");
590 if (sysfsgpio_jtag_mode_possible()) {
591 if (sysfsgpio_swd_mode_possible())
592 LOG_INFO("JTAG and SWD modes enabled");
594 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
595 } else if (sysfsgpio_swd_mode_possible()) {
596 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
598 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
599 return ERROR_JTAG_INIT_FAILED
;
604 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
605 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
606 * For SWD, SWCLK and SWDIO are configures as output high.
609 tck_fd
= setup_sysfs_gpio(tck_gpio
, 1, 0);
615 tms_fd
= setup_sysfs_gpio(tms_gpio
, 1, 1);
621 tdi_fd
= setup_sysfs_gpio(tdi_gpio
, 1, 0);
627 tdo_fd
= setup_sysfs_gpio(tdo_gpio
, 0, 0);
632 /* assume active low*/
633 if (trst_gpio
>= 0) {
634 trst_fd
= setup_sysfs_gpio(trst_gpio
, 1, 1);
639 /* assume active low*/
640 if (srst_gpio
>= 0) {
641 srst_fd
= setup_sysfs_gpio(srst_gpio
, 1, 1);
646 if (swclk_gpio
>= 0) {
647 swclk_fd
= setup_sysfs_gpio(swclk_gpio
, 1, 0);
652 if (swdio_gpio
>= 0) {
653 swdio_fd
= setup_sysfs_gpio(swdio_gpio
, 1, 0);
658 if (sysfsgpio_swd_mode_possible()) {
660 bitbang_swd_switch_seq(JTAG_TO_SWD
);
662 bitbang_swd_switch_seq(SWD_TO_JTAG
);
669 return ERROR_JTAG_INIT_FAILED
;
672 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)