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

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)