1 /***************************************************************************
2 * Copyright (C) 2007 by Pavel Chromy *
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. *
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. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
28 #include "replacements.h"
30 /* project specific includes */
34 #include "configuration.h"
35 #include "time_support.h"
43 /* PRESTO access library includes */
44 #if BUILD_PRESTO_FTD2XX == 1
46 #elif BUILD_PRESTO_LIBFTDI == 1
49 #error "BUG: either FTD2XX and LIBFTDI has to be used"
53 int presto_jtag_speed(int speed
);
54 int presto_jtag_register_commands(struct command_context_s
*cmd_ctx
);
55 int presto_jtag_init(void);
56 int presto_jtag_quit(void);
58 jtag_interface_t presto_interface
=
61 .execute_queue
= bitq_execute_queue
,
62 .speed
= presto_jtag_speed
,
63 .register_commands
= presto_jtag_register_commands
,
64 .init
= presto_jtag_init
,
65 .quit
= presto_jtag_quit
,
69 int presto_bitq_out(int tms
, int tdi
, int tdo_req
);
70 int presto_bitq_flush(void);
71 int presto_bitq_sleep(unsigned long us
);
72 int presto_bitq_reset(int trst
, int srst
);
73 int presto_bitq_in_rdy(void);
74 int presto_bitq_in(void);
76 bitq_interface_t presto_bitq
=
78 .out
= presto_bitq_out
,
79 .flush
= presto_bitq_flush
,
80 .sleep
= presto_bitq_sleep
,
81 .reset
= presto_bitq_reset
,
82 .in_rdy
= presto_bitq_in_rdy
,
87 /* -------------------------------------------------------------------------- */
90 #define FT_DEVICE_NAME_LEN 64
91 #define FT_DEVICE_SERNUM_LEN 64
93 #define PRESTO_VID_PID 0x0403f1a0
94 #define PRESTO_VID (0x0403)
95 #define PRESTO_PID (0xf1a0)
97 #define BUFFER_SIZE (64*62)
99 typedef struct presto_s
101 #if BUILD_PRESTO_FTD2XX == 1
104 #elif BUILD_PRESTO_LIBFTDI == 1
105 struct ftdi_context ftdic
;
109 char serial
[FT_DEVICE_SERNUM_LEN
];
111 u8 buff_out
[BUFFER_SIZE
];
114 u8 buff_in
[BUFFER_SIZE
];
115 int buff_in_exp
; /* expected in buffer length */
116 int buff_in_len
; /* length of data received */
119 unsigned long total_out
;
120 unsigned long total_in
;
122 int jtag_tms
; /* last tms state */
123 int jtag_tck
; /* last tck state */
130 presto_t presto_state
;
131 presto_t
*presto
= &presto_state
;
133 u8 presto_init_seq
[] =
135 0x80, 0xA0, 0xA8, 0xB0, 0xC0, 0xE0
138 int presto_write(u8
*buf
, int size
)
140 #if BUILD_PRESTO_FTD2XX == 1
142 if ((presto
->status
= FT_Write(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
144 LOG_ERROR("FT_Write returned: %lu", presto
->status
);
145 return ERROR_JTAG_DEVICE_ERROR
;
148 #elif BUILD_PRESTO_LIBFTDI == 1
150 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, buf
, size
)) < 0)
152 LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&presto
->ftdic
));
153 return ERROR_JTAG_DEVICE_ERROR
;
155 ftbytes
= presto
->retval
;
160 LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%i < %i)", ftbytes
, size
);
161 return ERROR_JTAG_DEVICE_ERROR
;
167 int presto_read(u8
* buf
, int size
)
169 #if BUILD_PRESTO_FTD2XX == 1
171 if ((presto
->status
= FT_Read(presto
->handle
, buf
, size
, &ftbytes
)) != FT_OK
)
173 LOG_ERROR("FT_Read returned: %lu", presto
->status
);
174 return ERROR_JTAG_DEVICE_ERROR
;
177 #elif BUILD_PRESTO_LIBFTDI == 1
180 struct timeval timeout
, now
;
181 gettimeofday(&timeout
, NULL
);
182 timeval_add_time(&timeout
, 1, 0); /* one second timeout */
184 while (ftbytes
< size
)
186 if ((presto
->retval
= ftdi_read_data(&presto
->ftdic
, buf
+ ftbytes
, size
- ftbytes
)) < 0)
188 LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&presto
->ftdic
));
189 return ERROR_JTAG_DEVICE_ERROR
;
191 ftbytes
+= presto
->retval
;
193 gettimeofday(&now
, NULL
);
194 if ((now
.tv_sec
> timeout
.tv_sec
) || ((now
.tv_sec
== timeout
.tv_sec
) && (now
.tv_usec
> timeout
.tv_usec
)))
201 /* this is just a warning, there might have been timeout when detecting PRESTO, which is not fatal */
202 LOG_WARNING("couldn't read the requested number of bytes from PRESTO (%i < %i)", ftbytes
, size
);
203 return ERROR_JTAG_DEVICE_ERROR
;
209 #if BUILD_PRESTO_FTD2XX == 1
210 int presto_open_ftd2xx(char *req_serial
)
215 char devname
[FT_DEVICE_NAME_LEN
];
221 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
224 /* Add non-standard Vid/Pid to the linux driver */
225 if ((presto
->status
= FT_SetVIDPID(PRESTO_VID
, PRESTO_PID
)) != FT_OK
)
227 LOG_ERROR("couldn't add PRESTO VID/PID");
232 if ((presto
->status
= FT_ListDevices(&numdevs
, NULL
, FT_LIST_NUMBER_ONLY
)) != FT_OK
)
234 LOG_ERROR("FT_ListDevices failed: %i", (int)presto
->status
);
235 return ERROR_JTAG_DEVICE_ERROR
;
238 LOG_DEBUG("FTDI devices available: %i", numdevs
);
239 for (i
= 0; i
< numdevs
; i
++)
241 if ((presto
->status
= FT_Open(i
, &(presto
->handle
))) != FT_OK
)
243 /* this is not fatal, the device may be legitimately open by other process, hence debug message only */
244 LOG_DEBUG("FT_Open failed: %i", (int)presto
->status
);
247 LOG_DEBUG("FTDI device %i open", i
);
249 if ((presto
->status
= FT_GetDeviceInfo(presto
->handle
, &device
, &vidpid
,
250 presto
->serial
, devname
, NULL
)) == FT_OK
)
252 if (vidpid
== PRESTO_VID_PID
253 && (req_serial
== NULL
|| !strcmp(presto
->serial
, req_serial
)))
257 LOG_DEBUG("FT_GetDeviceInfo failed: %i", presto
->status
);
259 LOG_DEBUG("FTDI device %i does not match, closing", i
);
260 FT_Close(presto
->handle
);
261 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
264 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
265 return ERROR_JTAG_DEVICE_ERROR
; /* presto not open, return */
267 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 1)) != FT_OK
)
268 return ERROR_JTAG_DEVICE_ERROR
;
271 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 100, 0)) != FT_OK
)
272 return ERROR_JTAG_DEVICE_ERROR
;
274 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
275 return ERROR_JTAG_DEVICE_ERROR
;
278 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
279 return ERROR_JTAG_DEVICE_ERROR
;
281 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
282 probably a bug in library threading */
284 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
285 return ERROR_JTAG_DEVICE_ERROR
;
289 LOG_DEBUG("PRESTO reset");
291 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
292 return ERROR_JTAG_DEVICE_ERROR
;
293 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x80, 1)) != FT_OK
)
294 return ERROR_JTAG_DEVICE_ERROR
;
295 if ((presto
->status
= FT_SetBaudRate(presto
->handle
, 9600)) != FT_OK
)
296 return ERROR_JTAG_DEVICE_ERROR
;
299 for (i
= 0; i
< 4 * 62; i
++)
300 if ((presto
->status
=FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
301 return ERROR_JTAG_DEVICE_ERROR
;
305 if ((presto
->status
= FT_SetBitMode(presto
->handle
, 0x00, 0)) != FT_OK
)
306 return ERROR_JTAG_DEVICE_ERROR
;
308 if ((presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
)) != FT_OK
)
309 return ERROR_JTAG_DEVICE_ERROR
;
312 if ((presto
->status
= FT_Write(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
313 return ERROR_JTAG_DEVICE_ERROR
;
315 /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason,
316 probably a bug in library threading */
318 if ((presto
->status
= FT_Read(presto
->handle
, &presto_data
, 1, &ftbytes
)) != FT_OK
)
319 return ERROR_JTAG_DEVICE_ERROR
;
323 LOG_DEBUG("PRESTO not responding");
324 return ERROR_JTAG_DEVICE_ERROR
;
328 if ((presto
->status
= FT_SetTimeouts(presto
->handle
, 0, 0)) != FT_OK
)
329 return ERROR_JTAG_DEVICE_ERROR
;
332 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
333 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
334 return ERROR_JTAG_DEVICE_ERROR
;
339 #elif BUILD_PRESTO_LIBFTDI == 1
340 int presto_open_libftdi(char *req_serial
)
344 LOG_DEBUG("searching for PRESTO using libftdi");
346 /* initialize FTDI context structure */
347 if (ftdi_init(&presto
->ftdic
) < 0)
349 LOG_ERROR("unable to init libftdi: %s", presto
->ftdic
.error_str
);
350 return ERROR_JTAG_DEVICE_ERROR
;
353 /* context, vendor id, product id */
354 if (ftdi_usb_open_desc(&presto
->ftdic
, PRESTO_VID
, PRESTO_PID
, NULL
, req_serial
) < 0)
356 LOG_ERROR("unable to open PRESTO: %s", presto
->ftdic
.error_str
);
357 return ERROR_JTAG_DEVICE_ERROR
;
360 if (ftdi_usb_reset(&presto
->ftdic
) < 0)
362 LOG_ERROR("unable to reset PRESTO device");
363 return ERROR_JTAG_DEVICE_ERROR
;
366 if (ftdi_set_latency_timer(&presto
->ftdic
, 1) < 0)
368 LOG_ERROR("unable to set latency timer");
369 return ERROR_JTAG_DEVICE_ERROR
;
372 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
374 LOG_ERROR("unable to purge PRESTO buffers");
375 return ERROR_JTAG_DEVICE_ERROR
;
379 if (presto_write(&presto_data
, 1) != ERROR_OK
)
381 LOG_ERROR("error writing to PRESTO");
382 return ERROR_JTAG_DEVICE_ERROR
;
385 if (presto_read(&presto_data
, 1) != ERROR_OK
)
387 LOG_DEBUG("no response from PRESTO, retrying");
389 if (ftdi_usb_purge_buffers(&presto
->ftdic
) < 0)
390 return ERROR_JTAG_DEVICE_ERROR
;
393 if (presto_write(&presto_data
, 1) != ERROR_OK
)
394 return ERROR_JTAG_DEVICE_ERROR
;
396 if (presto_read(&presto_data
, 1) != ERROR_OK
)
398 LOG_ERROR("no response from PRESTO, giving up");
399 return ERROR_JTAG_DEVICE_ERROR
;
403 if (presto_write(presto_init_seq
, sizeof(presto_init_seq
)) != ERROR_OK
)
405 LOG_ERROR("error writing PRESTO init sequence");
406 return ERROR_JTAG_DEVICE_ERROR
;
411 #endif /* BUILD_PRESTO_LIBFTDI == 1 */
413 int presto_open(char *req_serial
)
415 presto
->buff_out_pos
=0;
416 presto
->buff_in_pos
=0;
417 presto
->buff_in_len
=0;
418 presto
->buff_in_exp
=0;
425 presto
->jtag_tdi_data
=0;
426 presto
->jtag_tdi_count
=0;
428 #if BUILD_PRESTO_FTD2XX == 1
429 return presto_open_ftd2xx(req_serial
);
430 #elif BUILD_PRESTO_LIBFTDI == 1
431 return presto_open_libftdi(req_serial
);
435 int presto_close(void)
438 int result
= ERROR_OK
;
440 #if BUILD_PRESTO_FTD2XX == 1
441 unsigned long ftbytes
;
443 if (presto
->handle
== (FT_HANDLE
)INVALID_HANDLE_VALUE
)
446 presto
->status
= FT_Purge(presto
->handle
, FT_PURGE_TX
| FT_PURGE_RX
);
447 if (presto
->status
!= FT_OK
)
448 result
= ERROR_JTAG_DEVICE_ERROR
;
450 presto
->status
= FT_Write(presto
->handle
, &presto_init_seq
, sizeof(presto_init_seq
), &ftbytes
);
451 if (presto
->status
!= FT_OK
|| ftbytes
!= sizeof(presto_init_seq
))
452 result
= ERROR_JTAG_DEVICE_ERROR
;
454 if ((presto
->status
= FT_SetLatencyTimer(presto
->handle
, 16)) != FT_OK
)
455 result
= ERROR_JTAG_DEVICE_ERROR
;
457 if ((presto
->status
= FT_Close(presto
->handle
)) != FT_OK
)
458 result
= ERROR_JTAG_DEVICE_ERROR
;
460 presto
->handle
= (FT_HANDLE
)INVALID_HANDLE_VALUE
;
462 #elif BUILD_PRESTO_LIBFTDI == 1
464 if ((presto
->retval
= ftdi_write_data(&presto
->ftdic
, presto_init_seq
, sizeof(presto_init_seq
))) != sizeof(presto_init_seq
))
465 result
= ERROR_JTAG_DEVICE_ERROR
;
467 if ((presto
->retval
= ftdi_set_latency_timer(&presto
->ftdic
, 16)) < 0)
468 result
= ERROR_JTAG_DEVICE_ERROR
;
470 if ((presto
->retval
= ftdi_usb_close(&presto
->ftdic
)) < 0)
471 result
= ERROR_JTAG_DEVICE_ERROR
;
473 ftdi_deinit(&presto
->ftdic
);
480 int presto_flush(void)
482 if (presto
->buff_out_pos
== 0)
485 #if BUILD_PRESTO_FTD2XX == 1
486 if (presto
->status
!= FT_OK
)
487 #elif BUILD_PRESTO_LIBFTDI == 1
488 if (presto
->retval
< 0)
491 LOG_DEBUG("error in previous communication, canceling I/O operation");
492 return ERROR_JTAG_DEVICE_ERROR
;
495 if (presto_write(presto
->buff_out
, presto
->buff_out_pos
) != ERROR_OK
)
497 presto
->buff_out_pos
= 0;
498 return ERROR_JTAG_DEVICE_ERROR
;
501 presto
->total_out
+= presto
->buff_out_pos
;
502 presto
->buff_out_pos
= 0;
504 if (presto
->buff_in_exp
== 0)
507 presto
->buff_in_pos
= 0;
508 presto
->buff_in_len
= 0;
510 if (presto_read(presto
->buff_in
, presto
->buff_in_exp
) != ERROR_OK
)
512 presto
->buff_in_exp
= 0;
513 return ERROR_JTAG_DEVICE_ERROR
;
516 presto
->total_in
+= presto
->buff_in_exp
;
517 presto
->buff_in_len
= presto
->buff_in_exp
;
518 presto
->buff_in_exp
= 0;
524 int presto_sendbyte(int data
)
526 if (data
== EOF
) return presto_flush();
528 if (presto
->buff_out_pos
< BUFFER_SIZE
)
530 presto
->buff_out
[presto
->buff_out_pos
++] = (u8
)data
;
531 if (((data
& 0xC0) == 0x40) || ((data
& 0xD0)== 0xD0))
532 presto
->buff_in_exp
++;
535 return ERROR_JTAG_DEVICE_ERROR
;
537 #if BUILD_PRESTO_FTD2XX == 1
538 if (presto
->buff_out_pos
>= BUFFER_SIZE
)
539 #elif BUILD_PRESTO_LIBFTDI == 1
540 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 bytes only!) */
541 if (presto
->buff_out_pos
>= BUFFER_SIZE
|| presto
->buff_in_exp
==128)
543 return presto_flush();
549 int presto_getbyte(void)
551 if (presto
->buff_in_pos
< presto
->buff_in_len
)
552 return presto
->buff_in
[presto
->buff_in_pos
++];
554 if (presto
->buff_in_exp
== 0)
557 if (presto_flush() != ERROR_OK
)
560 if (presto
->buff_in_pos
<presto
->buff_in_len
)
561 return presto
->buff_in
[presto
->buff_in_pos
++];
567 /* -------------------------------------------------------------------------- */
570 int presto_bitq_out(int tms
, int tdi
, int tdo_req
)
572 unsigned char cmdparam
;
574 if (presto
->jtag_tck
== 0)
576 presto_sendbyte(0xA4);
577 presto
->jtag_tck
= 1;
580 else if (!tdo_req
&& tms
== presto
->jtag_tms
)
582 if (presto
->jtag_tdi_count
== 0)
583 presto
->jtag_tdi_data
= (tdi
!= 0);
585 presto
->jtag_tdi_data
|= (tdi
!= 0) << presto
->jtag_tdi_count
;
587 if (++presto
->jtag_tdi_count
== 4)
589 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
590 presto_sendbyte(presto
->jtag_tdi_data
);
591 presto
->jtag_tdi_count
= 0;
596 if (presto
->jtag_tdi_count
)
598 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
599 presto_sendbyte(presto
->jtag_tdi_data
);
600 presto
->jtag_tdi_count
= 0;
608 presto_sendbyte( 0xC0 | cmdparam
);
610 if (tms
!= presto
->jtag_tms
)
613 presto_sendbyte(0xEC);
615 presto_sendbyte(0xE8);
616 presto
->jtag_tms
= tms
;
620 presto_sendbyte(0xD4 | cmdparam
);
622 presto_sendbyte(0xC4|cmdparam
);
628 int presto_bitq_flush(void)
630 if (presto
->jtag_tdi_count
)
632 presto
->jtag_tdi_data
|= (presto
->jtag_tdi_count
- 1) << 4;
633 presto_sendbyte(presto
->jtag_tdi_data
);
634 presto
->jtag_tdi_count
= 0;
637 presto_sendbyte(0xCA);
638 presto
->jtag_tck
= 0;
640 presto_sendbyte(0xA0);
642 return presto_flush();
646 int presto_bitq_in_rdy(void)
648 if (presto
->buff_in_pos
>=presto
->buff_in_len
)
650 return presto
->buff_in_len
-presto
->buff_in_pos
;
654 int presto_bitq_in(void)
656 if (presto
->buff_in_pos
>=presto
->buff_in_len
)
658 if (presto
->buff_in
[presto
->buff_in_pos
++]&0x08) return 1;
663 int presto_bitq_sleep(unsigned long us
)
674 waits
= us
/ 170 + 2;
676 presto_sendbyte(0x80);
682 int presto_bitq_reset(int trst
, int srst
)
687 if (presto
->jtag_tms
)
693 presto_sendbyte(cmd
);
698 /* -------------------------------------------------------------------------- */
700 char *presto_speed_text
[4] =
708 int presto_jtag_speed(int speed
)
711 if ((speed
< 0) || (speed
> 3))
713 LOG_INFO("valid speed values: 0 (3 MHz), 1 (1.5 MHz), 2 (750 kHz) and 3 (93.75 kHz)");
714 return ERROR_INVALID_ARGUMENTS
;
717 LOG_INFO("setting speed to %d, max. TCK freq. is %s", speed
, presto_speed_text
[speed
]);
718 return presto_sendbyte(0xA8 | speed
);
724 int presto_handle_serial_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
730 presto_serial
= strdup(args
[0]);
734 LOG_ERROR("expected exactly one argument to presto_serial <serial-number>");
741 int presto_jtag_register_commands(struct command_context_s
*cmd_ctx
)
743 register_command(cmd_ctx
, NULL
, "presto_serial", presto_handle_serial_command
,
744 COMMAND_CONFIG
, NULL
);
749 int presto_jtag_init(void)
751 if (presto_open(presto_serial
) != ERROR_OK
)
754 if (presto_serial
!= NULL
)
755 LOG_ERROR("Cannot open PRESTO, serial number '%s'", presto_serial
);
757 LOG_ERROR("Cannot open PRESTO");
758 return ERROR_JTAG_INIT_FAILED
;
760 LOG_INFO("PRESTO open, serial number '%s'", presto
->serial
);
762 /* use JTAG speed setting from configuration file */
763 presto_jtag_speed(jtag_speed
);
765 bitq_interface
= &presto_bitq
;
770 int presto_jtag_quit(void)
774 LOG_INFO("PRESTO closed");
779 presto_serial
= NULL
;
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)