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

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)