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

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)