Laurentiu Cocanu - memory read/write and exit() error path fixes
[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 LOG_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 LOG_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 LOG_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 int retval;
245 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
246 target_t *target = bank->target;
247 mem_param_t mem_params[2];
248 reg_param_t reg_params[5];
249 armv4_5_algorithm_t armv4_5_info;
250 u32 status_code;
251
252 /* regrab previously allocated working_area, or allocate a new one */
253 if (!lpc2000_info->iap_working_area)
254 {
255 u8 jump_gate[8];
256
257 /* make sure we have a working area */
258 if (target_alloc_working_area(target, 172, &lpc2000_info->iap_working_area) != ERROR_OK)
259 {
260 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
261 return ERROR_FLASH_OPERATION_FAILED;
262 }
263
264 /* write IAP code to working area */
265 target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
266 target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
267 if((retval = target->type->write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK)
268 {
269 return retval;
270 }
271 }
272
273 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
274 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
275 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
276
277 /* command parameter table */
278 init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 4 * 6, PARAM_OUT);
279 target_buffer_set_u32(target, mem_params[0].value, code);
280 target_buffer_set_u32(target, mem_params[0].value + 0x4, param_table[0]);
281 target_buffer_set_u32(target, mem_params[0].value + 0x8, param_table[1]);
282 target_buffer_set_u32(target, mem_params[0].value + 0xc, param_table[2]);
283 target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
284 target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);
285
286 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
287 buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x8);
288
289 /* command result table */
290 init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 4 * 3, PARAM_IN);
291
292 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
293 buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
294
295 /* IAP entry point */
296 init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
297 buf_set_u32(reg_params[2].value, 0, 32, 0x7ffffff1);
298
299 /* IAP stack */
300 init_reg_param(&reg_params[3], "r13_svc", 32, PARAM_OUT);
301 buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xac);
302
303 /* return address */
304 init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
305 buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x4);
306
307 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);
308
309 status_code = buf_get_u32(mem_params[1].value, 0, 32);
310 result_table[0] = target_buffer_get_u32(target, mem_params[1].value);
311 result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 4);
312
313 destroy_mem_param(&mem_params[0]);
314 destroy_mem_param(&mem_params[1]);
315
316 destroy_reg_param(&reg_params[0]);
317 destroy_reg_param(&reg_params[1]);
318 destroy_reg_param(&reg_params[2]);
319 destroy_reg_param(&reg_params[3]);
320 destroy_reg_param(&reg_params[4]);
321
322 return status_code;
323 }
324
325 int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int last)
326 {
327 u32 param_table[5];
328 u32 result_table[2];
329 int status_code;
330 int i;
331
332 if ((first < 0) || (last > bank->num_sectors))
333 return ERROR_FLASH_SECTOR_INVALID;
334
335 for (i = first; i <= last; i++)
336 {
337 /* check single sector */
338 param_table[0] = param_table[1] = i;
339 status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
340
341 switch (status_code)
342 {
343 case ERROR_FLASH_OPERATION_FAILED:
344 return ERROR_FLASH_OPERATION_FAILED;
345 case LPC2000_CMD_SUCCESS:
346 bank->sectors[i].is_erased = 1;
347 break;
348 case LPC2000_SECTOR_NOT_BLANK:
349 bank->sectors[i].is_erased = 0;
350 break;
351 case LPC2000_INVALID_SECTOR:
352 bank->sectors[i].is_erased = 0;
353 break;
354 case LPC2000_BUSY:
355 return ERROR_FLASH_BUSY;
356 break;
357 default:
358 LOG_ERROR("BUG: unknown LPC2000 status code");
359 exit(-1);
360 }
361 }
362
363 return ERROR_OK;
364 }
365
366 /* flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
367 */
368 int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
369 {
370 lpc2000_flash_bank_t *lpc2000_info;
371
372 if (argc < 8)
373 {
374 LOG_WARNING("incomplete flash_bank lpc2000 configuration");
375 return ERROR_FLASH_BANK_INVALID;
376 }
377
378 lpc2000_info = malloc(sizeof(lpc2000_flash_bank_t));
379 bank->driver_priv = lpc2000_info;
380
381 if (strcmp(args[6], "lpc2000_v1") == 0)
382 {
383 lpc2000_info->variant = 1;
384 lpc2000_info->cmd51_dst_boundary = 512;
385 lpc2000_info->cmd51_can_256b = 0;
386 lpc2000_info->cmd51_can_8192b = 1;
387 }
388 else if (strcmp(args[6], "lpc2000_v2") == 0)
389 {
390 lpc2000_info->variant = 2;
391 lpc2000_info->cmd51_dst_boundary = 256;
392 lpc2000_info->cmd51_can_256b = 1;
393 lpc2000_info->cmd51_can_8192b = 0;
394 }
395 else
396 {
397 LOG_ERROR("unknown LPC2000 variant");
398 free(lpc2000_info);
399 return ERROR_FLASH_BANK_INVALID;
400 }
401
402 lpc2000_info->iap_working_area = NULL;
403 lpc2000_info->cclk = strtoul(args[7], NULL, 0);
404 lpc2000_info->calc_checksum = 0;
405 lpc2000_build_sector_list(bank);
406
407 if (argc >= 9)
408 {
409 if (strcmp(args[8], "calc_checksum") == 0)
410 lpc2000_info->calc_checksum = 1;
411 }
412
413 return ERROR_OK;
414 }
415
416 int lpc2000_erase(struct flash_bank_s *bank, int first, int last)
417 {
418 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
419 u32 param_table[5];
420 u32 result_table[2];
421 int status_code;
422
423 if (bank->target->state != TARGET_HALTED)
424 {
425 LOG_ERROR("Target not halted");
426 return ERROR_TARGET_NOT_HALTED;
427 }
428
429 param_table[0] = first;
430 param_table[1] = last;
431 param_table[2] = lpc2000_info->cclk;
432
433 /* Prepare sectors */
434 status_code = lpc2000_iap_call(bank, 50, 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 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
446 return ERROR_FLASH_OPERATION_FAILED;
447 }
448
449 /* Erase sectors */
450 status_code = lpc2000_iap_call(bank, 52, param_table, result_table);
451 switch (status_code)
452 {
453 case ERROR_FLASH_OPERATION_FAILED:
454 return ERROR_FLASH_OPERATION_FAILED;
455 case LPC2000_CMD_SUCCESS:
456 break;
457 case LPC2000_INVALID_SECTOR:
458 return ERROR_FLASH_SECTOR_INVALID;
459 break;
460 default:
461 LOG_WARNING("lpc2000 erase sectors returned %i", status_code);
462 return ERROR_FLASH_OPERATION_FAILED;
463 }
464
465 return ERROR_OK;
466 }
467
468 int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last)
469 {
470 /* can't protect/unprotect on the lpc2000 */
471 return ERROR_OK;
472 }
473
474 int lpc2000_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
475 {
476 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
477 target_t *target = bank->target;
478 u32 dst_min_alignment;
479 u32 bytes_remaining = count;
480 u32 bytes_written = 0;
481 int first_sector = 0;
482 int last_sector = 0;
483 u32 param_table[5];
484 u32 result_table[2];
485 int status_code;
486 int i;
487 working_area_t *download_area;
488 int retval = ERROR_OK;
489
490 if (bank->target->state != TARGET_HALTED)
491 {
492 LOG_ERROR("Target not halted");
493 return ERROR_TARGET_NOT_HALTED;
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 LOG_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 LOG_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 LOG_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 LOG_DEBUG("checksum: 0x%8.8x", checksum);
533 buf_set_u32(buffer + 0x14, 0, 32, checksum);
534 }
535
536 /* allocate a working area */
537 if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK)
538 {
539 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
540 return ERROR_FLASH_OPERATION_FAILED;
541 }
542
543 while (bytes_remaining > 0)
544 {
545 u32 thisrun_bytes;
546 if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
547 thisrun_bytes = lpc2000_info->cmd51_max_buffer;
548 else if (bytes_remaining >= 1024)
549 thisrun_bytes = 1024;
550 else if ((bytes_remaining >= 512) || (!lpc2000_info->cmd51_can_256b))
551 thisrun_bytes = 512;
552 else
553 thisrun_bytes = 256;
554
555 /* Prepare sectors */
556 param_table[0] = first_sector;
557 param_table[1] = last_sector;
558 status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
559 switch (status_code)
560 {
561 case ERROR_FLASH_OPERATION_FAILED:
562 retval = ERROR_FLASH_OPERATION_FAILED;
563 break;
564 case LPC2000_CMD_SUCCESS:
565 break;
566 case LPC2000_INVALID_SECTOR:
567 retval = ERROR_FLASH_SECTOR_INVALID;
568 break;
569 default:
570 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
571 retval = ERROR_FLASH_OPERATION_FAILED;
572 break;
573 }
574
575 /* Exit if error occured */
576 if (retval != ERROR_OK)
577 break;
578
579 if (bytes_remaining >= thisrun_bytes)
580 {
581 if ((retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written)) != ERROR_OK)
582 {
583 retval = ERROR_FLASH_OPERATION_FAILED;
584 break;
585 }
586 }
587 else
588 {
589 u8 *last_buffer = malloc(thisrun_bytes);
590 int i;
591 memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
592 for (i = bytes_remaining; i < thisrun_bytes; i++)
593 last_buffer[i] = 0xff;
594 target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer);
595 free(last_buffer);
596 }
597
598 LOG_DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes, bank->base + offset + bytes_written);
599
600 /* Write data */
601 param_table[0] = bank->base + offset + bytes_written;
602 param_table[1] = download_area->address;
603 param_table[2] = thisrun_bytes;
604 param_table[3] = lpc2000_info->cclk;
605 status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
606 switch (status_code)
607 {
608 case ERROR_FLASH_OPERATION_FAILED:
609 retval = ERROR_FLASH_OPERATION_FAILED;
610 break;
611 case LPC2000_CMD_SUCCESS:
612 break;
613 case LPC2000_INVALID_SECTOR:
614 retval = ERROR_FLASH_SECTOR_INVALID;
615 break;
616 default:
617 LOG_WARNING("lpc2000 returned %i", status_code);
618 retval = ERROR_FLASH_OPERATION_FAILED;
619 break;
620 }
621
622 /* Exit if error occured */
623 if (retval != ERROR_OK)
624 break;
625
626 if (bytes_remaining > thisrun_bytes)
627 bytes_remaining -= thisrun_bytes;
628 else
629 bytes_remaining = 0;
630 bytes_written += thisrun_bytes;
631 }
632
633 target_free_working_area(target, download_area);
634
635 return retval;
636 }
637
638 int lpc2000_probe(struct flash_bank_s *bank)
639 {
640 /* we can't probe on an lpc2000
641 * if this is an lpc2xxx, it has the configured flash
642 */
643 return ERROR_OK;
644 }
645
646 int lpc2000_erase_check(struct flash_bank_s *bank)
647 {
648 if (bank->target->state != TARGET_HALTED)
649 {
650 LOG_ERROR("Target not halted");
651 return ERROR_TARGET_NOT_HALTED;
652 }
653
654 return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1);
655 }
656
657 int lpc2000_protect_check(struct flash_bank_s *bank)
658 {
659 /* sectors are always protected */
660 return ERROR_OK;
661 }
662
663 int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size)
664 {
665 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
666
667 snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info->variant, lpc2000_info->cclk);
668
669 return ERROR_OK;
670 }
671
672 int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
673 {
674 flash_bank_t *bank;
675 u32 param_table[5];
676 u32 result_table[2];
677 int status_code;
678
679 if (argc < 1)
680 {
681 return ERROR_COMMAND_SYNTAX_ERROR;
682 }
683
684 bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
685 if (!bank)
686 {
687 command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
688 return ERROR_OK;
689 }
690
691 if (bank->target->state != TARGET_HALTED)
692 {
693 LOG_ERROR("Target not halted");
694 return ERROR_TARGET_NOT_HALTED;
695 }
696
697 if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0)
698 {
699 if (status_code == ERROR_FLASH_OPERATION_FAILED)
700 {
701 command_print(cmd_ctx, "no sufficient working area specified, can't access LPC2000 IAP interface");
702 return ERROR_OK;
703 }
704 command_print(cmd_ctx, "lpc2000 IAP returned status code %i", status_code);
705 }
706 else
707 {
708 command_print(cmd_ctx, "lpc2000 part id: 0x%8.8x", result_table[0]);
709 }
710
711 return ERROR_OK;
712 }

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)