change #include "interface.h" to <jtag/interface.h>
[openocd.git] / src / jtag / drivers / usbprog.c
1 /***************************************************************************
2 * Copyright (C) 2007 by Benedikt Sauter *
3 * sauter@ixbat.de *
4 * *
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. *
9 * *
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. *
14 * *
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 ***************************************************************************/
20
21 /*
22 * This file is based on Dominic Rath's amt_jtagaccel.c.
23 *
24 * usbprog is a free programming adapter. You can easily install
25 * different firmware versions from an "online pool" over USB.
26 * The adapter can be used for programming and debugging AVR and ARM
27 * processors, as USB to RS232 converter, as JTAG interface or as
28 * simple I/O interface (5 lines).
29 *
30 * http://www.embedded-projects.net/usbprog
31 */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <jtag/interface.h>
38 #include <jtag/commands.h>
39 #include "usb_common.h"
40
41
42 #define VID 0x1781
43 #define PID 0x0c63
44
45 /* Pins at usbprog */
46 #define TDO_BIT 0
47 #define TDI_BIT 3
48 #define TCK_BIT 2
49 #define TMS_BIT 1
50
51 static void usbprog_end_state(tap_state_t state);
52 static void usbprog_state_move(void);
53 static void usbprog_path_move(struct pathmove_command *cmd);
54 static void usbprog_runtest(int num_cycles);
55 static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size);
56
57 #define UNKOWN_COMMAND 0x00
58 #define PORT_DIRECTION 0x01
59 #define PORT_SET 0x02
60 #define PORT_GET 0x03
61 #define PORT_SETBIT 0x04
62 #define PORT_GETBIT 0x05
63 #define WRITE_TDI 0x06
64 #define READ_TDO 0x07
65 #define WRITE_AND_READ 0x08
66 #define WRITE_TMS 0x09
67 #define WRITE_TMS_CHAIN 0x0A
68
69 struct usbprog_jtag
70 {
71 struct usb_dev_handle* usb_handle;
72 };
73
74 static struct usbprog_jtag * usbprog_jtag_handle;
75
76 static struct usbprog_jtag* usbprog_jtag_open(void);
77 //static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag);
78 static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag);
79 static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen);
80
81 static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
82 static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
83 static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
84 static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan);
85
86 static char tms_chain[64];
87 static int tms_chain_index;
88
89 static void usbprog_jtag_tms_collect(char tms_scan);
90 static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag);
91
92 static void usbprog_write(int tck, int tms, int tdi);
93 static void usbprog_reset(int trst, int srst);
94
95 static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction);
96 static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value);
97 //static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag);
98 static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value);
99 //static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit);
100
101 static int usbprog_speed(int speed)
102 {
103 return ERROR_OK;
104 }
105
106 static int usbprog_execute_queue(void)
107 {
108 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
109 int scan_size;
110 enum scan_type type;
111 uint8_t *buffer;
112
113 while (cmd)
114 {
115 switch (cmd->type)
116 {
117 case JTAG_RESET:
118 #ifdef _DEBUG_JTAG_IO_
119 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
120 #endif
121 if (cmd->cmd.reset->trst == 1)
122 {
123 tap_set_state(TAP_RESET);
124 }
125 usbprog_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
126 break;
127 case JTAG_RUNTEST:
128 #ifdef _DEBUG_JTAG_IO_
129 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
130 #endif
131 usbprog_end_state(cmd->cmd.runtest->end_state);
132 usbprog_runtest(cmd->cmd.runtest->num_cycles);
133 break;
134 case JTAG_STATEMOVE:
135 #ifdef _DEBUG_JTAG_IO_
136 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
137 #endif
138 usbprog_end_state(cmd->cmd.statemove->end_state);
139 usbprog_state_move();
140 break;
141 case JTAG_PATHMOVE:
142 #ifdef _DEBUG_JTAG_IO_
143 LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
144 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
145 #endif
146 usbprog_path_move(cmd->cmd.pathmove);
147 break;
148 case JTAG_SCAN:
149 #ifdef _DEBUG_JTAG_IO_
150 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
151 #endif
152 usbprog_end_state(cmd->cmd.scan->end_state);
153 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
154 type = jtag_scan_type(cmd->cmd.scan);
155 usbprog_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
156 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
157 return ERROR_JTAG_QUEUE_FAILED;
158 if (buffer)
159 free(buffer);
160 break;
161 case JTAG_SLEEP:
162 #ifdef _DEBUG_JTAG_IO_
163 LOG_DEBUG("sleep %i", cmd->cmd.sleep->us);
164 #endif
165 jtag_sleep(cmd->cmd.sleep->us);
166 break;
167 default:
168 LOG_ERROR("BUG: unknown JTAG command type encountered");
169 exit(-1);
170 }
171
172 cmd = cmd->next;
173 }
174
175 return ERROR_OK;
176 }
177
178 static int usbprog_init(void)
179 {
180 usbprog_jtag_handle = usbprog_jtag_open();
181
182 tms_chain_index = 0;
183 if (usbprog_jtag_handle == 0)
184 {
185 LOG_ERROR("Can't find USB JTAG Interface! Please check connection and permissions.");
186 return ERROR_JTAG_INIT_FAILED;
187 }
188
189 LOG_INFO("USB JTAG Interface ready!");
190
191 usbprog_jtag_init(usbprog_jtag_handle);
192 usbprog_reset(0, 0);
193 usbprog_write(0, 0, 0);
194
195 return ERROR_OK;
196 }
197
198 static int usbprog_quit(void)
199 {
200 return ERROR_OK;
201 }
202
203 /*************** jtag execute commands **********************/
204 static void usbprog_end_state(tap_state_t state)
205 {
206 if (tap_is_state_stable(state))
207 tap_set_end_state(state);
208 else
209 {
210 LOG_ERROR("BUG: %i is not a valid end state", state);
211 exit(-1);
212 }
213 }
214
215 static void usbprog_state_move(void)
216 {
217 int i = 0, tms = 0;
218 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), tap_get_end_state());
219 int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state());
220
221 usbprog_jtag_write_tms(usbprog_jtag_handle, (char)tms_scan);
222 for (i = 0; i < tms_count; i++)
223 {
224 tms = (tms_scan >> i) & 1;
225 }
226
227 tap_set_state(tap_get_end_state());
228 }
229
230 static void usbprog_path_move(struct pathmove_command *cmd)
231 {
232 int num_states = cmd->num_states;
233 int state_count;
234
235 /* There may be queued transitions, and before following a specified
236 path, we must flush those queued transitions */
237 usbprog_jtag_tms_send(usbprog_jtag_handle);
238
239 state_count = 0;
240 while (num_states)
241 {
242 if (tap_state_transition(tap_get_state(), false) == cmd->path[state_count])
243 {
244 /* LOG_INFO("1"); */
245 usbprog_write(0, 0, 0);
246 usbprog_write(1, 0, 0);
247 }
248 else if (tap_state_transition(tap_get_state(), true) == cmd->path[state_count])
249 {
250 /* LOG_INFO("2"); */
251 usbprog_write(0, 1, 0);
252 usbprog_write(1, 1, 0);
253 }
254 else
255 {
256 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(tap_get_state()), tap_state_name(cmd->path[state_count]));
257 exit(-1);
258 }
259
260 tap_set_state(cmd->path[state_count]);
261 state_count++;
262 num_states--;
263 }
264
265 tap_set_end_state(tap_get_state());
266 }
267
268 static void usbprog_runtest(int num_cycles)
269 {
270 int i;
271
272 /* only do a state_move when we're not already in IDLE */
273 if (tap_get_state() != TAP_IDLE)
274 {
275 usbprog_end_state(TAP_IDLE);
276 usbprog_state_move();
277 }
278
279 /* execute num_cycles */
280 if (num_cycles > 0)
281 {
282 usbprog_jtag_tms_send(usbprog_jtag_handle);
283 usbprog_write(0, 0, 0);
284 }
285 else
286 {
287 usbprog_jtag_tms_send(usbprog_jtag_handle);
288 /* LOG_INFO("NUM CYCLES %i",num_cycles); */
289 }
290
291 for (i = 0; i < num_cycles; i++)
292 {
293 usbprog_write(1, 0, 0);
294 usbprog_write(0, 0, 0);
295 }
296
297 #ifdef _DEBUG_JTAG_IO_
298 LOG_DEBUG("runtest: cur_state %s end_state %s", tap_state_name(tap_get_state()), tap_state_name(tap_get_end_state()));
299 #endif
300
301 /* finish in end_state */
302 /*
303 usbprog_end_state(saved_end_state);
304 if (tap_get_state() != tap_get_end_state())
305 usbprog_state_move();
306 */
307 }
308
309 static void usbprog_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
310 {
311 tap_state_t saved_end_state = tap_get_end_state();
312
313 if (ir_scan)
314 usbprog_end_state(TAP_IRSHIFT);
315 else
316 usbprog_end_state(TAP_DRSHIFT);
317
318 /* Only move if we're not already there */
319 if (tap_get_state() != tap_get_end_state())
320 usbprog_state_move();
321
322 usbprog_end_state(saved_end_state);
323
324 usbprog_jtag_tms_send(usbprog_jtag_handle);
325
326 void (*f)(struct usbprog_jtag *usbprog_jtag, char * buffer, int size);
327 switch (type) {
328 case SCAN_OUT: f = &usbprog_jtag_write_tdi; break;
329 case SCAN_IN: f = &usbprog_jtag_read_tdo; break;
330 case SCAN_IO: f = &usbprog_jtag_write_and_read; break;
331 default:
332 LOG_ERROR("unknown scan type: %i", type);
333 exit(-1);
334 }
335 f(usbprog_jtag_handle, (char *)buffer, scan_size);
336
337 /* The adapter does the transition to PAUSE internally */
338 if (ir_scan)
339 tap_set_state(TAP_IRPAUSE);
340 else
341 tap_set_state(TAP_DRPAUSE);
342
343 if (tap_get_state() != tap_get_end_state())
344 usbprog_state_move();
345 }
346
347 /*************** jtag wrapper functions *********************/
348
349 static void usbprog_write(int tck, int tms, int tdi)
350 {
351 unsigned char output_value = 0x00;
352
353 if (tms)
354 output_value |= (1 << TMS_BIT);
355 if (tdi)
356 output_value |= (1 << TDI_BIT);
357 if (tck)
358 output_value |= (1 << TCK_BIT);
359
360 usbprog_jtag_write_slice(usbprog_jtag_handle,output_value);
361 }
362
363 /* (1) assert or (0) deassert reset lines */
364 static void usbprog_reset(int trst, int srst)
365 {
366 LOG_DEBUG("trst: %i, srst: %i", trst, srst);
367
368 if (trst)
369 usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 0);
370 else
371 usbprog_jtag_set_bit(usbprog_jtag_handle, 5, 1);
372
373 if (srst)
374 usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 0);
375 else
376 usbprog_jtag_set_bit(usbprog_jtag_handle, 4, 1);
377 }
378
379 /*************** jtag lowlevel functions ********************/
380
381 struct usb_bus *busses;
382
383 struct usbprog_jtag* usbprog_jtag_open(void)
384 {
385 usb_set_debug(10);
386 usb_init();
387
388 const uint16_t vids[] = { VID, 0 };
389 const uint16_t pids[] = { PID, 0 };
390 struct usb_dev_handle *dev;
391 if (jtag_usb_open(vids, pids, &dev) != ERROR_OK)
392 return NULL;
393
394 struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));
395 tmp->usb_handle = dev;
396
397 usb_set_configuration(dev, 1);
398 usb_claim_interface(dev, 0);
399 usb_set_altinterface(dev, 0);
400
401 return tmp;
402 }
403
404 #if 0
405 static void usbprog_jtag_close(struct usbprog_jtag *usbprog_jtag)
406 {
407 usb_close(usbprog_jtag->usb_handle);
408 free(usbprog_jtag);
409 }
410 #endif
411
412 static unsigned char usbprog_jtag_message(struct usbprog_jtag *usbprog_jtag, char *msg, int msglen)
413 {
414 int res = usb_bulk_write(usbprog_jtag->usb_handle, 3, msg,msglen, 100);
415 if ((msg[0] == 2) || (msg[0] == 1) || (msg[0] == 4) || (msg[0] == 0) || \
416 (msg[0] == 6) || (msg[0] == 0x0A) || (msg[0] == 9))
417 return 1;
418 if (res == msglen)
419 {
420 /* LOG_INFO("HALLLLOOO %i",(int)msg[0]); */
421 res = usb_bulk_read(usbprog_jtag->usb_handle, 0x82, msg, 2, 100);
422 if (res > 0)
423 return (unsigned char)msg[1];
424 else
425 return -1;
426 }
427 else
428 return -1;
429 return 0;
430 }
431
432 static void usbprog_jtag_init(struct usbprog_jtag *usbprog_jtag)
433 {
434 usbprog_jtag_set_direction(usbprog_jtag, 0xFE);
435 }
436
437 static void usbprog_jtag_write_and_read(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
438 {
439 char tmp[64]; /* fastes packet size for usb controller */
440 int send_bits, bufindex = 0, fillindex = 0, i, loops;
441
442 char swap;
443 /* 61 byte can be transfered (488 bit) */
444
445 while (size > 0)
446 {
447 if (size > 488)
448 {
449 send_bits = 488;
450 size = size - 488;
451 loops = 61;
452 }
453 else
454 {
455 send_bits = size;
456 loops = size / 8;
457 loops++;
458 size = 0;
459 }
460 tmp[0] = WRITE_AND_READ;
461 tmp[1] = (char)(send_bits >> 8); /* high */
462 tmp[2] = (char)(send_bits); /* low */
463 i = 0;
464
465 for (i = 0; i < loops; i++)
466 {
467 tmp[3 + i] = buffer[bufindex];
468 bufindex++;
469 }
470
471 if (usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000) == 64)
472 {
473 /* LOG_INFO("HALLLLOOO2 %i",(int)tmp[0]); */
474 usleep(1);
475 int timeout = 0;
476 while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 1000) < 1)
477 {
478 timeout++;
479 if (timeout > 10)
480 break;
481 }
482
483 for (i = 0; i < loops; i++)
484 {
485 swap = tmp[3 + i];
486 buffer[fillindex++] = swap;
487 }
488 }
489 }
490 }
491
492 static void usbprog_jtag_read_tdo(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
493 {
494 char tmp[64]; /* fastes packet size for usb controller */
495 int send_bits, fillindex = 0, i, loops;
496
497 char swap;
498 /* 61 byte can be transfered (488 bit) */
499
500 while (size > 0)
501 {
502 if (size > 488)
503 {
504 send_bits = 488;
505 size = size - 488;
506 loops = 61;
507 }
508 else
509 {
510 send_bits = size;
511 loops = size / 8;
512 loops++;
513 size = 0;
514 }
515 tmp[0] = WRITE_AND_READ;
516 tmp[1] = (char)(send_bits >> 8); /* high */
517 tmp[2] = (char)(send_bits); /* low */
518
519 usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 3, 1000);
520
521 /* LOG_INFO("HALLLLOOO3 %i",(int)tmp[0]); */
522 int timeout = 0;
523 usleep(1);
524 while (usb_bulk_read(usbprog_jtag->usb_handle, 0x82, tmp, 64, 10) < 1)
525 {
526 timeout++;
527 if (timeout > 10)
528 break;
529 }
530
531 for (i = 0; i < loops; i++)
532 {
533 swap = tmp[3 + i];
534 buffer[fillindex++] = swap;
535 }
536 }
537 }
538
539 static void usbprog_jtag_write_tdi(struct usbprog_jtag *usbprog_jtag, char * buffer, int size)
540 {
541 char tmp[64]; /* fastes packet size for usb controller */
542 int send_bits, bufindex = 0, i, loops;
543
544 /* 61 byte can be transfered (488 bit) */
545 while (size > 0)
546 {
547 if (size > 488)
548 {
549 send_bits = 488;
550 size = size - 488;
551 loops = 61;
552 }
553 else
554 {
555 send_bits = size;
556 loops = size/8;
557 /* if (loops == 0) */
558 loops++;
559 size = 0;
560 }
561 tmp[0] = WRITE_TDI;
562 tmp[1] = (char)(send_bits >> 8); /* high */
563 tmp[2] = (char)(send_bits); /* low */
564 i = 0;
565
566 for (i = 0; i < loops; i++)
567 {
568 tmp[3 + i] = buffer[bufindex];
569 bufindex++;
570 }
571 usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, 64, 1000);
572 }
573 }
574
575 static void usbprog_jtag_write_tms(struct usbprog_jtag *usbprog_jtag, char tms_scan)
576 {
577 usbprog_jtag_tms_collect(tms_scan);
578 }
579
580 static void usbprog_jtag_set_direction(struct usbprog_jtag *usbprog_jtag, unsigned char direction)
581 {
582 char tmp[2];
583 tmp[0] = PORT_DIRECTION;
584 tmp[1] = (char)direction;
585 usbprog_jtag_message(usbprog_jtag, tmp, 2);
586 }
587
588 static void usbprog_jtag_write_slice(struct usbprog_jtag *usbprog_jtag,unsigned char value)
589 {
590 char tmp[2];
591 tmp[0] = PORT_SET;
592 tmp[1] = (char)value;
593 usbprog_jtag_message(usbprog_jtag, tmp, 2);
594 }
595
596 #if 0
597 static unsigned char usbprog_jtag_get_port(struct usbprog_jtag *usbprog_jtag)
598 {
599 char tmp[2];
600 tmp[0] = PORT_GET;
601 tmp[1] = 0x00;
602 return usbprog_jtag_message(usbprog_jtag, tmp, 2);
603 }
604 #endif
605
606 static void usbprog_jtag_set_bit(struct usbprog_jtag *usbprog_jtag,int bit, int value)
607 {
608 char tmp[3];
609 tmp[0] = PORT_SETBIT;
610 tmp[1] = (char)bit;
611 if (value == 1)
612 tmp[2] = 0x01;
613 else
614 tmp[2] = 0x00;
615 usbprog_jtag_message(usbprog_jtag, tmp, 3);
616 }
617
618 #if 0
619 static int usbprog_jtag_get_bit(struct usbprog_jtag *usbprog_jtag, int bit)
620 {
621 char tmp[2];
622 tmp[0] = PORT_GETBIT;
623 tmp[1] = (char)bit;
624
625 if (usbprog_jtag_message(usbprog_jtag, tmp, 2) > 0)
626 return 1;
627 else
628 return 0;
629 }
630 #endif
631
632 static void usbprog_jtag_tms_collect(char tms_scan)
633 {
634 tms_chain[tms_chain_index] = tms_scan;
635 tms_chain_index++;
636 }
637
638 static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
639 {
640 int i;
641 /* LOG_INFO("TMS SEND"); */
642 if (tms_chain_index > 0)
643 {
644 char tmp[tms_chain_index + 2];
645 tmp[0] = WRITE_TMS_CHAIN;
646 tmp[1] = (char)(tms_chain_index);
647 for (i = 0; i < tms_chain_index + 1; i++)
648 tmp[2 + i] = tms_chain[i];
649 usb_bulk_write(usbprog_jtag->usb_handle, 3, tmp, tms_chain_index + 2, 1000);
650 tms_chain_index = 0;
651 }
652 }
653
654 struct jtag_interface usbprog_interface = {
655 .name = "usbprog",
656 .execute_queue = &usbprog_execute_queue,
657 .speed = &usbprog_speed,
658 .init = &usbprog_init,
659 .quit = &usbprog_quit
660 };

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)