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

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)