- prepare OpenOCD for branching, created ./trunk/
[openocd.git] / src / flash / lpc2000.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.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 #include "lpc2000.h"
21
22 #include "flash.h"
23 #include "target.h"
24 #include "log.h"
25 #include "armv4_5.h"
26 #include "algorithm.h"
27 #include "binarybuffer.h"
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 /* flash programming support for Philips LPC2xxx devices
33 * currently supported devices:
34 * variant 1 (lpc2000_v1):
35 * - 2104|5|6
36 * - 2114|9
37 * - 2124|9
38 * - 2194
39 * - 2212|4
40 * - 2292|4
41 *
42 * variant 2 (lpc2000_v2):
43 * - 213x
44 * - 214x
45 */
46
47 int lpc2000_register_commands(struct command_context_s *cmd_ctx);
48 int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
49 int lpc2000_erase(struct flash_bank_s *bank, int first, int last);
50 int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last);
51 int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
52 int lpc2000_probe(struct flash_bank_s *bank);
53 int lpc2000_erase_check(struct flash_bank_s *bank);
54 int lpc2000_protect_check(struct flash_bank_s *bank);
55 int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size);
56
57 int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
58
59 flash_driver_t lpc2000_flash =
60 {
61 .name = "lpc2000",
62 .register_commands = lpc2000_register_commands,
63 .flash_bank_command = lpc2000_flash_bank_command,
64 .erase = lpc2000_erase,
65 .protect = lpc2000_protect,
66 .write = lpc2000_write,
67 .probe = lpc2000_probe,
68 .erase_check = lpc2000_erase_check,
69 .protect_check = lpc2000_protect_check,
70 .info = lpc2000_info
71 };
72
73 int lpc2000_register_commands(struct command_context_s *cmd_ctx)
74 {
75 command_t *lpc2000_cmd = register_command(cmd_ctx, NULL, "lpc2000", NULL, COMMAND_ANY, NULL);
76
77 register_command(cmd_ctx, lpc2000_cmd, "part_id", lpc2000_handle_part_id_command, COMMAND_EXEC,
78 "print part id of lpc2000 flash bank <num>");
79
80 return ERROR_OK;
81 }
82
83 int lpc2000_build_sector_list(struct flash_bank_s *bank)
84 {
85 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
86
87 if (lpc2000_info->variant == 1)
88 {
89 int i = 0;
90 u32 offset = 0;
91
92 /* variant 1 has different layout for 128kb and 256kb flashes */
93 if (bank->size == 128 * 1024)
94 {
95 bank->num_sectors = 16;
96 bank->sectors = malloc(sizeof(flash_sector_t) * 16);
97 for (i = 0; i < 16; i++)
98 {
99 bank->sectors[i].offset = offset;
100 bank->sectors[i].size = 8 * 1024;
101 offset += bank->sectors[i].size;
102 bank->sectors[i].is_erased = -1;
103 bank->sectors[i].is_protected = 1;
104 }
105 }
106 else if (bank->size == 256 * 1024)
107 {
108 bank->num_sectors = 18;
109 bank->sectors = malloc(sizeof(flash_sector_t) * 18);
110
111 for (i = 0; i < 8; i++)
112 {
113 bank->sectors[i].offset = offset;
114 bank->sectors[i].size = 8 * 1024;
115 offset += bank->sectors[i].size;
116 bank->sectors[i].is_erased = -1;
117 bank->sectors[i].is_protected = 1;
118 }
119 for (i = 8; i < 10; i++)
120 {
121 bank->sectors[i].offset = offset;
122 bank->sectors[i].size = 64 * 1024;
123 offset += bank->sectors[i].size;
124 bank->sectors[i].is_erased = -1;
125 bank->sectors[i].is_protected = 1;
126 }
127 for (i = 10; i < 18; i++)
128 {
129 bank->sectors[i].offset = offset;
130 bank->sectors[i].size = 8 * 1024;
131 offset += bank->sectors[i].size;
132 bank->sectors[i].is_erased = -1;
133 bank->sectors[i].is_protected = 1;
134 }
135 }
136 else
137 {
138 ERROR("BUG: unknown bank->size encountered");
139 exit(-1);
140 }
141 }
142 else if (lpc2000_info->variant == 2)
143 {
144 int num_sectors;
145 int i;
146 u32 offset = 0;
147
148 /* variant 2 has a uniform layout, only number of sectors differs */
149 switch (bank->size)
150 {
151 case 32 * 1024:
152 num_sectors = 8;
153 break;
154 case 64 * 1024:
155 num_sectors = 9;
156 break;
157 case 128 * 1024:
158 num_sectors = 11;
159 break;
160 case 256 * 1024:
161 num_sectors = 15;
162 break;
163 case 500 * 1024:
164 num_sectors = 27;
165 break;
166 default:
167 ERROR("BUG: unknown bank->size encountered");
168 exit(-1);
169 break;
170 }
171
172 bank->num_sectors = num_sectors;
173 bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
174
175 for (i = 0; i < num_sectors; i++)
176 {
177 if ((i >= 0) && (i < 8))
178 {
179 bank->sectors[i].offset = offset;
180 bank->sectors[i].size = 4 * 1024;
181 offset += bank->sectors[i].size;
182 bank->sectors[i].is_erased = -1;
183 bank->sectors[i].is_protected = 1;
184 }
185 if ((i >= 8) && (i < 22))
186 {
187 bank->sectors[i].offset = offset;
188 bank->sectors[i].size = 32 * 1024;
189 offset += bank->sectors[i].size;
190 bank->sectors[i].is_erased = -1;
191 bank->sectors[i].is_protected = 1;
192 }
193 if ((i >= 22) && (i < 27))
194 {
195 bank->sectors[i].offset = offset;
196 bank->sectors[i].size = 4 * 1024;
197 offset += bank->sectors[i].size;
198 bank->sectors[i].is_erased = -1;
199 bank->sectors[i].is_protected = 1;
200 }
201 }
202 }
203 else
204 {
205 ERROR("BUG: unknown lpc2000_info->variant encountered");
206 exit(-1);
207 }
208
209 return ERROR_OK;
210 }
211
212 /* call LPC2000 IAP function
213 * uses 172 bytes working area
214 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
215 * 0x8 to 0x1f: command parameter table
216 * 0x20 to 0x2b: command result table
217 * 0x2c to 0xac: stack (only 128b needed)
218 */
219 int lpc2000_iap_call(flash_bank_t *bank, int code, u32 param_table[5], u32 result_table[2])
220 {
221 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
222 target_t *target = lpc2000_info->target;
223 mem_param_t mem_params[2];
224 reg_param_t reg_params[5];
225 armv4_5_algorithm_t armv4_5_info;
226 u32 status_code;
227
228 /* regrab previously allocated working_area, or allocate a new one */
229 if (!lpc2000_info->iap_working_area)
230 {
231 u8 jump_gate[8];
232
233 /* make sure we have a working area */
234 if (target_alloc_working_area(target, 172, &lpc2000_info->iap_working_area) != ERROR_OK)
235 {
236 ERROR("no working area specified, can't write LPC2000 internal flash");
237 return ERROR_FLASH_OPERATION_FAILED;
238 }
239
240 /* write IAP code to working area */
241 buf_set_u32(jump_gate, 0, 32, ARMV4_5_BX(12));
242 buf_set_u32(jump_gate, 32, 32, 0xeafffffe);
243 target->type->write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, (u8*)jump_gate);
244 }
245
246 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
247 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
248 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
249
250 /* command parameter table */
251 init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 4 * 6, PARAM_OUT);
252 buf_set_u32(mem_params[0].value, 0, 32, code);
253 buf_set_u32(mem_params[0].value, 32, 32, param_table[0]);
254 buf_set_u32(mem_params[0].value, 64, 32, param_table[1]);
255 buf_set_u32(mem_params[0].value, 96, 32, param_table[2]);
256 buf_set_u32(mem_params[0].value, 128, 32, param_table[3]);
257 buf_set_u32(mem_params[0].value, 160, 32, param_table[4]);
258
259 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
260 buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x8);
261
262 /* command result table */
263 init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 4 * 3, PARAM_IN);
264
265 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
266 buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
267
268 /* IAP entry point */
269 init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
270 buf_set_u32(reg_params[2].value, 0, 32, 0x7ffffff1);
271
272 /* IAP stack */
273 init_reg_param(&reg_params[3], "r13_svc", 32, PARAM_OUT);
274 buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xac);
275
276 /* return address */
277 init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
278 buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x4);
279
280 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);
281
282 status_code = buf_get_u32(mem_params[1].value, 0, 32);
283 result_table[0] = buf_get_u32(mem_params[1].value, 32, 32);
284 result_table[1] = buf_get_u32(mem_params[1].value, 64, 32);
285
286 destroy_mem_param(&mem_params[0]);
287 destroy_mem_param(&mem_params[1]);
288
289 destroy_reg_param(&reg_params[0]);
290 destroy_reg_param(&reg_params[1]);
291 destroy_reg_param(&reg_params[2]);
292 destroy_reg_param(&reg_params[3]);
293 destroy_reg_param(&reg_params[4]);
294
295 return status_code;
296 }
297
298 int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int last)
299 {
300 u32 param_table[5];
301 u32 result_table[2];
302 int status_code;
303 int i;
304
305 if ((first < 0) || (last > bank->num_sectors))
306 return ERROR_FLASH_SECTOR_INVALID;
307
308 for (i = first; i <= last; i++)
309 {
310 /* check single sector */
311 param_table[0] = param_table[1] = i;
312 status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
313
314 switch (status_code)
315 {
316 case ERROR_FLASH_OPERATION_FAILED:
317 return ERROR_FLASH_OPERATION_FAILED;
318 case LPC2000_CMD_SUCCESS:
319 bank->sectors[i].is_erased = 1;
320 break;
321 case LPC2000_SECTOR_NOT_BLANK:
322 bank->sectors[i].is_erased = 0;
323 break;
324 case LPC2000_INVALID_SECTOR:
325 bank->sectors[i].is_erased = 0;
326 break;
327 case LPC2000_BUSY:
328 return ERROR_FLASH_BUSY;
329 break;
330 default:
331 ERROR("BUG: unknown LPC2000 status code");
332 exit(-1);
333 }
334 }
335
336 return ERROR_OK;
337 }
338
339 /* flash_bank lpc2000 <base> <size> 0 0 <lpc_variant> <target#> <cclk> [calc_checksum]
340 */
341 int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
342 {
343 lpc2000_flash_bank_t *lpc2000_info;
344
345 if (argc < 8)
346 {
347 WARNING("incomplete flash_bank lpc2000 configuration");
348 return ERROR_FLASH_BANK_INVALID;
349 }
350
351 lpc2000_info = malloc(sizeof(lpc2000_flash_bank_t));
352 bank->driver_priv = lpc2000_info;
353
354 if (strcmp(args[5], "lpc2000_v1") == 0)
355 {
356 lpc2000_info->variant = 1;
357 lpc2000_info->cmd51_dst_boundary = 512;
358 lpc2000_info->cmd51_can_256b = 0;
359 lpc2000_info->cmd51_can_8192b = 1;
360 }
361 else if (strcmp(args[5], "lpc2000_v2") == 0)
362 {
363 lpc2000_info->variant = 2;
364 lpc2000_info->cmd51_dst_boundary = 256;
365 lpc2000_info->cmd51_can_256b = 1;
366 lpc2000_info->cmd51_can_8192b = 0;
367 }
368 else
369 {
370 ERROR("unknown LPC2000 variant");
371 free(lpc2000_info);
372 return ERROR_FLASH_BANK_INVALID;
373 }
374
375 lpc2000_info->target = get_target_by_num(strtoul(args[6], NULL, 0));
376 if (!lpc2000_info->target)
377 {
378 ERROR("no target '%s' configured", args[6]);
379 exit(-1);
380 }
381 lpc2000_info->iap_working_area = NULL;
382 lpc2000_info->cclk = strtoul(args[7], NULL, 0);
383 lpc2000_info->calc_checksum = 0;
384 lpc2000_build_sector_list(bank);
385
386
387 if (argc >= 9)
388 {
389 if (strcmp(args[8], "calc_checksum") == 0)
390 lpc2000_info->calc_checksum = 1;
391 }
392
393 return ERROR_OK;
394 }
395
396 int lpc2000_erase(struct flash_bank_s *bank, int first, int last)
397 {
398 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
399 u32 param_table[5];
400 u32 result_table[2];
401 int status_code;
402
403 if (lpc2000_info->target->state != TARGET_HALTED)
404 {
405 return ERROR_TARGET_NOT_HALTED;
406 }
407
408 if ((first < 0) || (last < first) || (last >= bank->num_sectors))
409 {
410 return ERROR_FLASH_SECTOR_INVALID;
411 }
412
413 param_table[0] = first;
414 param_table[1] = last;
415 param_table[2] = lpc2000_info->cclk;
416
417 /* Prepare sectors */
418 status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
419 switch (status_code)
420 {
421 case ERROR_FLASH_OPERATION_FAILED:
422 return ERROR_FLASH_OPERATION_FAILED;
423 case LPC2000_CMD_SUCCESS:
424 break;
425 case LPC2000_INVALID_SECTOR:
426 return ERROR_FLASH_SECTOR_INVALID;
427 break;
428 default:
429 WARNING("lpc2000 prepare sectors returned %i", status_code);
430 return ERROR_FLASH_OPERATION_FAILED;
431 }
432
433 /* Erase sectors */
434 status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
435 switch (status_code)
436 {
437 case ERROR_FLASH_OPERATION_FAILED:
438 return ERROR_FLASH_OPERATION_FAILED;
439 case LPC2000_CMD_SUCCESS:
440 break;
441 case LPC2000_INVALID_SECTOR:
442 return ERROR_FLASH_SECTOR_INVALID;
443 break;
444 default:
445 WARNING("lpc2000 erase sectors returned %i", status_code);
446 return ERROR_FLASH_OPERATION_FAILED;
447 }
448
449 return ERROR_OK;
450 }
451
452 int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last)
453 {
454 /* can't protect/unprotect on the lpc2000 */
455 return ERROR_OK;
456 }
457
458 int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
459 {
460 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
461 target_t *target = lpc2000_info->target;
462 u32 dst_min_alignment;
463 u32 bytes_remaining = count;
464 u32 bytes_written = 0;
465 int first_sector = 0;
466 int last_sector = 0;
467 u32 param_table[5];
468 u32 result_table[2];
469 int status_code;
470 int i;
471 working_area_t *download_area;
472
473 if (lpc2000_info->target->state != TARGET_HALTED)
474 {
475 return ERROR_TARGET_NOT_HALTED;
476 }
477
478 /* allocate a working area */
479 if (target_alloc_working_area(target, 4096, &download_area) != ERROR_OK)
480 {
481 ERROR("no working area specified, can't write LPC2000 internal flash");
482 return ERROR_FLASH_OPERATION_FAILED;
483 }
484
485 if (offset + count > bank->size)
486 return ERROR_FLASH_DST_OUT_OF_BANK;
487
488 if (lpc2000_info->cmd51_can_256b)
489 dst_min_alignment = 256;
490 else
491 dst_min_alignment = 512;
492
493 if (offset % dst_min_alignment)
494 {
495 WARNING("offset 0x%x breaks required alignment 0x%x", offset, dst_min_alignment);
496 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
497 }
498
499 for (i = 0; i < bank->num_sectors; i++)
500 {
501 if (offset >= bank->sectors[i].offset)
502 first_sector = i;
503 if (offset + CEIL(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset)
504 last_sector = i;
505 }
506
507 DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
508
509 /* check if exception vectors should be flashed */
510 if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
511 {
512 u32 checksum = 0;
513 int i = 0;
514 for (i = 0; i < 8; i++)
515 {
516 DEBUG("0x%2.2x: 0x%8.8x", i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
517 if (i != 5)
518 checksum += buf_get_u32(buffer + (i * 4), 0, 32);
519 }
520 checksum = 0 - checksum;
521 DEBUG("checksum: 0x%8.8x", checksum);
522 buf_set_u32(buffer + 0x14, 0, 32, checksum);
523 }
524
525 while (bytes_remaining > 0)
526 {
527 u32 thisrun_bytes;
528 if (bytes_remaining >= 4096)
529 thisrun_bytes = 4096;
530 else if (bytes_remaining >= 1024)
531 thisrun_bytes = 1024;
532 else if ((bytes_remaining >= 512) || (!lpc2000_info->cmd51_can_256b))
533 thisrun_bytes = 512;
534 else
535 thisrun_bytes = 256;
536
537 /* Prepare sectors */
538 param_table[0] = first_sector;
539 param_table[1] = last_sector;
540 status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
541 switch (status_code)
542 {
543 case ERROR_FLASH_OPERATION_FAILED:
544 return ERROR_FLASH_OPERATION_FAILED;
545 case LPC2000_CMD_SUCCESS:
546 break;
547 case LPC2000_INVALID_SECTOR:
548 return ERROR_FLASH_SECTOR_INVALID;
549 break;
550 default:
551 WARNING("lpc2000 prepare sectors returned %i", status_code);
552 return ERROR_FLASH_OPERATION_FAILED;
553 }
554
555 if (bytes_remaining >= thisrun_bytes)
556 {
557 if (target_write_buffer(lpc2000_info->target, download_area->address, thisrun_bytes, buffer + bytes_written) != ERROR_OK)
558 {
559 target_free_working_area(target, download_area);
560 return ERROR_FLASH_OPERATION_FAILED;
561 }
562 }
563 else
564 {
565 u8 *last_buffer = malloc(thisrun_bytes);
566 int i;
567 memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
568 for (i = bytes_remaining; i < thisrun_bytes; i++)
569 last_buffer[i] = 0xff;
570 target_write_buffer(lpc2000_info->target, download_area->address, thisrun_bytes, last_buffer);
571 free(last_buffer);
572 }
573
574 DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes, bank->base + offset + bytes_written);
575
576 /* Write data */
577 param_table[0] = bank->base + offset + bytes_written;
578 param_table[1] = download_area->address;
579 param_table[2] = thisrun_bytes;
580 param_table[3] = lpc2000_info->cclk;
581 status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
582 switch (status_code)
583 {
584 case ERROR_FLASH_OPERATION_FAILED:
585 return ERROR_FLASH_OPERATION_FAILED;
586 case LPC2000_CMD_SUCCESS:
587 break;
588 case LPC2000_INVALID_SECTOR:
589 return ERROR_FLASH_SECTOR_INVALID;
590 break;
591 default:
592 WARNING("lpc2000 returned %i", status_code);
593 return ERROR_FLASH_OPERATION_FAILED;
594 }
595
596 if (bytes_remaining > thisrun_bytes)
597 bytes_remaining -= thisrun_bytes;
598 else
599 bytes_remaining = 0;
600 bytes_written += thisrun_bytes;
601 }
602
603 target_free_working_area(target, download_area);
604
605 return ERROR_OK;
606 }
607
608 int lpc2000_probe(struct flash_bank_s *bank)
609 {
610 /* we can't probe on an lpc2000
611 * if this is an lpc2xxx, it has the configured flash
612 */
613 return ERROR_OK;
614 }
615
616 int lpc2000_erase_check(struct flash_bank_s *bank)
617 {
618 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
619
620 if (lpc2000_info->target->state != TARGET_HALTED)
621 {
622 return ERROR_TARGET_NOT_HALTED;
623 }
624
625 return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1);
626 }
627
628 int lpc2000_protect_check(struct flash_bank_s *bank)
629 {
630 /* sectors are always protected */
631 return ERROR_OK;
632 }
633
634 int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size)
635 {
636 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
637
638 snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info->variant, lpc2000_info->cclk);
639
640 return ERROR_OK;
641 }
642
643 int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
644 {
645 flash_bank_t *bank;
646 u32 param_table[5];
647 u32 result_table[2];
648 int status_code;
649 lpc2000_flash_bank_t *lpc2000_info;
650
651 if (argc < 1)
652 {
653 command_print(cmd_ctx, "usage: lpc2000 part_id <num>");
654 return ERROR_OK;
655 }
656
657 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
658 if (!bank)
659 {
660 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
661 return ERROR_OK;
662 }
663
664 lpc2000_info = bank->driver_priv;
665 if (lpc2000_info->target->state != TARGET_HALTED)
666 {
667 return ERROR_TARGET_NOT_HALTED;
668 }
669
670 if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0)
671 {
672 if (status_code == ERROR_FLASH_OPERATION_FAILED)
673 {
674 command_print(cmd_ctx, "no sufficient working area specified, can't access LPC2000 IAP interface");
675 return ERROR_OK;
676 }
677 command_print(cmd_ctx, "lpc2000 IAP returned status code %i", status_code);
678 }
679 else
680 {
681 command_print(cmd_ctx, "lpc2000 part id: 0x%8.8x", result_table[0]);
682 }
683
684 return ERROR_OK;
685 }

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)