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

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)