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>
60 * Helper func to determine if gpio number valid
62 * Assume here that there will be less than 10000 gpios on a system
64 static bool is_gpio_valid(int gpio
)
66 return gpio
>= 0 && gpio
< 10000;
70 * Helper func to open, write to and close a file
71 * name and valstr must be null terminated.
73 * Returns negative on failure.
75 static int open_write_close(const char *name
, const char *valstr
)
78 int fd
= open(name
, O_WRONLY
);
82 ret
= write(fd
, valstr
, strlen(valstr
));
89 * Helper func to unexport gpio from sysfs
91 static void unexport_sysfs_gpio(int gpio
)
95 if (!is_gpio_valid(gpio
))
98 snprintf(gpiostr
, sizeof(gpiostr
), "%d", gpio
);
99 if (open_write_close("/sys/class/gpio/unexport", gpiostr
) < 0)
100 LOG_ERROR("Couldn't unexport gpio %d", gpio
);
104 * Exports and sets up direction for gpio.
105 * If the gpio is an output, it is initialized according to init_high,
106 * otherwise it is ignored.
108 * If the gpio is already exported we just show a warning and continue; if
109 * openocd happened to crash (or was killed by user) then the gpios will not
110 * have been cleaned up.
112 static int setup_sysfs_gpio(int gpio
, int is_output
, int init_high
)
114 struct timeval timeout
, now
;
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 gettimeofday(&timeout
, NULL
);
135 timeval_add_time(&timeout
, 0, 500000);
137 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", gpio
);
139 ret
= open_write_close(buf
, is_output
? (init_high
? "high" : "low") : "in");
140 if (ret
>= 0 || errno
!= EACCES
)
142 gettimeofday(&now
, NULL
);
143 if (timeval_compare(&now
, &timeout
) >= 0)
148 LOG_ERROR("Couldn't set direction for gpio %d", gpio
);
149 perror("sysfsgpio: ");
150 unexport_sysfs_gpio(gpio
);
154 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/value", gpio
);
156 ret
= open(buf
, O_RDWR
| O_NONBLOCK
| O_SYNC
);
157 if (ret
>= 0 || errno
!= EACCES
)
159 gettimeofday(&now
, NULL
);
160 if (timeval_compare(&now
, &timeout
) >= 0)
165 LOG_ERROR("Couldn't open value for gpio %d", gpio
);
166 perror("sysfsgpio: ");
167 unexport_sysfs_gpio(gpio
);
173 /* gpio numbers for each gpio. Negative values are invalid */
174 static int tck_gpio
= -1;
175 static int tms_gpio
= -1;
176 static int tdi_gpio
= -1;
177 static int tdo_gpio
= -1;
178 static int trst_gpio
= -1;
179 static int srst_gpio
= -1;
180 static int swclk_gpio
= -1;
181 static int swdio_gpio
= -1;
184 * file descriptors for /sys/class/gpio/gpioXX/value
185 * Set up during init.
187 static int tck_fd
= -1;
188 static int tms_fd
= -1;
189 static int tdi_fd
= -1;
190 static int tdo_fd
= -1;
191 static int trst_fd
= -1;
192 static int srst_fd
= -1;
193 static int swclk_fd
= -1;
194 static int swdio_fd
= -1;
196 static int last_swclk
;
197 static int last_swdio
;
198 static bool last_stored
;
199 static bool swdio_input
;
201 static void sysfsgpio_swdio_drive(bool is_output
)
206 snprintf(buf
, sizeof(buf
), "/sys/class/gpio/gpio%d/direction", swdio_gpio
);
207 ret
= open_write_close(buf
, is_output
? "high" : "in");
209 LOG_ERROR("Couldn't set direction for gpio %d", swdio_gpio
);
210 perror("sysfsgpio: ");
214 swdio_input
= !is_output
;
217 static int sysfsgpio_swdio_read(void)
221 /* important to seek to signal sysfs of new read */
222 lseek(swdio_fd
, 0, SEEK_SET
);
223 int ret
= read(swdio_fd
, &buf
, sizeof(buf
));
226 LOG_WARNING("reading swdio failed");
230 return buf
[0] != '0';
233 static void sysfsgpio_swdio_write(int swclk
, int swdio
)
235 const char one
[] = "1";
236 const char zero
[] = "0";
238 size_t bytes_written
;
241 if (!last_stored
|| (swdio
!= last_swdio
)) {
242 bytes_written
= write(swdio_fd
, swdio
? &one
: &zero
, 1);
243 if (bytes_written
!= 1)
244 LOG_WARNING("writing swdio failed");
248 /* write swclk last */
249 if (!last_stored
|| (swclk
!= last_swclk
)) {
250 bytes_written
= write(swclk_fd
, swclk
? &one
: &zero
, 1);
251 if (bytes_written
!= 1)
252 LOG_WARNING("writing swclk failed");
261 * Bitbang interface read of TDO
263 * The sysfs value will read back either '0' or '1'. The trick here is to call
264 * lseek to bypass buffering in the sysfs kernel driver.
266 static bb_value_t
sysfsgpio_read(void)
270 /* important to seek to signal sysfs of new read */
271 lseek(tdo_fd
, 0, SEEK_SET
);
272 int ret
= read(tdo_fd
, &buf
, sizeof(buf
));
275 LOG_WARNING("reading tdo failed");
279 return buf
[0] == '0' ? BB_LOW
: BB_HIGH
;
283 * Bitbang interface write of TCK, TMS, TDI
285 * Seeing as this is the only function where the outputs are changed,
286 * we can cache the old value to avoid needlessly writing it.
288 static int sysfsgpio_write(int tck
, int tms
, int tdi
)
291 sysfsgpio_swdio_write(tck
, tdi
);
295 const char one
[] = "1";
296 const char zero
[] = "0";
302 static int first_time
;
303 size_t bytes_written
;
312 if (tdi
!= last_tdi
) {
313 bytes_written
= write(tdi_fd
, tdi
? &one
: &zero
, 1);
314 if (bytes_written
!= 1)
315 LOG_WARNING("writing tdi failed");
318 if (tms
!= last_tms
) {
319 bytes_written
= write(tms_fd
, tms
? &one
: &zero
, 1);
320 if (bytes_written
!= 1)
321 LOG_WARNING("writing tms failed");
325 if (tck
!= last_tck
) {
326 bytes_written
= write(tck_fd
, tck
? &one
: &zero
, 1);
327 if (bytes_written
!= 1)
328 LOG_WARNING("writing tck failed");
339 * Bitbang interface to manipulate reset lines SRST and TRST
341 * (1) assert or (0) deassert reset lines
343 static int sysfsgpio_reset(int trst
, int srst
)
345 LOG_DEBUG("sysfsgpio_reset");
346 const char one
[] = "1";
347 const char zero
[] = "0";
348 size_t bytes_written
;
350 /* assume active low */
352 bytes_written
= write(srst_fd
, srst
? &zero
: &one
, 1);
353 if (bytes_written
!= 1)
354 LOG_WARNING("writing srst failed");
357 /* assume active low */
359 bytes_written
= write(trst_fd
, trst
? &zero
: &one
, 1);
360 if (bytes_written
!= 1)
361 LOG_WARNING("writing trst failed");
367 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionums
)
370 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
371 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], tms_gpio
);
372 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[2], tdi_gpio
);
373 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], tdo_gpio
);
374 } else if (CMD_ARGC
!= 0) {
375 return ERROR_COMMAND_SYNTAX_ERROR
;
379 "SysfsGPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d",
380 tck_gpio
, tms_gpio
, tdi_gpio
, tdo_gpio
);
385 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tck
)
388 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tck_gpio
);
390 command_print(CMD
, "SysfsGPIO num: tck = %d", tck_gpio
);
394 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tms
)
397 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tms_gpio
);
399 command_print(CMD
, "SysfsGPIO num: tms = %d", tms_gpio
);
403 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdo
)
406 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdo_gpio
);
408 command_print(CMD
, "SysfsGPIO num: tdo = %d", tdo_gpio
);
412 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_tdi
)
415 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], tdi_gpio
);
417 command_print(CMD
, "SysfsGPIO num: tdi = %d", tdi_gpio
);
421 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_srst
)
424 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], srst_gpio
);
426 command_print(CMD
, "SysfsGPIO num: srst = %d", srst_gpio
);
430 COMMAND_HANDLER(sysfsgpio_handle_jtag_gpionum_trst
)
433 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], trst_gpio
);
435 command_print(CMD
, "SysfsGPIO num: trst = %d", trst_gpio
);
439 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionums
)
442 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
443 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], swdio_gpio
);
444 } else if (CMD_ARGC
!= 0) {
445 return ERROR_COMMAND_SYNTAX_ERROR
;
449 "SysfsGPIO nums: swclk = %d, swdio = %d",
450 swclk_gpio
, swdio_gpio
);
455 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swclk
)
458 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swclk_gpio
);
460 command_print(CMD
, "SysfsGPIO num: swclk = %d", swclk_gpio
);
464 COMMAND_HANDLER(sysfsgpio_handle_swd_gpionum_swdio
)
467 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], swdio_gpio
);
469 command_print(CMD
, "SysfsGPIO num: swdio = %d", swdio_gpio
);
473 static const struct command_registration sysfsgpio_command_handlers
[] = {
475 .name
= "sysfsgpio_jtag_nums",
476 .handler
= &sysfsgpio_handle_jtag_gpionums
,
477 .mode
= COMMAND_CONFIG
,
478 .help
= "gpio numbers for tck, tms, tdi, tdo. (in that order)",
479 .usage
= "[tck tms tdi tdo]",
482 .name
= "sysfsgpio_tck_num",
483 .handler
= &sysfsgpio_handle_jtag_gpionum_tck
,
484 .mode
= COMMAND_CONFIG
,
485 .help
= "gpio number for tck.",
489 .name
= "sysfsgpio_tms_num",
490 .handler
= &sysfsgpio_handle_jtag_gpionum_tms
,
491 .mode
= COMMAND_CONFIG
,
492 .help
= "gpio number for tms.",
496 .name
= "sysfsgpio_tdo_num",
497 .handler
= &sysfsgpio_handle_jtag_gpionum_tdo
,
498 .mode
= COMMAND_CONFIG
,
499 .help
= "gpio number for tdo.",
503 .name
= "sysfsgpio_tdi_num",
504 .handler
= &sysfsgpio_handle_jtag_gpionum_tdi
,
505 .mode
= COMMAND_CONFIG
,
506 .help
= "gpio number for tdi.",
510 .name
= "sysfsgpio_srst_num",
511 .handler
= &sysfsgpio_handle_jtag_gpionum_srst
,
512 .mode
= COMMAND_CONFIG
,
513 .help
= "gpio number for srst.",
517 .name
= "sysfsgpio_trst_num",
518 .handler
= &sysfsgpio_handle_jtag_gpionum_trst
,
519 .mode
= COMMAND_CONFIG
,
520 .help
= "gpio number for trst.",
524 .name
= "sysfsgpio_swd_nums",
525 .handler
= &sysfsgpio_handle_swd_gpionums
,
526 .mode
= COMMAND_CONFIG
,
527 .help
= "gpio numbers for swclk, swdio. (in that order)",
528 .usage
= "[swclk swdio]",
531 .name
= "sysfsgpio_swclk_num",
532 .handler
= &sysfsgpio_handle_swd_gpionum_swclk
,
533 .mode
= COMMAND_CONFIG
,
534 .help
= "gpio number for swclk.",
538 .name
= "sysfsgpio_swdio_num",
539 .handler
= &sysfsgpio_handle_swd_gpionum_swdio
,
540 .mode
= COMMAND_CONFIG
,
541 .help
= "gpio number for swdio.",
544 COMMAND_REGISTRATION_DONE
547 static int sysfsgpio_init(void);
548 static int sysfsgpio_quit(void);
550 static const char * const sysfsgpio_transports
[] = { "jtag", "swd", NULL
};
552 static struct jtag_interface sysfsgpio_interface
= {
553 .supported
= DEBUG_CAP_TMS_SEQ
,
554 .execute_queue
= bitbang_execute_queue
,
557 struct adapter_driver sysfsgpio_adapter_driver
= {
559 .transports
= sysfsgpio_transports
,
560 .commands
= sysfsgpio_command_handlers
,
562 .init
= sysfsgpio_init
,
563 .quit
= sysfsgpio_quit
,
564 .reset
= sysfsgpio_reset
,
566 .jtag_ops
= &sysfsgpio_interface
,
567 .swd_ops
= &bitbang_swd
,
570 static struct bitbang_interface sysfsgpio_bitbang
= {
571 .read
= sysfsgpio_read
,
572 .write
= sysfsgpio_write
,
573 .swdio_read
= sysfsgpio_swdio_read
,
574 .swdio_drive
= sysfsgpio_swdio_drive
,
578 /* helper func to close and cleanup files only if they were valid/ used */
579 static void cleanup_fd(int fd
, int gpio
)
585 unexport_sysfs_gpio(gpio
);
589 static void cleanup_all_fds(void)
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
);
596 cleanup_fd(srst_fd
, srst_gpio
);
597 cleanup_fd(swclk_fd
, swclk_gpio
);
598 cleanup_fd(swdio_fd
, swdio_gpio
);
601 static bool sysfsgpio_jtag_mode_possible(void)
603 if (!is_gpio_valid(tck_gpio
))
605 if (!is_gpio_valid(tms_gpio
))
607 if (!is_gpio_valid(tdi_gpio
))
609 if (!is_gpio_valid(tdo_gpio
))
614 static bool sysfsgpio_swd_mode_possible(void)
616 if (!is_gpio_valid(swclk_gpio
))
618 if (!is_gpio_valid(swdio_gpio
))
623 static int sysfsgpio_init(void)
625 bitbang_interface
= &sysfsgpio_bitbang
;
627 LOG_INFO("SysfsGPIO JTAG/SWD bitbang driver");
629 if (sysfsgpio_jtag_mode_possible()) {
630 if (sysfsgpio_swd_mode_possible())
631 LOG_INFO("JTAG and SWD modes enabled");
633 LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)");
634 } else if (sysfsgpio_swd_mode_possible()) {
635 LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)");
637 LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode");
638 return ERROR_JTAG_INIT_FAILED
;
643 * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST
644 * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high.
645 * For SWD, SWCLK and SWDIO are configures as output high.
648 tck_fd
= setup_sysfs_gpio(tck_gpio
, 1, 0);
654 tms_fd
= setup_sysfs_gpio(tms_gpio
, 1, 1);
660 tdi_fd
= setup_sysfs_gpio(tdi_gpio
, 1, 0);
666 tdo_fd
= setup_sysfs_gpio(tdo_gpio
, 0, 0);
671 /* assume active low*/
672 if (trst_gpio
>= 0) {
673 trst_fd
= setup_sysfs_gpio(trst_gpio
, 1, 1);
678 /* assume active low*/
679 if (srst_gpio
>= 0) {
680 srst_fd
= setup_sysfs_gpio(srst_gpio
, 1, 1);
685 if (swclk_gpio
>= 0) {
686 swclk_fd
= setup_sysfs_gpio(swclk_gpio
, 1, 0);
691 if (swdio_gpio
>= 0) {
692 swdio_fd
= setup_sysfs_gpio(swdio_gpio
, 1, 0);
697 if (sysfsgpio_swd_mode_possible()) {
699 bitbang_swd_switch_seq(JTAG_TO_SWD
);
701 bitbang_swd_switch_seq(SWD_TO_JTAG
);
708 return ERROR_JTAG_INIT_FAILED
;
711 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)