1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
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 ***************************************************************************/
30 #include "algorithm.h"
31 #include "binarybuffer.h"
36 /* flash programming support for Philips LPC2xxx devices
37 * currently supported devices:
38 * variant 1 (lpc2000_v1):
46 * variant 2 (lpc2000_v2):
54 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
);
55 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
56 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
);
57 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
58 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
59 int lpc2000_probe(struct flash_bank_s
*bank
);
60 int lpc2000_erase_check(struct flash_bank_s
*bank
);
61 int lpc2000_protect_check(struct flash_bank_s
*bank
);
62 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
64 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
66 flash_driver_t lpc2000_flash
=
69 .register_commands
= lpc2000_register_commands
,
70 .flash_bank_command
= lpc2000_flash_bank_command
,
71 .erase
= lpc2000_erase
,
72 .protect
= lpc2000_protect
,
73 .write
= lpc2000_write
,
74 .probe
= lpc2000_probe
,
75 .auto_probe
= lpc2000_probe
,
76 .erase_check
= lpc2000_erase_check
,
77 .protect_check
= lpc2000_protect_check
,
81 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
)
83 command_t
*lpc2000_cmd
= register_command(cmd_ctx
, NULL
, "lpc2000", NULL
, COMMAND_ANY
, NULL
);
85 register_command(cmd_ctx
, lpc2000_cmd
, "part_id", lpc2000_handle_part_id_command
, COMMAND_EXEC
,
86 "print part id of lpc2000 flash bank <num>");
91 int lpc2000_build_sector_list(struct flash_bank_s
*bank
)
93 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
95 /* default to a 4096 write buffer */
96 lpc2000_info
->cmd51_max_buffer
= 4096;
98 if (lpc2000_info
->variant
== 1)
103 /* variant 1 has different layout for 128kb and 256kb flashes */
104 if (bank
->size
== 128 * 1024)
106 bank
->num_sectors
= 16;
107 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 16);
108 for (i
= 0; i
< 16; i
++)
110 bank
->sectors
[i
].offset
= offset
;
111 bank
->sectors
[i
].size
= 8 * 1024;
112 offset
+= bank
->sectors
[i
].size
;
113 bank
->sectors
[i
].is_erased
= -1;
114 bank
->sectors
[i
].is_protected
= 1;
117 else if (bank
->size
== 256 * 1024)
119 bank
->num_sectors
= 18;
120 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 18);
122 for (i
= 0; i
< 8; i
++)
124 bank
->sectors
[i
].offset
= offset
;
125 bank
->sectors
[i
].size
= 8 * 1024;
126 offset
+= bank
->sectors
[i
].size
;
127 bank
->sectors
[i
].is_erased
= -1;
128 bank
->sectors
[i
].is_protected
= 1;
130 for (i
= 8; i
< 10; i
++)
132 bank
->sectors
[i
].offset
= offset
;
133 bank
->sectors
[i
].size
= 64 * 1024;
134 offset
+= bank
->sectors
[i
].size
;
135 bank
->sectors
[i
].is_erased
= -1;
136 bank
->sectors
[i
].is_protected
= 1;
138 for (i
= 10; i
< 18; i
++)
140 bank
->sectors
[i
].offset
= offset
;
141 bank
->sectors
[i
].size
= 8 * 1024;
142 offset
+= bank
->sectors
[i
].size
;
143 bank
->sectors
[i
].is_erased
= -1;
144 bank
->sectors
[i
].is_protected
= 1;
149 LOG_ERROR("BUG: unknown bank->size encountered");
153 else if (lpc2000_info
->variant
== 2)
159 /* variant 2 has a uniform layout, only number of sectors differs */
163 lpc2000_info
->cmd51_max_buffer
= 1024;
167 lpc2000_info
->cmd51_max_buffer
= 1024;
190 LOG_ERROR("BUG: unknown bank->size encountered");
195 bank
->num_sectors
= num_sectors
;
196 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
198 for (i
= 0; i
< num_sectors
; i
++)
200 if ((i
>= 0) && (i
< 8))
202 bank
->sectors
[i
].offset
= offset
;
203 bank
->sectors
[i
].size
= 4 * 1024;
204 offset
+= bank
->sectors
[i
].size
;
205 bank
->sectors
[i
].is_erased
= -1;
206 bank
->sectors
[i
].is_protected
= 1;
208 if ((i
>= 8) && (i
< 22))
210 bank
->sectors
[i
].offset
= offset
;
211 bank
->sectors
[i
].size
= 32 * 1024;
212 offset
+= bank
->sectors
[i
].size
;
213 bank
->sectors
[i
].is_erased
= -1;
214 bank
->sectors
[i
].is_protected
= 1;
216 if ((i
>= 22) && (i
< 27))
218 bank
->sectors
[i
].offset
= offset
;
219 bank
->sectors
[i
].size
= 4 * 1024;
220 offset
+= bank
->sectors
[i
].size
;
221 bank
->sectors
[i
].is_erased
= -1;
222 bank
->sectors
[i
].is_protected
= 1;
228 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
235 /* call LPC2000 IAP function
236 * uses 172 bytes working area
237 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
238 * 0x8 to 0x1f: command parameter table
239 * 0x20 to 0x2b: command result table
240 * 0x2c to 0xac: stack (only 128b needed)
242 int lpc2000_iap_call(flash_bank_t
*bank
, int code
, u32 param_table
[5], u32 result_table
[2])
244 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
245 target_t
*target
= bank
->target
;
246 mem_param_t mem_params
[2];
247 reg_param_t reg_params
[5];
248 armv4_5_algorithm_t armv4_5_info
;
251 /* regrab previously allocated working_area, or allocate a new one */
252 if (!lpc2000_info
->iap_working_area
)
256 /* make sure we have a working area */
257 if (target_alloc_working_area(target
, 172, &lpc2000_info
->iap_working_area
) != ERROR_OK
)
259 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
260 return ERROR_FLASH_OPERATION_FAILED
;
263 /* write IAP code to working area */
264 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
265 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
266 target
->type
->write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, jump_gate
);
269 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
270 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
271 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
273 /* command parameter table */
274 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 4 * 6, PARAM_OUT
);
275 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
276 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x4, param_table
[0]);
277 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x8, param_table
[1]);
278 target_buffer_set_u32(target
, mem_params
[0].value
+ 0xc, param_table
[2]);
279 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
280 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
282 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
283 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x8);
285 /* command result table */
286 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 4 * 3, PARAM_IN
);
288 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
289 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
291 /* IAP entry point */
292 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
293 buf_set_u32(reg_params
[2].value
, 0, 32, 0x7ffffff1);
296 init_reg_param(®_params
[3], "r13_svc", 32, PARAM_OUT
);
297 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xac);
300 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
301 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x4);
303 target
->type
->run_algorithm(target
, 2, mem_params
, 5, reg_params
, lpc2000_info
->iap_working_area
->address
, lpc2000_info
->iap_working_area
->address
+ 0x4, 10000, &armv4_5_info
);
305 status_code
= buf_get_u32(mem_params
[1].value
, 0, 32);
306 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
);
307 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 4);
309 destroy_mem_param(&mem_params
[0]);
310 destroy_mem_param(&mem_params
[1]);
312 destroy_reg_param(®_params
[0]);
313 destroy_reg_param(®_params
[1]);
314 destroy_reg_param(®_params
[2]);
315 destroy_reg_param(®_params
[3]);
316 destroy_reg_param(®_params
[4]);
321 int lpc2000_iap_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
328 if ((first
< 0) || (last
> bank
->num_sectors
))
329 return ERROR_FLASH_SECTOR_INVALID
;
331 for (i
= first
; i
<= last
; i
++)
333 /* check single sector */
334 param_table
[0] = param_table
[1] = i
;
335 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
339 case ERROR_FLASH_OPERATION_FAILED
:
340 return ERROR_FLASH_OPERATION_FAILED
;
341 case LPC2000_CMD_SUCCESS
:
342 bank
->sectors
[i
].is_erased
= 1;
344 case LPC2000_SECTOR_NOT_BLANK
:
345 bank
->sectors
[i
].is_erased
= 0;
347 case LPC2000_INVALID_SECTOR
:
348 bank
->sectors
[i
].is_erased
= 0;
351 return ERROR_FLASH_BUSY
;
354 LOG_ERROR("BUG: unknown LPC2000 status code");
362 /* flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
364 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
366 lpc2000_flash_bank_t
*lpc2000_info
;
370 LOG_WARNING("incomplete flash_bank lpc2000 configuration");
371 return ERROR_FLASH_BANK_INVALID
;
374 lpc2000_info
= malloc(sizeof(lpc2000_flash_bank_t
));
375 bank
->driver_priv
= lpc2000_info
;
377 if (strcmp(args
[6], "lpc2000_v1") == 0)
379 lpc2000_info
->variant
= 1;
380 lpc2000_info
->cmd51_dst_boundary
= 512;
381 lpc2000_info
->cmd51_can_256b
= 0;
382 lpc2000_info
->cmd51_can_8192b
= 1;
384 else if (strcmp(args
[6], "lpc2000_v2") == 0)
386 lpc2000_info
->variant
= 2;
387 lpc2000_info
->cmd51_dst_boundary
= 256;
388 lpc2000_info
->cmd51_can_256b
= 1;
389 lpc2000_info
->cmd51_can_8192b
= 0;
393 LOG_ERROR("unknown LPC2000 variant");
395 return ERROR_FLASH_BANK_INVALID
;
398 lpc2000_info
->iap_working_area
= NULL
;
399 lpc2000_info
->cclk
= strtoul(args
[7], NULL
, 0);
400 lpc2000_info
->calc_checksum
= 0;
401 lpc2000_build_sector_list(bank
);
405 if (strcmp(args
[8], "calc_checksum") == 0)
406 lpc2000_info
->calc_checksum
= 1;
412 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
)
414 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
419 if (bank
->target
->state
!= TARGET_HALTED
)
421 return ERROR_TARGET_NOT_HALTED
;
424 param_table
[0] = first
;
425 param_table
[1] = last
;
426 param_table
[2] = lpc2000_info
->cclk
;
428 /* Prepare sectors */
429 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
432 case ERROR_FLASH_OPERATION_FAILED
:
433 return ERROR_FLASH_OPERATION_FAILED
;
434 case LPC2000_CMD_SUCCESS
:
436 case LPC2000_INVALID_SECTOR
:
437 return ERROR_FLASH_SECTOR_INVALID
;
440 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
441 return ERROR_FLASH_OPERATION_FAILED
;
445 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
448 case ERROR_FLASH_OPERATION_FAILED
:
449 return ERROR_FLASH_OPERATION_FAILED
;
450 case LPC2000_CMD_SUCCESS
:
452 case LPC2000_INVALID_SECTOR
:
453 return ERROR_FLASH_SECTOR_INVALID
;
456 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
457 return ERROR_FLASH_OPERATION_FAILED
;
463 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
465 /* can't protect/unprotect on the lpc2000 */
469 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
471 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
472 target_t
*target
= bank
->target
;
473 u32 dst_min_alignment
;
474 u32 bytes_remaining
= count
;
475 u32 bytes_written
= 0;
476 int first_sector
= 0;
482 working_area_t
*download_area
;
483 int retval
= ERROR_OK
;
485 if (bank
->target
->state
!= TARGET_HALTED
)
487 return ERROR_TARGET_NOT_HALTED
;
490 /* allocate a working area */
491 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
)
493 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
494 return ERROR_FLASH_OPERATION_FAILED
;
497 if (offset
+ count
> bank
->size
)
499 retval
= ERROR_FLASH_DST_OUT_OF_BANK
;
500 goto cleanup_working_area
;
503 if (lpc2000_info
->cmd51_can_256b
)
504 dst_min_alignment
= 256;
506 dst_min_alignment
= 512;
508 if (offset
% dst_min_alignment
)
510 LOG_WARNING("offset 0x%x breaks required alignment 0x%x", offset
, dst_min_alignment
);
511 retval
= ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
512 goto cleanup_working_area
;
515 for (i
= 0; i
< bank
->num_sectors
; i
++)
517 if (offset
>= bank
->sectors
[i
].offset
)
519 if (offset
+ CEIL(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
523 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
525 /* check if exception vectors should be flashed */
526 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
530 for (i
= 0; i
< 8; i
++)
532 LOG_DEBUG("0x%2.2x: 0x%8.8x", i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
534 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
536 checksum
= 0 - checksum
;
537 LOG_DEBUG("checksum: 0x%8.8x", checksum
);
538 buf_set_u32(buffer
+ 0x14, 0, 32, checksum
);
541 while (bytes_remaining
> 0)
544 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
545 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
546 else if (bytes_remaining
>= 1024)
547 thisrun_bytes
= 1024;
548 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
553 /* Prepare sectors */
554 param_table
[0] = first_sector
;
555 param_table
[1] = last_sector
;
556 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
559 case ERROR_FLASH_OPERATION_FAILED
:
560 retval
= ERROR_FLASH_OPERATION_FAILED
;
562 case LPC2000_CMD_SUCCESS
:
564 case LPC2000_INVALID_SECTOR
:
565 retval
= ERROR_FLASH_SECTOR_INVALID
;
568 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
569 retval
= ERROR_FLASH_OPERATION_FAILED
;
573 /* Exit if error occured */
574 if (retval
!= ERROR_OK
)
575 goto cleanup_working_area
;
577 if (bytes_remaining
>= thisrun_bytes
)
579 if (retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
) != ERROR_OK
)
581 goto cleanup_working_area
;
586 u8
*last_buffer
= malloc(thisrun_bytes
);
588 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
589 for (i
= bytes_remaining
; i
< thisrun_bytes
; i
++)
590 last_buffer
[i
] = 0xff;
591 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
595 LOG_DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
598 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
599 param_table
[1] = download_area
->address
;
600 param_table
[2] = thisrun_bytes
;
601 param_table
[3] = lpc2000_info
->cclk
;
602 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
605 case ERROR_FLASH_OPERATION_FAILED
:
606 retval
= ERROR_FLASH_OPERATION_FAILED
;
608 case LPC2000_CMD_SUCCESS
:
610 case LPC2000_INVALID_SECTOR
:
611 retval
= ERROR_FLASH_SECTOR_INVALID
;
614 LOG_WARNING("lpc2000 returned %i", status_code
);
615 retval
= ERROR_FLASH_OPERATION_FAILED
;
619 /* Exit if error occured */
620 if (retval
!= ERROR_OK
)
621 goto cleanup_working_area
;
623 if (bytes_remaining
> thisrun_bytes
)
624 bytes_remaining
-= thisrun_bytes
;
627 bytes_written
+= thisrun_bytes
;
630 cleanup_working_area
:
631 target_free_working_area(target
, download_area
);
636 int lpc2000_probe(struct flash_bank_s
*bank
)
638 /* we can't probe on an lpc2000
639 * if this is an lpc2xxx, it has the configured flash
644 int lpc2000_erase_check(struct flash_bank_s
*bank
)
646 if (bank
->target
->state
!= TARGET_HALTED
)
648 return ERROR_TARGET_NOT_HALTED
;
651 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
654 int lpc2000_protect_check(struct flash_bank_s
*bank
)
656 /* sectors are always protected */
660 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
662 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
664 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info
->variant
, lpc2000_info
->cclk
);
669 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
678 return ERROR_COMMAND_SYNTAX_ERROR
;
681 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
684 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
688 if (bank
->target
->state
!= TARGET_HALTED
)
690 return ERROR_TARGET_NOT_HALTED
;
693 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
695 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
697 command_print(cmd_ctx
, "no sufficient working area specified, can't access LPC2000 IAP interface");
700 command_print(cmd_ctx
, "lpc2000 IAP returned status code %i", status_code
);
704 command_print(cmd_ctx
, "lpc2000 part id: 0x%8.8x", result_table
[0]);
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)