Improve lpc2000.c command argument parsing.
[openocd.git] / src / flash / lpc2000.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius *
6 * didele.deze@gmail.com *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "lpc2000.h"
29 #include "armv4_5.h"
30 #include "armv7m.h"
31 #include "binarybuffer.h"
32
33
34 /* flash programming support for NXP LPC17xx and LPC2xxx devices
35 * currently supported devices:
36 * variant 1 (lpc2000_v1):
37 * - 2104 | 5 | 6
38 * - 2114 | 9
39 * - 2124 | 9
40 * - 2194
41 * - 2212 | 4
42 * - 2292 | 4
43 *
44 * variant 2 (lpc2000_v2):
45 * - 213x
46 * - 214x
47 * - 2101 | 2 | 3
48 * - 2364 | 6 | 8
49 * - 2378
50 *
51 * lpc1700:
52 * - 175x
53 * - 176x (tested with LPC1768)
54 */
55
56 static int lpc2000_register_commands(struct command_context_s *cmd_ctx);
57 static int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
58 static int lpc2000_erase(struct flash_bank_s *bank, int first, int last);
59 static int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last);
60 static int lpc2000_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count);
61 static int lpc2000_probe(struct flash_bank_s *bank);
62 static int lpc2000_erase_check(struct flash_bank_s *bank);
63 static int lpc2000_protect_check(struct flash_bank_s *bank);
64 static int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size);
65
66 static int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
67
68 flash_driver_t lpc2000_flash =
69 {
70 .name = "lpc2000",
71 .register_commands = lpc2000_register_commands,
72 .flash_bank_command = lpc2000_flash_bank_command,
73 .erase = lpc2000_erase,
74 .protect = lpc2000_protect,
75 .write = lpc2000_write,
76 .probe = lpc2000_probe,
77 .auto_probe = lpc2000_probe,
78 .erase_check = lpc2000_erase_check,
79 .protect_check = lpc2000_protect_check,
80 .info = lpc2000_info
81 };
82
83 static int lpc2000_register_commands(struct command_context_s *cmd_ctx)
84 {
85 command_t *lpc2000_cmd = register_command(cmd_ctx, NULL, "lpc2000", NULL, COMMAND_ANY, NULL);
86
87 register_command(cmd_ctx, lpc2000_cmd, "part_id", lpc2000_handle_part_id_command, COMMAND_EXEC,
88 "print part id of lpc2000 flash bank <num>");
89
90 return ERROR_OK;
91 }
92
93 static int lpc2000_build_sector_list(struct flash_bank_s *bank)
94 {
95 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
96 int i;
97 uint32_t offset = 0;
98
99 /* default to a 4096 write buffer */
100 lpc2000_info->cmd51_max_buffer = 4096;
101
102 if (lpc2000_info->variant == lpc2000_v1)
103 {
104 /* variant 1 has different layout for 128kb and 256kb flashes */
105 if (bank->size == 128 * 1024)
106 {
107 bank->num_sectors = 16;
108 bank->sectors = malloc(sizeof(flash_sector_t) * 16);
109 for (i = 0; i < 16; i++)
110 {
111 bank->sectors[i].offset = offset;
112 bank->sectors[i].size = 8 * 1024;
113 offset += bank->sectors[i].size;
114 bank->sectors[i].is_erased = -1;
115 bank->sectors[i].is_protected = 1;
116 }
117 }
118 else if (bank->size == 256 * 1024)
119 {
120 bank->num_sectors = 18;
121 bank->sectors = malloc(sizeof(flash_sector_t) * 18);
122
123 for (i = 0; i < 8; i++)
124 {
125 bank->sectors[i].offset = offset;
126 bank->sectors[i].size = 8 * 1024;
127 offset += bank->sectors[i].size;
128 bank->sectors[i].is_erased = -1;
129 bank->sectors[i].is_protected = 1;
130 }
131 for (i = 8; i < 10; i++)
132 {
133 bank->sectors[i].offset = offset;
134 bank->sectors[i].size = 64 * 1024;
135 offset += bank->sectors[i].size;
136 bank->sectors[i].is_erased = -1;
137 bank->sectors[i].is_protected = 1;
138 }
139 for (i = 10; i < 18; i++)
140 {
141 bank->sectors[i].offset = offset;
142 bank->sectors[i].size = 8 * 1024;
143 offset += bank->sectors[i].size;
144 bank->sectors[i].is_erased = -1;
145 bank->sectors[i].is_protected = 1;
146 }
147 }
148 else
149 {
150 LOG_ERROR("BUG: unknown bank->size encountered");
151 exit(-1);
152 }
153 }
154 else if (lpc2000_info->variant == lpc2000_v2)
155 {
156 /* variant 2 has a uniform layout, only number of sectors differs */
157 switch (bank->size)
158 {
159 case 4 * 1024:
160 lpc2000_info->cmd51_max_buffer = 1024;
161 bank->num_sectors = 1;
162 break;
163 case 8 * 1024:
164 lpc2000_info->cmd51_max_buffer = 1024;
165 bank->num_sectors = 2;
166 break;
167 case 16 * 1024:
168 bank->num_sectors = 4;
169 break;
170 case 32 * 1024:
171 bank->num_sectors = 8;
172 break;
173 case 64 * 1024:
174 bank->num_sectors = 9;
175 break;
176 case 128 * 1024:
177 bank->num_sectors = 11;
178 break;
179 case 256 * 1024:
180 bank->num_sectors = 15;
181 break;
182 case 512 * 1024:
183 case 500 * 1024:
184 bank->num_sectors = 27;
185 break;
186 default:
187 LOG_ERROR("BUG: unknown bank->size encountered");
188 exit(-1);
189 break;
190 }
191
192 bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
193
194 for (i = 0; i < bank->num_sectors; i++)
195 {
196 if ((i >= 0) && (i < 8))
197 {
198 bank->sectors[i].offset = offset;
199 bank->sectors[i].size = 4 * 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 >= 8) && (i < 22))
205 {
206 bank->sectors[i].offset = offset;
207 bank->sectors[i].size = 32 * 1024;
208 offset += bank->sectors[i].size;
209 bank->sectors[i].is_erased = -1;
210 bank->sectors[i].is_protected = 1;
211 }
212 if ((i >= 22) && (i < 27))
213 {
214 bank->sectors[i].offset = offset;
215 bank->sectors[i].size = 4 * 1024;
216 offset += bank->sectors[i].size;
217 bank->sectors[i].is_erased = -1;
218 bank->sectors[i].is_protected = 1;
219 }
220 }
221 }
222 else if (lpc2000_info->variant == lpc1700)
223 {
224 switch(bank->size)
225 {
226 case 32 * 1024:
227 bank->num_sectors = 8;
228 break;
229 case 64 * 1024:
230 bank->num_sectors = 16;
231 break;
232 case 128 * 1024:
233 bank->num_sectors = 18;
234 break;
235 case 256 * 1024:
236 bank->num_sectors = 22;
237 break;
238 case 512 * 1024:
239 bank->num_sectors = 30;
240 break;
241 default:
242 LOG_ERROR("BUG: unknown bank->size encountered");
243 exit(-1);
244 }
245
246 bank->sectors = malloc(sizeof(flash_sector_t) * bank->num_sectors);
247
248 for(i = 0; i < bank->num_sectors; i++)
249 {
250 bank->sectors[i].offset = offset;
251 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
252 bank->sectors[i].size = (i < 16)? 4 * 1024 : 32 * 1024;
253 offset += bank->sectors[i].size;
254 bank->sectors[i].is_erased = -1;
255 bank->sectors[i].is_protected = 1;
256 }
257 }
258 else
259 {
260 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
261 exit(-1);
262 }
263
264 return ERROR_OK;
265 }
266
267 /* call LPC1700/LPC2000 IAP function
268 * uses 180 bytes working area
269 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
270 * 0x8 to 0x1f: command parameter table (1+5 words)
271 * 0x20 to 0x33: command result table (1+4 words)
272 * 0x34 to 0xb3: stack (only 128b needed)
273 */
274 static int lpc2000_iap_call(flash_bank_t *bank, int code, uint32_t param_table[5], uint32_t result_table[4])
275 {
276 int retval;
277 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
278 target_t *target = bank->target;
279 mem_param_t mem_params[2];
280 reg_param_t reg_params[5];
281 armv4_5_algorithm_t armv4_5_info; /* for LPC2000 */
282 armv7m_algorithm_t armv7m_info; /* for LPC1700 */
283 uint32_t status_code;
284 uint32_t iap_entry_point = 0; /* to make compiler happier */
285
286 /* regrab previously allocated working_area, or allocate a new one */
287 if (!lpc2000_info->iap_working_area)
288 {
289 uint8_t jump_gate[8];
290
291 /* make sure we have a working area */
292 if (target_alloc_working_area(target, 180, &lpc2000_info->iap_working_area) != ERROR_OK)
293 {
294 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
295 return ERROR_FLASH_OPERATION_FAILED;
296 }
297
298 /* write IAP code to working area */
299 switch(lpc2000_info->variant)
300 {
301 case lpc1700:
302 target_buffer_set_u32(target, jump_gate, ARMV7M_T_BX(12));
303 target_buffer_set_u32(target, jump_gate + 4, ARMV7M_T_B(0xfffffe));
304 break;
305 case lpc2000_v1:
306 case lpc2000_v2:
307 target_buffer_set_u32(target, jump_gate, ARMV4_5_BX(12));
308 target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0));
309 break;
310 default:
311 LOG_ERROR("BUG: unknown bank->size encountered");
312 exit(-1);
313 }
314
315 if ((retval = target_write_memory(target, lpc2000_info->iap_working_area->address, 4, 2, jump_gate)) != ERROR_OK)
316 {
317 LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", lpc2000_info->iap_working_area->address);
318 return retval;
319 }
320 }
321
322 switch(lpc2000_info->variant)
323 {
324 case lpc1700:
325 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
326 armv7m_info.core_mode = ARMV7M_MODE_ANY;
327 iap_entry_point = 0x1fff1ff1;
328 break;
329 case lpc2000_v1:
330 case lpc2000_v2:
331 armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
332 armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
333 armv4_5_info.core_state = ARMV4_5_STATE_ARM;
334 iap_entry_point = 0x7ffffff1;
335 break;
336 default:
337 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
338 exit(-1);
339 }
340
341 /* command parameter table */
342 init_mem_param(&mem_params[0], lpc2000_info->iap_working_area->address + 8, 6 * 4, PARAM_OUT);
343 target_buffer_set_u32(target, mem_params[0].value, code);
344 target_buffer_set_u32(target, mem_params[0].value + 0x04, param_table[0]);
345 target_buffer_set_u32(target, mem_params[0].value + 0x08, param_table[1]);
346 target_buffer_set_u32(target, mem_params[0].value + 0x0c, param_table[2]);
347 target_buffer_set_u32(target, mem_params[0].value + 0x10, param_table[3]);
348 target_buffer_set_u32(target, mem_params[0].value + 0x14, param_table[4]);
349
350 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
351 buf_set_u32(reg_params[0].value, 0, 32, lpc2000_info->iap_working_area->address + 0x08);
352
353 /* command result table */
354 init_mem_param(&mem_params[1], lpc2000_info->iap_working_area->address + 0x20, 5 * 4, PARAM_IN);
355
356 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
357 buf_set_u32(reg_params[1].value, 0, 32, lpc2000_info->iap_working_area->address + 0x20);
358
359 /* IAP entry point */
360 init_reg_param(&reg_params[2], "r12", 32, PARAM_OUT);
361 buf_set_u32(reg_params[2].value, 0, 32, iap_entry_point);
362
363 switch(lpc2000_info->variant)
364 {
365 case lpc1700:
366 /* IAP stack */
367 init_reg_param(&reg_params[3], "sp", 32, PARAM_OUT);
368 buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
369
370 /* return address */
371 init_reg_param(&reg_params[4], "lr", 32, PARAM_OUT);
372 buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
373
374 target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv7m_info);
375 break;
376 case lpc2000_v1:
377 case lpc2000_v2:
378 /* IAP stack */
379 init_reg_param(&reg_params[3], "r13_svc", 32, PARAM_OUT);
380 buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4);
381
382 /* return address */
383 init_reg_param(&reg_params[4], "lr_svc", 32, PARAM_OUT);
384 buf_set_u32(reg_params[4].value, 0, 32, lpc2000_info->iap_working_area->address + 0x04);
385
386 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);
387 break;
388 default:
389 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
390 exit(-1);
391 }
392
393
394 status_code = target_buffer_get_u32(target, mem_params[1].value);
395 result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04);
396 result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08);
397 result_table[2] = target_buffer_get_u32(target, mem_params[1].value + 0x0c);
398 result_table[3] = target_buffer_get_u32(target, mem_params[1].value + 0x10);
399
400 LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32", 0x%8.8" PRIx32") completed with result = %8.8" PRIx32,
401 code, param_table[0], param_table[1], param_table[2], param_table[3], param_table[4], status_code);
402
403 destroy_mem_param(&mem_params[0]);
404 destroy_mem_param(&mem_params[1]);
405
406 destroy_reg_param(&reg_params[0]);
407 destroy_reg_param(&reg_params[1]);
408 destroy_reg_param(&reg_params[2]);
409 destroy_reg_param(&reg_params[3]);
410 destroy_reg_param(&reg_params[4]);
411
412 return status_code;
413 }
414
415 static int lpc2000_iap_blank_check(struct flash_bank_s *bank, int first, int last)
416 {
417 uint32_t param_table[5];
418 uint32_t result_table[4];
419 int status_code;
420 int i;
421
422 if ((first < 0) || (last >= bank->num_sectors))
423 return ERROR_FLASH_SECTOR_INVALID;
424
425 for (i = first; i <= last; i++)
426 {
427 /* check single sector */
428 param_table[0] = param_table[1] = i;
429 status_code = lpc2000_iap_call(bank, 53, param_table, result_table);
430
431 switch (status_code)
432 {
433 case ERROR_FLASH_OPERATION_FAILED:
434 return ERROR_FLASH_OPERATION_FAILED;
435 case LPC2000_CMD_SUCCESS:
436 bank->sectors[i].is_erased = 1;
437 break;
438 case LPC2000_SECTOR_NOT_BLANK:
439 bank->sectors[i].is_erased = 0;
440 break;
441 case LPC2000_INVALID_SECTOR:
442 bank->sectors[i].is_erased = 0;
443 break;
444 case LPC2000_BUSY:
445 return ERROR_FLASH_BUSY;
446 break;
447 default:
448 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code);
449 exit(-1);
450 }
451 }
452
453 return ERROR_OK;
454 }
455
456 /*
457 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
458 */
459 static int lpc2000_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
460 {
461 lpc2000_flash_bank_t *lpc2000_info;
462
463 if (argc < 8)
464 {
465 LOG_WARNING("incomplete flash_bank lpc2000 configuration");
466 return ERROR_FLASH_BANK_INVALID;
467 }
468
469 lpc2000_info = malloc(sizeof(lpc2000_flash_bank_t));
470 bank->driver_priv = lpc2000_info;
471
472 if (strcmp(args[6], "lpc2000_v1") == 0)
473 {
474 lpc2000_info->variant = lpc2000_v1;
475 lpc2000_info->cmd51_dst_boundary = 512;
476 lpc2000_info->cmd51_can_256b = 0;
477 lpc2000_info->cmd51_can_8192b = 1;
478 lpc2000_info->checksum_vector = 5;
479 }
480 else if (strcmp(args[6], "lpc2000_v2") == 0)
481 {
482 lpc2000_info->variant = lpc2000_v2;
483 lpc2000_info->cmd51_dst_boundary = 256;
484 lpc2000_info->cmd51_can_256b = 1;
485 lpc2000_info->cmd51_can_8192b = 0;
486 lpc2000_info->checksum_vector = 5;
487 }
488 else if (strcmp(args[6], "lpc1700") == 0)
489 {
490 lpc2000_info->variant = lpc1700;
491 lpc2000_info->cmd51_dst_boundary = 256;
492 lpc2000_info->cmd51_can_256b = 1;
493 lpc2000_info->cmd51_can_8192b = 0;
494 lpc2000_info->checksum_vector = 7;
495 }
496 else
497 {
498 LOG_ERROR("unknown LPC2000 variant: %s", args[6]);
499 free(lpc2000_info);
500 return ERROR_FLASH_BANK_INVALID;
501 }
502
503 lpc2000_info->iap_working_area = NULL;
504 COMMAND_PARSE_NUMBER(u32, args[7], lpc2000_info->cclk);
505 lpc2000_info->calc_checksum = 0;
506 lpc2000_build_sector_list(bank);
507
508 if (argc >= 9)
509 {
510 if (strcmp(args[8], "calc_checksum") == 0)
511 lpc2000_info->calc_checksum = 1;
512 }
513
514 return ERROR_OK;
515 }
516
517 static int lpc2000_erase(struct flash_bank_s *bank, int first, int last)
518 {
519 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
520 uint32_t param_table[5];
521 uint32_t result_table[4];
522 int status_code;
523
524 if (bank->target->state != TARGET_HALTED)
525 {
526 LOG_ERROR("Target not halted");
527 return ERROR_TARGET_NOT_HALTED;
528 }
529
530 param_table[0] = first;
531 param_table[1] = last;
532 param_table[2] = lpc2000_info->cclk;
533
534 /* Prepare sectors */
535 status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
536 switch (status_code)
537 {
538 case ERROR_FLASH_OPERATION_FAILED:
539 return ERROR_FLASH_OPERATION_FAILED;
540 case LPC2000_CMD_SUCCESS:
541 break;
542 case LPC2000_INVALID_SECTOR:
543 return ERROR_FLASH_SECTOR_INVALID;
544 break;
545 default:
546 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
547 return ERROR_FLASH_OPERATION_FAILED;
548 }
549
550 /* Erase sectors */
551 status_code = lpc2000_iap_call(bank, 52, 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 LOG_WARNING("lpc2000 erase sectors returned %i", status_code);
563 return ERROR_FLASH_OPERATION_FAILED;
564 }
565
566 return ERROR_OK;
567 }
568
569 static int lpc2000_protect(struct flash_bank_s *bank, int set, int first, int last)
570 {
571 /* can't protect/unprotect on the lpc2000 */
572 return ERROR_OK;
573 }
574
575 static int lpc2000_write(struct flash_bank_s *bank, uint8_t *buffer, uint32_t offset, uint32_t count)
576 {
577 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
578 target_t *target = bank->target;
579 uint32_t dst_min_alignment;
580 uint32_t bytes_remaining = count;
581 uint32_t bytes_written = 0;
582 int first_sector = 0;
583 int last_sector = 0;
584 uint32_t param_table[5];
585 uint32_t result_table[4];
586 int status_code;
587 int i;
588 working_area_t *download_area;
589 int retval = ERROR_OK;
590
591 if (bank->target->state != TARGET_HALTED)
592 {
593 LOG_ERROR("Target not halted");
594 return ERROR_TARGET_NOT_HALTED;
595 }
596
597 if (offset + count > bank->size)
598 return ERROR_FLASH_DST_OUT_OF_BANK;
599
600 dst_min_alignment = lpc2000_info->cmd51_dst_boundary;
601
602 if (offset % dst_min_alignment)
603 {
604 LOG_WARNING("offset 0x%" PRIx32 " breaks required alignment 0x%" PRIx32, offset, dst_min_alignment);
605 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
606 }
607
608 for (i = 0; i < bank->num_sectors; i++)
609 {
610 if (offset >= bank->sectors[i].offset)
611 first_sector = i;
612 if (offset + CEIL(count, dst_min_alignment) * dst_min_alignment > bank->sectors[i].offset)
613 last_sector = i;
614 }
615
616 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
617
618 /* check if exception vectors should be flashed */
619 if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum)
620 {
621 uint32_t checksum = 0;
622 int i;
623 for (i = 0; i < 8; i++)
624 {
625 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32));
626 if (i != lpc2000_info->checksum_vector)
627 checksum += buf_get_u32(buffer + (i * 4), 0, 32);
628 }
629 checksum = 0 - checksum;
630 LOG_DEBUG("checksum: 0x%8.8" PRIx32, checksum);
631
632 uint32_t original_value = buf_get_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32);
633 if (original_value != checksum)
634 {
635 LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32 ") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32 ").",
636 original_value, checksum);
637 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
638 }
639
640 buf_set_u32(buffer + (lpc2000_info->checksum_vector * 4), 0, 32, checksum);
641 }
642
643 /* allocate a working area */
644 if (target_alloc_working_area(target, lpc2000_info->cmd51_max_buffer, &download_area) != ERROR_OK)
645 {
646 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
647 return ERROR_FLASH_OPERATION_FAILED;
648 }
649
650 while (bytes_remaining > 0)
651 {
652 uint32_t thisrun_bytes;
653 if (bytes_remaining >= lpc2000_info->cmd51_max_buffer)
654 thisrun_bytes = lpc2000_info->cmd51_max_buffer;
655 else if (bytes_remaining >= 1024)
656 thisrun_bytes = 1024;
657 else if ((bytes_remaining >= 512) || (!lpc2000_info->cmd51_can_256b))
658 thisrun_bytes = 512;
659 else
660 thisrun_bytes = 256;
661
662 /* Prepare sectors */
663 param_table[0] = first_sector;
664 param_table[1] = last_sector;
665 status_code = lpc2000_iap_call(bank, 50, param_table, result_table);
666 switch (status_code)
667 {
668 case ERROR_FLASH_OPERATION_FAILED:
669 retval = ERROR_FLASH_OPERATION_FAILED;
670 break;
671 case LPC2000_CMD_SUCCESS:
672 break;
673 case LPC2000_INVALID_SECTOR:
674 retval = ERROR_FLASH_SECTOR_INVALID;
675 break;
676 default:
677 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code);
678 retval = ERROR_FLASH_OPERATION_FAILED;
679 break;
680 }
681
682 /* Exit if error occured */
683 if (retval != ERROR_OK)
684 break;
685
686 if (bytes_remaining >= thisrun_bytes)
687 {
688 if ((retval = target_write_buffer(bank->target, download_area->address, thisrun_bytes, buffer + bytes_written)) != ERROR_OK)
689 {
690 retval = ERROR_FLASH_OPERATION_FAILED;
691 break;
692 }
693 }
694 else
695 {
696 uint8_t *last_buffer = malloc(thisrun_bytes);
697 memcpy(last_buffer, buffer + bytes_written, bytes_remaining);
698 memset(last_buffer + bytes_remaining, 0xff, thisrun_bytes - bytes_remaining);
699 target_write_buffer(bank->target, download_area->address, thisrun_bytes, last_buffer);
700 free(last_buffer);
701 }
702
703 LOG_DEBUG("writing 0x%" PRIx32 " bytes to address 0x%" PRIx32 , thisrun_bytes, bank->base + offset + bytes_written);
704
705 /* Write data */
706 param_table[0] = bank->base + offset + bytes_written;
707 param_table[1] = download_area->address;
708 param_table[2] = thisrun_bytes;
709 param_table[3] = lpc2000_info->cclk;
710 status_code = lpc2000_iap_call(bank, 51, param_table, result_table);
711 switch (status_code)
712 {
713 case ERROR_FLASH_OPERATION_FAILED:
714 retval = ERROR_FLASH_OPERATION_FAILED;
715 break;
716 case LPC2000_CMD_SUCCESS:
717 break;
718 case LPC2000_INVALID_SECTOR:
719 retval = ERROR_FLASH_SECTOR_INVALID;
720 break;
721 default:
722 LOG_WARNING("lpc2000 returned %i", status_code);
723 retval = ERROR_FLASH_OPERATION_FAILED;
724 break;
725 }
726
727 /* Exit if error occured */
728 if (retval != ERROR_OK)
729 break;
730
731 if (bytes_remaining > thisrun_bytes)
732 bytes_remaining -= thisrun_bytes;
733 else
734 bytes_remaining = 0;
735 bytes_written += thisrun_bytes;
736 }
737
738 target_free_working_area(target, download_area);
739
740 return retval;
741 }
742
743 static int lpc2000_probe(struct flash_bank_s *bank)
744 {
745 /* we can't probe on an lpc2000
746 * if this is an lpc2xxx, it has the configured flash
747 */
748 return ERROR_OK;
749 }
750
751 static int lpc2000_erase_check(struct flash_bank_s *bank)
752 {
753 if (bank->target->state != TARGET_HALTED)
754 {
755 LOG_ERROR("Target not halted");
756 return ERROR_TARGET_NOT_HALTED;
757 }
758
759 return lpc2000_iap_blank_check(bank, 0, bank->num_sectors - 1);
760 }
761
762 static int lpc2000_protect_check(struct flash_bank_s *bank)
763 {
764 /* sectors are always protected */
765 return ERROR_OK;
766 }
767
768 static int lpc2000_info(struct flash_bank_s *bank, char *buf, int buf_size)
769 {
770 lpc2000_flash_bank_t *lpc2000_info = bank->driver_priv;
771
772 snprintf(buf, buf_size, "lpc2000 flash driver variant: %i, clk: %" PRIi32 "kHz" , lpc2000_info->variant, lpc2000_info->cclk);
773
774 return ERROR_OK;
775 }
776
777 static int lpc2000_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
778 {
779 uint32_t param_table[5];
780 uint32_t result_table[4];
781 int status_code;
782
783 if (argc < 1)
784 {
785 return ERROR_COMMAND_SYNTAX_ERROR;
786 }
787
788 flash_bank_t *bank;
789 int retval = flash_command_get_bank_by_num(cmd_ctx, args[0], &bank);
790 if (ERROR_OK != retval)
791 return retval;
792
793 if (bank->target->state != TARGET_HALTED)
794 {
795 LOG_ERROR("Target not halted");
796 return ERROR_TARGET_NOT_HALTED;
797 }
798
799 if ((status_code = lpc2000_iap_call(bank, 54, param_table, result_table)) != 0x0)
800 {
801 if (status_code == ERROR_FLASH_OPERATION_FAILED)
802 {
803 command_print(cmd_ctx, "no sufficient working area specified, can't access LPC2000 IAP interface");
804 return ERROR_OK;
805 }
806 command_print(cmd_ctx, "lpc2000 IAP returned status code %i", status_code);
807 }
808 else
809 {
810 command_print(cmd_ctx, "lpc2000 part id: 0x%8.8" PRIx32 , result_table[0]);
811 }
812
813 return ERROR_OK;
814 }

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)