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

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)