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

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)