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

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)