1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * LPC1700 support Copyright (C) 2009 by Audrius Urmanavicius *
6 * didele.deze@gmail.com *
8 * LPC1100 variant and auto-probing support Copyright (C) 2014 *
9 * by Cosmin Gorgovan cosmin [at] linux-geek [dot] org *
11 * LPC800/LPC1500/LPC54100 support Copyright (C) 2013/2014 *
12 * by Nemui Trinomius *
13 * nemuisan_kawausogasuki@live.jp *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
20 * This program is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23 * GNU General Public License for more details. *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program; if not, write to the *
27 * Free Software Foundation, Inc., *
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
29 ***************************************************************************/
36 #include <helper/binarybuffer.h>
37 #include <target/algorithm.h>
38 #include <target/arm_opcodes.h>
39 #include <target/armv7m.h>
43 * flash programming support for NXP LPC8xx,LPC1xxx,LPC4xxx,LP5410x and LPC2xxx devices.
45 * @todo Provide a way to update CCLK after declaring the flash bank. The value which is correct after chip reset will
46 * rarely still work right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz).
49 * currently supported devices:
50 * variant 1 (lpc2000_v1):
58 * variant 2 (lpc2000_v2):
67 * - 176x (tested with LPC1768)
69 * - 178x (tested with LPC1788)
71 * lpc4000: (lpc1700's alias)
73 * - 408x (tested with LPC4088)
75 * lpc4300: (also available as lpc1800 - alias)
76 * - 43x2 | 3 | 5 | 7 (tested with LPC4337/LPC4357)
80 * - 810 | 1 | 2 (tested with LPC810/LPC811/LPC812)
81 * - 822 | 4 (tested with LPC824)
89 * - 11Uxx (tested with LPC11U34)
94 * - 15x7 | 8 | 9 (tested with LPC1549)
97 * - 54101 | 2 (tested with LPC54102)
99 * The auto variant auto-detects parts from the following series:
118 /* Part IDs for autodetection */
119 /* A script which can automatically extract part ids from user manuals is available here:
120 * https://github.com/lgeek/lpc_part_ids
122 #define LPC1110_1 0x0A07102B
123 #define LPC1110_2 0x1A07102B
124 #define LPC1111_002_1 0x0A16D02B
125 #define LPC1111_002_2 0x1A16D02B
126 #define LPC1111_101_1 0x041E502B
127 #define LPC1111_101_2 0x2516D02B
128 #define LPC1111_103_1 0x00010013
129 #define LPC1111_201_1 0x0416502B
130 #define LPC1111_201_2 0x2516902B
131 #define LPC1111_203_1 0x00010012
132 #define LPC1112_101_1 0x042D502B
133 #define LPC1112_101_2 0x2524D02B
134 #define LPC1112_102_1 0x0A24902B
135 #define LPC1112_102_2 0x1A24902B
136 #define LPC1112_103_1 0x00020023
137 #define LPC1112_201_1 0x0425502B
138 #define LPC1112_201_2 0x2524902B
139 #define LPC1112_203_1 0x00020022
140 #define LPC1113_201_1 0x0434502B
141 #define LPC1113_201_2 0x2532902B
142 #define LPC1113_203_1 0x00030032
143 #define LPC1113_301_1 0x0434102B
144 #define LPC1113_301_2 0x2532102B
145 #define LPC1113_303_1 0x00030030
146 #define LPC1114_102_1 0x0A40902B
147 #define LPC1114_102_2 0x1A40902B
148 #define LPC1114_201_1 0x0444502B
149 #define LPC1114_201_2 0x2540902B
150 #define LPC1114_203_1 0x00040042
151 #define LPC1114_301_1 0x0444102B
152 #define LPC1114_301_2 0x2540102B
153 #define LPC1114_303_1 0x00040040
154 #define LPC1114_323_1 0x00040060
155 #define LPC1114_333_1 0x00040070
156 #define LPC1115_303_1 0x00050080
158 #define LPC11A02_1 0x4D4C802B
159 #define LPC11A04_1 0x4D80002B
160 #define LPC11A11_001_1 0x455EC02B
161 #define LPC11A12_101_1 0x4574802B
162 #define LPC11A13_201_1 0x458A402B
163 #define LPC11A14_301_1 0x35A0002B
164 #define LPC11A14_301_2 0x45A0002B
166 #define LPC11C12_301_1 0x1421102B
167 #define LPC11C14_301_1 0x1440102B
168 #define LPC11C22_301_1 0x1431102B
169 #define LPC11C24_301_1 0x1430102B
171 #define LPC11E11_101 0x293E902B
172 #define LPC11E12_201 0x2954502B
173 #define LPC11E13_301 0x296A102B
174 #define LPC11E14_401 0x2980102B
175 #define LPC11E36_501 0x00009C41
176 #define LPC11E37_401 0x00007C45
177 #define LPC11E37_501 0x00007C41
179 #define LPC11U12_201_1 0x095C802B
180 #define LPC11U12_201_2 0x295C802B
181 #define LPC11U13_201_1 0x097A802B
182 #define LPC11U13_201_2 0x297A802B
183 #define LPC11U14_201_1 0x0998802B
184 #define LPC11U14_201_2 0x2998802B
185 #define LPC11U23_301 0x2972402B
186 #define LPC11U24_301 0x2988402B
187 #define LPC11U24_401 0x2980002B
188 #define LPC11U34_311 0x0003D440
189 #define LPC11U34_421 0x0001CC40
190 #define LPC11U35_401 0x0001BC40
191 #define LPC11U35_501 0x0000BC40
192 #define LPC11U36_401 0x00019C40
193 #define LPC11U37_401 0x00017C40
194 #define LPC11U37H_401 0x00007C44
195 #define LPC11U37_501 0x00007C40
197 #define LPC11E66 0x0000DCC1
198 #define LPC11E67 0x0000BC81
199 #define LPC11E68 0x00007C01
201 #define LPC11U66 0x0000DCC8
202 #define LPC11U67_1 0x0000BC88
203 #define LPC11U67_2 0x0000BC80
204 #define LPC11U68_1 0x00007C08
205 #define LPC11U68_2 0x00007C00
207 #define LPC1311 0x2C42502B
208 #define LPC1311_1 0x1816902B
209 #define LPC1313 0x2C40102B
210 #define LPC1313_1 0x1830102B
211 #define LPC1315 0x3A010523
212 #define LPC1316 0x1A018524
213 #define LPC1317 0x1A020525
214 #define LPC1342 0x3D01402B
215 #define LPC1343 0x3D00002B
216 #define LPC1345 0x28010541
217 #define LPC1346 0x08018542
218 #define LPC1347 0x08020543
220 #define LPC1751_1 0x25001110
221 #define LPC1751_2 0x25001118
222 #define LPC1752 0x25001121
223 #define LPC1754 0x25011722
224 #define LPC1756 0x25011723
225 #define LPC1758 0x25013F37
226 #define LPC1759 0x25113737
227 #define LPC1763 0x26012033
228 #define LPC1764 0x26011922
229 #define LPC1765 0x26013733
230 #define LPC1766 0x26013F33
231 #define LPC1767 0x26012837
232 #define LPC1768 0x26013F37
233 #define LPC1769 0x26113F37
234 #define LPC1774 0x27011132
235 #define LPC1776 0x27191F43
236 #define LPC1777 0x27193747
237 #define LPC1778 0x27193F47
238 #define LPC1785 0x281D1743
239 #define LPC1786 0x281D1F43
240 #define LPC1787 0x281D3747
241 #define LPC1788 0x281D3F47
243 #define LPC4072 0x47011121
244 #define LPC4074 0x47011132
245 #define LPC4076 0x47191F43
246 #define LPC4078 0x47193F47
247 #define LPC4088 0x481D3F47
249 #define LPC810_021 0x00008100
250 #define LPC811_001 0x00008110
251 #define LPC812_101 0x00008120
252 #define LPC812_101_1 0x00008121
253 #define LPC812_101_2 0x00008122
254 #define LPC812_101_3 0x00008123
256 #define LPC822_101 0x00008221
257 #define LPC822_101_1 0x00008222
258 #define LPC824_201 0x00008241
259 #define LPC824_201_1 0x00008242
261 #define IAP_CODE_LEN 0x34
275 struct lpc2000_flash_bank
{
276 lpc2000_variant variant
;
278 int cmd51_dst_boundary
;
280 uint32_t cmd51_max_buffer
;
282 uint32_t iap_max_stack
;
283 uint32_t lpc4300_bank
;
287 enum lpc2000_status_codes
{
288 LPC2000_CMD_SUCCESS
= 0,
289 LPC2000_INVALID_COMMAND
= 1,
290 LPC2000_SRC_ADDR_ERROR
= 2,
291 LPC2000_DST_ADDR_ERROR
= 3,
292 LPC2000_SRC_ADDR_NOT_MAPPED
= 4,
293 LPC2000_DST_ADDR_NOT_MAPPED
= 5,
294 LPC2000_COUNT_ERROR
= 6,
295 LPC2000_INVALID_SECTOR
= 7,
296 LPC2000_SECTOR_NOT_BLANK
= 8,
297 LPC2000_SECTOR_NOT_PREPARED
= 9,
298 LPC2000_COMPARE_ERROR
= 10,
300 LPC2000_PARAM_ERROR
= 12,
301 LPC2000_ADDR_ERROR
= 13,
302 LPC2000_ADDR_NOT_MAPPED
= 14,
303 LPC2000_CMD_NOT_LOCKED
= 15,
304 LPC2000_INVALID_CODE
= 16,
305 LPC2000_INVALID_BAUD_RATE
= 17,
306 LPC2000_INVALID_STOP_BIT
= 18,
307 LPC2000_CRP_ENABLED
= 19,
308 LPC2000_INVALID_FLASH_UNIT
= 20,
309 LPC2000_USER_CODE_CHECKSUM
= 21,
310 LCP2000_ERROR_SETTING_ACTIVE_PARTITION
= 22,
313 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
315 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
318 /* default to a 4096 write buffer */
319 lpc2000_info
->cmd51_max_buffer
= 4096;
321 if (lpc2000_info
->variant
== lpc2000_v1
) {
322 lpc2000_info
->cmd51_dst_boundary
= 512;
323 lpc2000_info
->checksum_vector
= 5;
324 lpc2000_info
->iap_max_stack
= 128;
326 /* variant 1 has different layout for 128kb and 256kb flashes */
327 if (bank
->size
== 128 * 1024) {
328 bank
->num_sectors
= 16;
329 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 16);
330 for (int i
= 0; i
< 16; i
++) {
331 bank
->sectors
[i
].offset
= offset
;
332 bank
->sectors
[i
].size
= 8 * 1024;
333 offset
+= bank
->sectors
[i
].size
;
334 bank
->sectors
[i
].is_erased
= -1;
335 bank
->sectors
[i
].is_protected
= 1;
337 } else if (bank
->size
== 256 * 1024) {
338 bank
->num_sectors
= 18;
339 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
341 for (int i
= 0; i
< 8; i
++) {
342 bank
->sectors
[i
].offset
= offset
;
343 bank
->sectors
[i
].size
= 8 * 1024;
344 offset
+= bank
->sectors
[i
].size
;
345 bank
->sectors
[i
].is_erased
= -1;
346 bank
->sectors
[i
].is_protected
= 1;
348 for (int i
= 8; i
< 10; i
++) {
349 bank
->sectors
[i
].offset
= offset
;
350 bank
->sectors
[i
].size
= 64 * 1024;
351 offset
+= bank
->sectors
[i
].size
;
352 bank
->sectors
[i
].is_erased
= -1;
353 bank
->sectors
[i
].is_protected
= 1;
355 for (int i
= 10; i
< 18; i
++) {
356 bank
->sectors
[i
].offset
= offset
;
357 bank
->sectors
[i
].size
= 8 * 1024;
358 offset
+= bank
->sectors
[i
].size
;
359 bank
->sectors
[i
].is_erased
= -1;
360 bank
->sectors
[i
].is_protected
= 1;
363 LOG_ERROR("BUG: unknown bank->size encountered");
366 } else if (lpc2000_info
->variant
== lpc2000_v2
) {
367 lpc2000_info
->cmd51_dst_boundary
= 256;
368 lpc2000_info
->checksum_vector
= 5;
369 lpc2000_info
->iap_max_stack
= 128;
371 /* variant 2 has a uniform layout, only number of sectors differs */
372 switch (bank
->size
) {
374 lpc2000_info
->cmd51_max_buffer
= 1024;
375 bank
->num_sectors
= 1;
378 lpc2000_info
->cmd51_max_buffer
= 1024;
379 bank
->num_sectors
= 2;
382 bank
->num_sectors
= 4;
385 bank
->num_sectors
= 8;
388 bank
->num_sectors
= 9;
391 bank
->num_sectors
= 11;
394 bank
->num_sectors
= 15;
397 bank
->num_sectors
= 27;
401 bank
->num_sectors
= 28;
404 LOG_ERROR("BUG: unknown bank->size encountered");
409 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
411 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
413 bank
->sectors
[i
].offset
= offset
;
414 bank
->sectors
[i
].size
= 4 * 1024;
415 offset
+= bank
->sectors
[i
].size
;
416 bank
->sectors
[i
].is_erased
= -1;
417 bank
->sectors
[i
].is_protected
= 1;
419 bank
->sectors
[i
].offset
= offset
;
420 bank
->sectors
[i
].size
= 32 * 1024;
421 offset
+= bank
->sectors
[i
].size
;
422 bank
->sectors
[i
].is_erased
= -1;
423 bank
->sectors
[i
].is_protected
= 1;
425 bank
->sectors
[i
].offset
= offset
;
426 bank
->sectors
[i
].size
= 4 * 1024;
427 offset
+= bank
->sectors
[i
].size
;
428 bank
->sectors
[i
].is_erased
= -1;
429 bank
->sectors
[i
].is_protected
= 1;
432 } else if (lpc2000_info
->variant
== lpc1700
) {
433 lpc2000_info
->cmd51_dst_boundary
= 256;
434 lpc2000_info
->checksum_vector
= 7;
435 lpc2000_info
->iap_max_stack
= 128;
437 switch (bank
->size
) {
439 lpc2000_info
->cmd51_max_buffer
= 256;
440 bank
->num_sectors
= 1;
443 lpc2000_info
->cmd51_max_buffer
= 512;
444 bank
->num_sectors
= 2;
447 lpc2000_info
->cmd51_max_buffer
= 512;
448 bank
->num_sectors
= 4;
451 lpc2000_info
->cmd51_max_buffer
= 1024;
452 bank
->num_sectors
= 8;
455 bank
->num_sectors
= 16;
458 bank
->num_sectors
= 18;
461 bank
->num_sectors
= 22;
464 bank
->num_sectors
= 30;
467 LOG_ERROR("BUG: unknown bank->size encountered");
471 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
473 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
474 bank
->sectors
[i
].offset
= offset
;
475 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx/LPC40xx devices */
476 bank
->sectors
[i
].size
= (i
< 16) ? 4 * 1024 : 32 * 1024;
477 offset
+= bank
->sectors
[i
].size
;
478 bank
->sectors
[i
].is_erased
= -1;
479 bank
->sectors
[i
].is_protected
= 1;
481 } else if (lpc2000_info
->variant
== lpc4300
) {
482 lpc2000_info
->cmd51_dst_boundary
= 512;
483 lpc2000_info
->checksum_vector
= 7;
484 lpc2000_info
->iap_max_stack
= 208;
486 switch (bank
->size
) {
488 bank
->num_sectors
= 11;
491 bank
->num_sectors
= 13;
494 bank
->num_sectors
= 15;
497 LOG_ERROR("BUG: unknown bank->size encountered");
501 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
503 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
504 bank
->sectors
[i
].offset
= offset
;
505 /* sectors 0-7 are 8kB-sized, 8 and above are 64kB-sized for LPC43xx devices */
506 bank
->sectors
[i
].size
= (i
< 8) ? 8 * 1024 : 64 * 1024;
507 offset
+= bank
->sectors
[i
].size
;
508 bank
->sectors
[i
].is_erased
= -1;
509 bank
->sectors
[i
].is_protected
= 1;
512 } else if (lpc2000_info
->variant
== lpc800
) {
513 lpc2000_info
->cmd51_dst_boundary
= 64;
514 lpc2000_info
->checksum_vector
= 7;
515 lpc2000_info
->iap_max_stack
= 208; /* 148byte for LPC81x,208byte for LPC82x. */
516 lpc2000_info
->cmd51_max_buffer
= 256; /* smallest MCU in the series, LPC810, has 1 kB of SRAM */
518 switch (bank
->size
) {
520 bank
->num_sectors
= 4;
523 bank
->num_sectors
= 8;
526 bank
->num_sectors
= 16;
529 lpc2000_info
->cmd51_max_buffer
= 1024; /* For LPC824, has 8kB of SRAM */
530 bank
->num_sectors
= 32;
533 LOG_ERROR("BUG: unknown bank->size encountered");
537 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
539 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
540 bank
->sectors
[i
].offset
= offset
;
541 /* all sectors are 1kB-sized for LPC8xx devices */
542 bank
->sectors
[i
].size
= 1 * 1024;
543 offset
+= bank
->sectors
[i
].size
;
544 bank
->sectors
[i
].is_erased
= -1;
545 bank
->sectors
[i
].is_protected
= 1;
548 } else if (lpc2000_info
->variant
== lpc1100
) {
549 lpc2000_info
->cmd51_dst_boundary
= 256;
550 lpc2000_info
->checksum_vector
= 7;
551 lpc2000_info
->iap_max_stack
= 128;
553 if ((bank
->size
% (4 * 1024)) != 0) {
554 LOG_ERROR("BUG: unknown bank->size encountered,\nLPC1100 flash size must be a multiple of 4096");
557 lpc2000_info
->cmd51_max_buffer
= 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */
558 bank
->num_sectors
= bank
->size
/ 4096;
560 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
562 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
563 bank
->sectors
[i
].offset
= offset
;
564 /* all sectors are 4kB-sized */
565 bank
->sectors
[i
].size
= 4 * 1024;
566 offset
+= bank
->sectors
[i
].size
;
567 bank
->sectors
[i
].is_erased
= -1;
568 bank
->sectors
[i
].is_protected
= 1;
571 } else if (lpc2000_info
->variant
== lpc1500
) {
572 lpc2000_info
->cmd51_dst_boundary
= 256;
573 lpc2000_info
->checksum_vector
= 7;
574 lpc2000_info
->iap_max_stack
= 128;
576 switch (bank
->size
) {
578 bank
->num_sectors
= 16;
581 bank
->num_sectors
= 32;
584 bank
->num_sectors
= 64;
587 LOG_ERROR("BUG: unknown bank->size encountered");
591 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
593 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
594 bank
->sectors
[i
].offset
= offset
;
595 /* all sectors are 4kB-sized */
596 bank
->sectors
[i
].size
= 4 * 1024;
597 offset
+= bank
->sectors
[i
].size
;
598 bank
->sectors
[i
].is_erased
= -1;
599 bank
->sectors
[i
].is_protected
= 1;
602 } else if (lpc2000_info
->variant
== lpc54100
) {
603 lpc2000_info
->cmd51_dst_boundary
= 256;
604 lpc2000_info
->checksum_vector
= 7;
605 lpc2000_info
->iap_max_stack
= 128;
607 switch (bank
->size
) {
609 bank
->num_sectors
= 8;
612 bank
->num_sectors
= 16;
615 LOG_ERROR("BUG: unknown bank->size encountered");
619 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
621 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
622 bank
->sectors
[i
].offset
= offset
;
623 /* all sectors are 32kB-sized */
624 bank
->sectors
[i
].size
= 32 * 1024;
625 offset
+= bank
->sectors
[i
].size
;
626 bank
->sectors
[i
].is_erased
= -1;
627 bank
->sectors
[i
].is_protected
= 1;
631 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
638 /* this function allocates and initializes working area used for IAP algorithm
639 * uses 52 + max IAP stack bytes working area
640 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
641 * 0x8 to 0x1f: command parameter table (1+5 words)
642 * 0x20 to 0x33: command result table (1+4 words)
643 * 0x34 to 0xb3|0x104: stack
644 * (128b needed for lpc1xxx/2000/5410x, 208b for lpc43xx/lpc82x and 148b for lpc81x)
647 static int lpc2000_iap_working_area_init(struct flash_bank
*bank
, struct working_area
**iap_working_area
)
649 struct target
*target
= bank
->target
;
650 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
652 if (target_alloc_working_area(target
, IAP_CODE_LEN
+ lpc2000_info
->iap_max_stack
, iap_working_area
) != ERROR_OK
) {
653 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
654 return ERROR_FLASH_OPERATION_FAILED
;
657 uint8_t jump_gate
[8];
659 /* write IAP code to working area */
660 switch (lpc2000_info
->variant
) {
668 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_T_BX(12));
669 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV5_T_BKPT(0));
673 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
674 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
677 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
681 int retval
= target_write_memory(target
, (*iap_working_area
)->address
, 4, 2, jump_gate
);
682 if (retval
!= ERROR_OK
)
683 LOG_ERROR("Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)",
684 (*iap_working_area
)->address
);
689 /* call LPC8xx/LPC1xxx/LPC4xxx/LPC5410x/LPC2000 IAP function */
691 static int lpc2000_iap_call(struct flash_bank
*bank
, struct working_area
*iap_working_area
, int code
,
692 uint32_t param_table
[5], uint32_t result_table
[4])
694 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
695 struct target
*target
= bank
->target
;
697 struct arm_algorithm arm_algo
; /* for LPC2000 */
698 struct armv7m_algorithm armv7m_info
; /* for LPC8xx/LPC1xxx/LPC4xxx/LPC5410x */
699 uint32_t iap_entry_point
= 0; /* to make compiler happier */
701 switch (lpc2000_info
->variant
) {
706 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
707 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
708 iap_entry_point
= 0x1fff1ff1;
712 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
713 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
714 iap_entry_point
= 0x03000205;
718 arm_algo
.common_magic
= ARM_COMMON_MAGIC
;
719 arm_algo
.core_mode
= ARM_MODE_SVC
;
720 arm_algo
.core_state
= ARM_STATE_ARM
;
721 iap_entry_point
= 0x7ffffff1;
724 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
725 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
726 /* read out IAP entry point from ROM driver table at 0x10400100 */
727 target_read_u32(target
, 0x10400100, &iap_entry_point
);
730 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
734 struct mem_param mem_params
[2];
736 /* command parameter table */
737 init_mem_param(&mem_params
[0], iap_working_area
->address
+ 8, 6 * 4, PARAM_OUT
);
738 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
739 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
740 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
741 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
742 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
743 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
745 struct reg_param reg_params
[5];
747 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
748 buf_set_u32(reg_params
[0].value
, 0, 32, iap_working_area
->address
+ 0x08);
750 /* command result table */
751 init_mem_param(&mem_params
[1], iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
753 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
754 buf_set_u32(reg_params
[1].value
, 0, 32, iap_working_area
->address
+ 0x20);
756 /* IAP entry point */
757 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
758 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
760 switch (lpc2000_info
->variant
) {
769 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
770 buf_set_u32(reg_params
[3].value
, 0, 32,
771 iap_working_area
->address
+ IAP_CODE_LEN
+ lpc2000_info
->iap_max_stack
);
774 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
775 buf_set_u32(reg_params
[4].value
, 0, 32, (iap_working_area
->address
+ 0x04) | 1);
776 /* bit0 of LR = 1 to return in Thumb mode */
778 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
, 0, 10000,
784 init_reg_param(®_params
[3], "sp_svc", 32, PARAM_OUT
);
785 buf_set_u32(reg_params
[3].value
, 0, 32,
786 iap_working_area
->address
+ IAP_CODE_LEN
+ lpc2000_info
->iap_max_stack
);
789 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
790 buf_set_u32(reg_params
[4].value
, 0, 32, iap_working_area
->address
+ 0x04);
792 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
,
793 iap_working_area
->address
+ 0x4, 10000, &arm_algo
);
796 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
800 int status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
801 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
802 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
803 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
804 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
806 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
807 ") completed with result = %8.8x",
808 code
, param_table
[0], param_table
[1], param_table
[2], param_table
[3], param_table
[4], status_code
);
810 destroy_mem_param(&mem_params
[0]);
811 destroy_mem_param(&mem_params
[1]);
813 destroy_reg_param(®_params
[0]);
814 destroy_reg_param(®_params
[1]);
815 destroy_reg_param(®_params
[2]);
816 destroy_reg_param(®_params
[3]);
817 destroy_reg_param(®_params
[4]);
822 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
824 if ((first
< 0) || (last
>= bank
->num_sectors
))
825 return ERROR_FLASH_SECTOR_INVALID
;
827 uint32_t param_table
[5] = {0};
828 uint32_t result_table
[4];
829 struct working_area
*iap_working_area
;
831 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
833 if (retval
!= ERROR_OK
)
836 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
837 if (lpc2000_info
->variant
== lpc4300
)
838 param_table
[2] = lpc2000_info
->lpc4300_bank
;
840 for (int i
= first
; i
<= last
&& retval
== ERROR_OK
; i
++) {
841 /* check single sector */
842 param_table
[0] = param_table
[1] = i
;
843 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 53, param_table
, result_table
);
845 switch (status_code
) {
846 case ERROR_FLASH_OPERATION_FAILED
:
847 retval
= ERROR_FLASH_OPERATION_FAILED
;
849 case LPC2000_CMD_SUCCESS
:
850 bank
->sectors
[i
].is_erased
= 1;
852 case LPC2000_SECTOR_NOT_BLANK
:
853 bank
->sectors
[i
].is_erased
= 0;
855 case LPC2000_INVALID_SECTOR
:
856 bank
->sectors
[i
].is_erased
= 0;
859 retval
= ERROR_FLASH_BUSY
;
862 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
867 struct target
*target
= bank
->target
;
868 target_free_working_area(target
, iap_working_area
);
874 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
876 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
879 return ERROR_COMMAND_SYNTAX_ERROR
;
881 struct lpc2000_flash_bank
*lpc2000_info
= calloc(1, sizeof(*lpc2000_info
));
882 lpc2000_info
->probed
= false;
884 bank
->driver_priv
= lpc2000_info
;
886 if (strcmp(CMD_ARGV
[6], "lpc2000_v1") == 0) {
887 lpc2000_info
->variant
= lpc2000_v1
;
888 } else if (strcmp(CMD_ARGV
[6], "lpc2000_v2") == 0) {
889 lpc2000_info
->variant
= lpc2000_v2
;
890 } else if (strcmp(CMD_ARGV
[6], "lpc1700") == 0 || strcmp(CMD_ARGV
[6], "lpc4000") == 0) {
891 lpc2000_info
->variant
= lpc1700
;
892 } else if (strcmp(CMD_ARGV
[6], "lpc1800") == 0 || strcmp(CMD_ARGV
[6], "lpc4300") == 0) {
893 lpc2000_info
->variant
= lpc4300
;
894 } else if (strcmp(CMD_ARGV
[6], "lpc800") == 0) {
895 lpc2000_info
->variant
= lpc800
;
896 } else if (strcmp(CMD_ARGV
[6], "lpc1100") == 0) {
897 lpc2000_info
->variant
= lpc1100
;
898 } else if (strcmp(CMD_ARGV
[6], "lpc1500") == 0) {
899 lpc2000_info
->variant
= lpc1500
;
900 } else if (strcmp(CMD_ARGV
[6], "lpc54100") == 0) {
901 lpc2000_info
->variant
= lpc54100
;
902 } else if (strcmp(CMD_ARGV
[6], "auto") == 0) {
903 lpc2000_info
->variant
= lpc_auto
;
905 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
907 return ERROR_FLASH_BANK_INVALID
;
910 /* Maximum size required for the IAP stack.
911 This value only gets used when probing, only for auto, lpc1100 and lpc1700.
912 We use the maximum size for any part supported by the driver(!) to be safe
913 in case the auto variant is mistakenly used on a MCU from one of the series
914 for which we don't support auto-probing. */
915 lpc2000_info
->iap_max_stack
= 208;
917 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
918 lpc2000_info
->calc_checksum
= 0;
920 uint32_t temp_base
= 0;
921 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], temp_base
);
922 if (temp_base
>= 0x1B000000)
923 lpc2000_info
->lpc4300_bank
= 1; /* bank B */
925 lpc2000_info
->lpc4300_bank
= 0; /* bank A */
928 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
929 lpc2000_info
->calc_checksum
= 1;
935 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
937 if (bank
->target
->state
!= TARGET_HALTED
) {
938 LOG_ERROR("Target not halted");
939 return ERROR_TARGET_NOT_HALTED
;
942 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
943 uint32_t param_table
[5] = {0};
945 param_table
[0] = first
;
946 param_table
[1] = last
;
948 if (lpc2000_info
->variant
== lpc4300
)
949 param_table
[2] = lpc2000_info
->lpc4300_bank
;
951 param_table
[2] = lpc2000_info
->cclk
;
953 uint32_t result_table
[4];
954 struct working_area
*iap_working_area
;
956 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
958 if (retval
!= ERROR_OK
)
961 if (lpc2000_info
->variant
== lpc4300
)
962 /* Init IAP Anyway */
963 lpc2000_iap_call(bank
, iap_working_area
, 49, param_table
, result_table
);
965 /* Prepare sectors */
966 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 50, param_table
, result_table
);
967 switch (status_code
) {
968 case ERROR_FLASH_OPERATION_FAILED
:
969 retval
= ERROR_FLASH_OPERATION_FAILED
;
971 case LPC2000_CMD_SUCCESS
:
973 case LPC2000_INVALID_SECTOR
:
974 retval
= ERROR_FLASH_SECTOR_INVALID
;
977 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
978 retval
= ERROR_FLASH_OPERATION_FAILED
;
982 if (retval
== ERROR_OK
) {
984 param_table
[2] = lpc2000_info
->cclk
;
985 if (lpc2000_info
->variant
== lpc4300
)
986 param_table
[3] = lpc2000_info
->lpc4300_bank
;
988 status_code
= lpc2000_iap_call(bank
, iap_working_area
, 52, param_table
, result_table
);
989 switch (status_code
) {
990 case ERROR_FLASH_OPERATION_FAILED
:
991 retval
= ERROR_FLASH_OPERATION_FAILED
;
993 case LPC2000_CMD_SUCCESS
:
995 case LPC2000_INVALID_SECTOR
:
996 retval
= ERROR_FLASH_SECTOR_INVALID
;
999 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
1000 retval
= ERROR_FLASH_OPERATION_FAILED
;
1005 struct target
*target
= bank
->target
;
1006 target_free_working_area(target
, iap_working_area
);
1011 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
1013 /* can't protect/unprotect on the lpc2000 */
1017 static int lpc2000_write(struct flash_bank
*bank
, const uint8_t *buffer
, uint32_t offset
, uint32_t count
)
1019 struct target
*target
= bank
->target
;
1021 if (bank
->target
->state
!= TARGET_HALTED
) {
1022 LOG_ERROR("Target not halted");
1023 return ERROR_TARGET_NOT_HALTED
;
1026 if (offset
+ count
> bank
->size
)
1027 return ERROR_FLASH_DST_OUT_OF_BANK
;
1029 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
1031 uint32_t dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
1033 if (offset
% dst_min_alignment
) {
1034 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
, offset
, dst_min_alignment
);
1035 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
1038 int first_sector
= 0;
1039 int last_sector
= 0;
1041 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
1042 if (offset
>= bank
->sectors
[i
].offset
)
1044 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
1048 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
1050 /* check if exception vectors should be flashed */
1051 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
) {
1052 assert(lpc2000_info
->checksum_vector
< 8);
1053 uint32_t checksum
= 0;
1054 for (int i
= 0; i
< 8; i
++) {
1055 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
1056 if (i
!= lpc2000_info
->checksum_vector
)
1057 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
1059 checksum
= 0 - checksum
;
1060 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
1062 uint32_t original_value
= buf_get_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32);
1063 if (original_value
!= checksum
) {
1064 LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32
") to be written to flash is "
1065 "different from calculated vector checksum (0x%8.8" PRIx32
").", original_value
, checksum
);
1066 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector "
1070 /* FIXME: WARNING! This code is broken because it modifies the callers buffer in place. */
1071 buf_set_u32((uint8_t *)buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
1074 struct working_area
*iap_working_area
;
1076 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
1078 if (retval
!= ERROR_OK
)
1081 struct working_area
*download_area
;
1083 /* allocate a working area */
1084 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
) {
1085 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
1086 target_free_working_area(target
, iap_working_area
);
1087 return ERROR_FLASH_OPERATION_FAILED
;
1090 uint32_t bytes_remaining
= count
;
1091 uint32_t bytes_written
= 0;
1092 uint32_t param_table
[5] = {0};
1093 uint32_t result_table
[4];
1095 if (lpc2000_info
->variant
== lpc4300
)
1096 /* Init IAP Anyway */
1097 lpc2000_iap_call(bank
, iap_working_area
, 49, param_table
, result_table
);
1099 while (bytes_remaining
> 0) {
1100 uint32_t thisrun_bytes
;
1101 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
1102 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
1104 thisrun_bytes
= lpc2000_info
->cmd51_dst_boundary
;
1106 /* Prepare sectors */
1107 param_table
[0] = first_sector
;
1108 param_table
[1] = last_sector
;
1110 if (lpc2000_info
->variant
== lpc4300
)
1111 param_table
[2] = lpc2000_info
->lpc4300_bank
;
1113 param_table
[2] = lpc2000_info
->cclk
;
1115 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 50, param_table
, result_table
);
1116 switch (status_code
) {
1117 case ERROR_FLASH_OPERATION_FAILED
:
1118 retval
= ERROR_FLASH_OPERATION_FAILED
;
1120 case LPC2000_CMD_SUCCESS
:
1122 case LPC2000_INVALID_SECTOR
:
1123 retval
= ERROR_FLASH_SECTOR_INVALID
;
1126 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
1127 retval
= ERROR_FLASH_OPERATION_FAILED
;
1131 /* Exit if error occured */
1132 if (retval
!= ERROR_OK
)
1135 if (bytes_remaining
>= thisrun_bytes
) {
1136 retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
);
1137 if (retval
!= ERROR_OK
) {
1138 retval
= ERROR_FLASH_OPERATION_FAILED
;
1142 uint8_t *last_buffer
= malloc(thisrun_bytes
);
1143 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
1144 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
- bytes_remaining
);
1145 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
1149 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
,
1150 bank
->base
+ offset
+ bytes_written
);
1153 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
1154 param_table
[1] = download_area
->address
;
1155 param_table
[2] = thisrun_bytes
;
1156 param_table
[3] = lpc2000_info
->cclk
;
1157 status_code
= lpc2000_iap_call(bank
, iap_working_area
, 51, param_table
, result_table
);
1158 switch (status_code
) {
1159 case ERROR_FLASH_OPERATION_FAILED
:
1160 retval
= ERROR_FLASH_OPERATION_FAILED
;
1162 case LPC2000_CMD_SUCCESS
:
1164 case LPC2000_INVALID_SECTOR
:
1165 retval
= ERROR_FLASH_SECTOR_INVALID
;
1168 LOG_WARNING("lpc2000 returned %i", status_code
);
1169 retval
= ERROR_FLASH_OPERATION_FAILED
;
1173 /* Exit if error occured */
1174 if (retval
!= ERROR_OK
)
1177 if (bytes_remaining
> thisrun_bytes
)
1178 bytes_remaining
-= thisrun_bytes
;
1180 bytes_remaining
= 0;
1181 bytes_written
+= thisrun_bytes
;
1184 target_free_working_area(target
, iap_working_area
);
1185 target_free_working_area(target
, download_area
);
1190 static int get_lpc2000_part_id(struct flash_bank
*bank
, uint32_t *part_id
)
1192 if (bank
->target
->state
!= TARGET_HALTED
) {
1193 LOG_ERROR("Target not halted");
1194 return ERROR_TARGET_NOT_HALTED
;
1197 uint32_t param_table
[5] = {0};
1198 uint32_t result_table
[4];
1199 struct working_area
*iap_working_area
;
1201 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
1203 if (retval
!= ERROR_OK
)
1206 /* The status seems to be bogus with the part ID command on some IAP
1207 firmwares, so ignore it. */
1208 lpc2000_iap_call(bank
, iap_working_area
, 54, param_table
, result_table
);
1210 /* If the result is zero, the command probably didn't work out. */
1211 if (result_table
[0] == 0)
1212 return LPC2000_INVALID_COMMAND
;
1214 *part_id
= result_table
[0];
1215 return LPC2000_CMD_SUCCESS
;
1218 static int lpc2000_auto_probe_flash(struct flash_bank
*bank
)
1222 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
1224 if (bank
->target
->state
!= TARGET_HALTED
) {
1225 LOG_ERROR("Target not halted");
1226 return ERROR_TARGET_NOT_HALTED
;
1229 retval
= get_lpc2000_part_id(bank
, &part_id
);
1230 if (retval
!= LPC2000_CMD_SUCCESS
) {
1231 LOG_ERROR("Could not get part ID");
1238 lpc2000_info
->variant
= lpc1100
;
1239 bank
->size
= 4 * 1024;
1250 case LPC11A11_001_1
:
1254 lpc2000_info
->variant
= lpc1100
;
1255 bank
->size
= 8 * 1024;
1267 case LPC11C12_301_1
:
1268 case LPC11C22_301_1
:
1269 case LPC11A12_101_1
:
1271 case LPC11U12_201_1
:
1272 case LPC11U12_201_2
:
1274 lpc2000_info
->variant
= lpc1100
;
1275 bank
->size
= 16 * 1024;
1284 case LPC11A13_201_1
:
1286 case LPC11U13_201_1
:
1287 case LPC11U13_201_2
:
1289 lpc2000_info
->variant
= lpc1100
;
1290 bank
->size
= 24 * 1024;
1302 case LPC11A14_301_1
:
1303 case LPC11A14_301_2
:
1304 case LPC11C14_301_1
:
1305 case LPC11C24_301_1
:
1307 case LPC11U14_201_1
:
1308 case LPC11U14_201_2
:
1316 lpc2000_info
->variant
= lpc1100
;
1317 bank
->size
= 32 * 1024;
1322 lpc2000_info
->variant
= lpc1700
;
1323 bank
->size
= 32 * 1024;
1327 lpc2000_info
->variant
= lpc1100
;
1328 bank
->size
= 40 * 1024;
1335 lpc2000_info
->variant
= lpc1100
;
1336 bank
->size
= 48 * 1024;
1340 lpc2000_info
->variant
= lpc1100
;
1341 bank
->size
= 56 * 1024;
1351 lpc2000_info
->variant
= lpc1100
;
1352 bank
->size
= 64 * 1024;
1357 lpc2000_info
->variant
= lpc1700
;
1358 bank
->size
= 64 * 1024;
1363 lpc2000_info
->variant
= lpc1100
;
1364 bank
->size
= 96 * 1024;
1376 lpc2000_info
->variant
= lpc1100
;
1377 bank
->size
= 128 * 1024;
1384 lpc2000_info
->variant
= lpc1700
;
1385 bank
->size
= 128 * 1024;
1390 lpc2000_info
->variant
= lpc1100
;
1391 bank
->size
= 256 * 1024;
1402 lpc2000_info
->variant
= lpc1700
;
1403 bank
->size
= 256 * 1024;
1417 lpc2000_info
->variant
= lpc1700
;
1418 bank
->size
= 512 * 1024;
1422 lpc2000_info
->variant
= lpc800
;
1423 bank
->size
= 4 * 1024;
1427 lpc2000_info
->variant
= lpc800
;
1428 bank
->size
= 8 * 1024;
1437 lpc2000_info
->variant
= lpc800
;
1438 bank
->size
= 16 * 1024;
1443 lpc2000_info
->variant
= lpc800
;
1444 bank
->size
= 32 * 1024;
1448 LOG_ERROR("BUG: unknown Part ID encountered: 0x%x", part_id
);
1455 static int lpc2000_probe(struct flash_bank
*bank
)
1459 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
1461 if (!lpc2000_info
->probed
) {
1462 if (lpc2000_info
->variant
== lpc_auto
) {
1463 status
= lpc2000_auto_probe_flash(bank
);
1464 if (status
!= ERROR_OK
)
1466 } else if (lpc2000_info
->variant
== lpc1100
|| lpc2000_info
->variant
== lpc1700
) {
1467 status
= get_lpc2000_part_id(bank
, &part_id
);
1468 if (status
== LPC2000_CMD_SUCCESS
)
1469 LOG_INFO("If auto-detection fails for this part, please email "
1470 "openocd-devel@lists.sourceforge.net, citing part id 0x%x.\n", part_id
);
1473 lpc2000_build_sector_list(bank
);
1474 lpc2000_info
->probed
= true;
1480 static int lpc2000_erase_check(struct flash_bank
*bank
)
1482 if (bank
->target
->state
!= TARGET_HALTED
) {
1483 LOG_ERROR("Target not halted");
1484 return ERROR_TARGET_NOT_HALTED
;
1487 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
1490 static int lpc2000_protect_check(struct flash_bank
*bank
)
1492 /* sectors are always protected */
1496 static int get_lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
1498 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
1500 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz", lpc2000_info
->variant
,
1501 lpc2000_info
->cclk
);
1506 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
1509 return ERROR_COMMAND_SYNTAX_ERROR
;
1511 struct flash_bank
*bank
;
1512 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
1513 if (ERROR_OK
!= retval
)
1516 if (bank
->target
->state
!= TARGET_HALTED
) {
1517 LOG_ERROR("Target not halted");
1518 return ERROR_TARGET_NOT_HALTED
;
1522 int status_code
= get_lpc2000_part_id(bank
, &part_id
);
1523 if (status_code
!= 0x0) {
1524 if (status_code
== ERROR_FLASH_OPERATION_FAILED
) {
1525 command_print(CMD_CTX
, "no sufficient working area specified, can't access LPC2000 IAP interface");
1527 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
1529 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, part_id
);
1534 static const struct command_registration lpc2000_exec_command_handlers
[] = {
1537 .handler
= lpc2000_handle_part_id_command
,
1538 .mode
= COMMAND_EXEC
,
1539 .help
= "print part id of lpc2000 flash bank <num>",
1542 COMMAND_REGISTRATION_DONE
1544 static const struct command_registration lpc2000_command_handlers
[] = {
1547 .mode
= COMMAND_ANY
,
1548 .help
= "lpc2000 flash command group",
1550 .chain
= lpc2000_exec_command_handlers
,
1552 COMMAND_REGISTRATION_DONE
1555 struct flash_driver lpc2000_flash
= {
1557 .commands
= lpc2000_command_handlers
,
1558 .flash_bank_command
= lpc2000_flash_bank_command
,
1559 .erase
= lpc2000_erase
,
1560 .protect
= lpc2000_protect
,
1561 .write
= lpc2000_write
,
1562 .read
= default_flash_read
,
1563 .probe
= lpc2000_probe
,
1564 .auto_probe
= lpc2000_probe
,
1565 .erase_check
= lpc2000_erase_check
,
1566 .protect_check
= lpc2000_protect_check
,
1567 .info
= get_lpc2000_info
,
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)