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 * 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. *
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. *
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 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
22 ***************************************************************************/
29 #include <helper/binarybuffer.h>
30 #include <target/algorithm.h>
31 #include <target/arm_opcodes.h>
32 #include <target/armv7m.h>
36 * flash programming support for NXP LPC17xx and LPC2xxx devices.
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).
42 * currently supported devices:
43 * variant 1 (lpc2000_v1):
51 * variant 2 (lpc2000_v2):
60 * - 176x (tested with LPC1768)
62 * lpc4300 (also available as lpc1800 - alias)
63 * - 43x2 | 3 | 5 | 7 (tested with 4337)
67 * - 810 | 1 | 2 (tested with 812)
78 struct lpc2000_flash_bank
{
79 lpc2000_variant variant
;
81 int cmd51_dst_boundary
;
86 uint32_t cmd51_max_buffer
;
88 uint32_t iap_max_stack
;
89 uint32_t cmd51_src_offset
;
90 uint32_t lpc4300_bank
;
93 enum lpc2000_status_codes
{
94 LPC2000_CMD_SUCCESS
= 0,
95 LPC2000_INVALID_COMMAND
= 1,
96 LPC2000_SRC_ADDR_ERROR
= 2,
97 LPC2000_DST_ADDR_ERROR
= 3,
98 LPC2000_SRC_ADDR_NOT_MAPPED
= 4,
99 LPC2000_DST_ADDR_NOT_MAPPED
= 5,
100 LPC2000_COUNT_ERROR
= 6,
101 LPC2000_INVALID_SECTOR
= 7,
102 LPC2000_SECTOR_NOT_BLANK
= 8,
103 LPC2000_SECTOR_NOT_PREPARED
= 9,
104 LPC2000_COMPARE_ERROR
= 10,
106 LPC2000_PARAM_ERROR
= 12,
107 LPC2000_ADDR_ERROR
= 13,
108 LPC2000_ADDR_NOT_MAPPED
= 14,
109 LPC2000_CMD_NOT_LOCKED
= 15,
110 LPC2000_INVALID_CODE
= 16,
111 LPC2000_INVALID_BAUD_RATE
= 17,
112 LPC2000_INVALID_STOP_BIT
= 18,
113 LPC2000_CRP_ENABLED
= 19,
114 LPC2000_INVALID_FLASH_UNIT
= 20,
115 LPC2000_USER_CODE_CHECKSUM
= 21,
116 LCP2000_ERROR_SETTING_ACTIVE_PARTITION
= 22,
119 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
121 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
124 /* default to a 4096 write buffer */
125 lpc2000_info
->cmd51_max_buffer
= 4096;
127 if (lpc2000_info
->variant
== lpc2000_v1
) {
128 /* variant 1 has different layout for 128kb and 256kb flashes */
129 if (bank
->size
== 128 * 1024) {
130 bank
->num_sectors
= 16;
131 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 16);
132 for (int i
= 0; i
< 16; i
++) {
133 bank
->sectors
[i
].offset
= offset
;
134 bank
->sectors
[i
].size
= 8 * 1024;
135 offset
+= bank
->sectors
[i
].size
;
136 bank
->sectors
[i
].is_erased
= -1;
137 bank
->sectors
[i
].is_protected
= 1;
139 } else if (bank
->size
== 256 * 1024) {
140 bank
->num_sectors
= 18;
141 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
143 for (int i
= 0; i
< 8; i
++) {
144 bank
->sectors
[i
].offset
= offset
;
145 bank
->sectors
[i
].size
= 8 * 1024;
146 offset
+= bank
->sectors
[i
].size
;
147 bank
->sectors
[i
].is_erased
= -1;
148 bank
->sectors
[i
].is_protected
= 1;
150 for (int i
= 8; i
< 10; i
++) {
151 bank
->sectors
[i
].offset
= offset
;
152 bank
->sectors
[i
].size
= 64 * 1024;
153 offset
+= bank
->sectors
[i
].size
;
154 bank
->sectors
[i
].is_erased
= -1;
155 bank
->sectors
[i
].is_protected
= 1;
157 for (int i
= 10; i
< 18; i
++) {
158 bank
->sectors
[i
].offset
= offset
;
159 bank
->sectors
[i
].size
= 8 * 1024;
160 offset
+= bank
->sectors
[i
].size
;
161 bank
->sectors
[i
].is_erased
= -1;
162 bank
->sectors
[i
].is_protected
= 1;
165 LOG_ERROR("BUG: unknown bank->size encountered");
168 } else if (lpc2000_info
->variant
== lpc2000_v2
) {
169 /* variant 2 has a uniform layout, only number of sectors differs */
170 switch (bank
->size
) {
172 lpc2000_info
->cmd51_max_buffer
= 1024;
173 bank
->num_sectors
= 1;
176 lpc2000_info
->cmd51_max_buffer
= 1024;
177 bank
->num_sectors
= 2;
180 bank
->num_sectors
= 4;
183 bank
->num_sectors
= 8;
186 bank
->num_sectors
= 9;
189 bank
->num_sectors
= 11;
192 bank
->num_sectors
= 15;
195 bank
->num_sectors
= 27;
199 bank
->num_sectors
= 28;
202 LOG_ERROR("BUG: unknown bank->size encountered");
207 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
209 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
211 bank
->sectors
[i
].offset
= offset
;
212 bank
->sectors
[i
].size
= 4 * 1024;
213 offset
+= bank
->sectors
[i
].size
;
214 bank
->sectors
[i
].is_erased
= -1;
215 bank
->sectors
[i
].is_protected
= 1;
217 bank
->sectors
[i
].offset
= offset
;
218 bank
->sectors
[i
].size
= 32 * 1024;
219 offset
+= bank
->sectors
[i
].size
;
220 bank
->sectors
[i
].is_erased
= -1;
221 bank
->sectors
[i
].is_protected
= 1;
223 bank
->sectors
[i
].offset
= offset
;
224 bank
->sectors
[i
].size
= 4 * 1024;
225 offset
+= bank
->sectors
[i
].size
;
226 bank
->sectors
[i
].is_erased
= -1;
227 bank
->sectors
[i
].is_protected
= 1;
230 } else if (lpc2000_info
->variant
== lpc1700
) {
231 switch (bank
->size
) {
233 lpc2000_info
->cmd51_max_buffer
= 1024;
234 bank
->num_sectors
= 1;
237 lpc2000_info
->cmd51_max_buffer
= 1024;
238 bank
->num_sectors
= 2;
241 lpc2000_info
->cmd51_max_buffer
= 1024;
242 bank
->num_sectors
= 4;
245 lpc2000_info
->cmd51_max_buffer
= 1024;
246 bank
->num_sectors
= 8;
249 bank
->num_sectors
= 16;
252 bank
->num_sectors
= 18;
255 bank
->num_sectors
= 22;
258 bank
->num_sectors
= 30;
261 LOG_ERROR("BUG: unknown bank->size encountered");
265 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
267 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
268 bank
->sectors
[i
].offset
= offset
;
269 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
270 bank
->sectors
[i
].size
= (i
< 16) ? 4 * 1024 : 32 * 1024;
271 offset
+= bank
->sectors
[i
].size
;
272 bank
->sectors
[i
].is_erased
= -1;
273 bank
->sectors
[i
].is_protected
= 1;
275 } else if (lpc2000_info
->variant
== lpc4300
) {
276 switch (bank
->size
) {
278 bank
->num_sectors
= 11;
281 bank
->num_sectors
= 13;
284 bank
->num_sectors
= 15;
287 LOG_ERROR("BUG: unknown bank->size encountered");
291 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
293 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
294 bank
->sectors
[i
].offset
= offset
;
295 /* sectors 0-7 are 8kB-sized, 8 and above are 64kB-sized for LPC43xx devices */
296 bank
->sectors
[i
].size
= (i
< 8) ? 8 * 1024 : 64 * 1024;
297 offset
+= bank
->sectors
[i
].size
;
298 bank
->sectors
[i
].is_erased
= -1;
299 bank
->sectors
[i
].is_protected
= 1;
302 } else if (lpc2000_info
->variant
== lpc800
) {
303 lpc2000_info
->cmd51_max_buffer
= 1024;
304 switch (bank
->size
) {
306 bank
->num_sectors
= 4;
309 bank
->num_sectors
= 8;
312 bank
->num_sectors
= 16;
315 LOG_ERROR("BUG: unknown bank->size encountered");
319 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
321 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
322 bank
->sectors
[i
].offset
= offset
;
323 /* sectors 0-15 are 1kB-sized for LPC8xx devices */
324 bank
->sectors
[i
].size
= 1 * 1024;
325 offset
+= bank
->sectors
[i
].size
;
326 bank
->sectors
[i
].is_erased
= -1;
327 bank
->sectors
[i
].is_protected
= 1;
331 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
338 /* this function allocates and initializes working area used for IAP algorithm
339 * uses 52 + max IAP stack bytes working area
340 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
341 * 0x8 to 0x1f: command parameter table (1+5 words)
342 * 0x20 to 0x33: command result table (1+4 words)
343 * 0x34 to 0xb3|0x104: stack (only 128b needed for lpc17xx/2000, 208 for lpc43xx and 148b for lpc8xx)
346 static int lpc2000_iap_working_area_init(struct flash_bank
*bank
, struct working_area
**iap_working_area
)
348 struct target
*target
= bank
->target
;
349 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
351 if (target_alloc_working_area(target
, 0x34 + lpc2000_info
->iap_max_stack
, iap_working_area
) != ERROR_OK
) {
352 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
353 return ERROR_FLASH_OPERATION_FAILED
;
356 uint8_t jump_gate
[8];
358 /* write IAP code to working area */
359 switch (lpc2000_info
->variant
) {
363 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_T_BX(12));
364 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV5_T_BKPT(0));
368 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
369 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
372 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
376 int retval
= target_write_memory(target
, (*iap_working_area
)->address
, 4, 2, jump_gate
);
377 if (retval
!= ERROR_OK
)
378 LOG_ERROR("Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)",
379 (*iap_working_area
)->address
);
384 /* call LPC1700/LPC2000 IAP function */
386 static int lpc2000_iap_call(struct flash_bank
*bank
, struct working_area
*iap_working_area
, int code
,
387 uint32_t param_table
[5], uint32_t result_table
[4])
389 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
390 struct target
*target
= bank
->target
;
392 struct arm_algorithm arm_algo
; /* for LPC2000 */
393 struct armv7m_algorithm armv7m_info
; /* for LPC1700 */
394 uint32_t iap_entry_point
= 0; /* to make compiler happier */
396 switch (lpc2000_info
->variant
) {
399 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
400 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
401 iap_entry_point
= 0x1fff1ff1;
405 arm_algo
.common_magic
= ARM_COMMON_MAGIC
;
406 arm_algo
.core_mode
= ARM_MODE_SVC
;
407 arm_algo
.core_state
= ARM_STATE_ARM
;
408 iap_entry_point
= 0x7ffffff1;
411 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
412 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
413 /* read out IAP entry point from ROM driver table at 0x10400100 */
414 target_read_u32(target
, 0x10400100, &iap_entry_point
);
417 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
421 struct mem_param mem_params
[2];
423 /* command parameter table */
424 init_mem_param(&mem_params
[0], iap_working_area
->address
+ 8, 6 * 4, PARAM_OUT
);
425 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
426 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
427 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
428 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
429 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
430 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
432 struct reg_param reg_params
[5];
434 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
435 buf_set_u32(reg_params
[0].value
, 0, 32, iap_working_area
->address
+ 0x08);
437 /* command result table */
438 init_mem_param(&mem_params
[1], iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
440 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
441 buf_set_u32(reg_params
[1].value
, 0, 32, iap_working_area
->address
+ 0x20);
443 /* IAP entry point */
444 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
445 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
447 switch (lpc2000_info
->variant
) {
452 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
453 buf_set_u32(reg_params
[3].value
, 0, 32, iap_working_area
->address
+ lpc2000_info
->cmd51_src_offset
);
456 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
457 buf_set_u32(reg_params
[4].value
, 0, 32, (iap_working_area
->address
+ 0x04) | 1);
458 /* bit0 of LR = 1 to return in Thumb mode */
460 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
, 0, 10000,
466 init_reg_param(®_params
[3], "sp_svc", 32, PARAM_OUT
);
467 buf_set_u32(reg_params
[3].value
, 0, 32, iap_working_area
->address
+ lpc2000_info
->cmd51_src_offset
);
470 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
471 buf_set_u32(reg_params
[4].value
, 0, 32, iap_working_area
->address
+ 0x04);
473 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
,
474 iap_working_area
->address
+ 0x4, 10000, &arm_algo
);
477 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
481 int status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
482 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
483 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
484 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
485 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
487 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
488 ") completed with result = %8.8" PRIx32
,
489 code
, param_table
[0], param_table
[1], param_table
[2], param_table
[3], param_table
[4], status_code
);
491 destroy_mem_param(&mem_params
[0]);
492 destroy_mem_param(&mem_params
[1]);
494 destroy_reg_param(®_params
[0]);
495 destroy_reg_param(®_params
[1]);
496 destroy_reg_param(®_params
[2]);
497 destroy_reg_param(®_params
[3]);
498 destroy_reg_param(®_params
[4]);
503 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
505 if ((first
< 0) || (last
>= bank
->num_sectors
))
506 return ERROR_FLASH_SECTOR_INVALID
;
508 uint32_t param_table
[5] = {0};
509 uint32_t result_table
[4];
510 struct working_area
*iap_working_area
;
512 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
514 if (retval
!= ERROR_OK
)
517 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
518 if (lpc2000_info
->variant
== lpc4300
)
519 param_table
[2] = lpc2000_info
->lpc4300_bank
;
521 for (int i
= first
; i
<= last
&& retval
== ERROR_OK
; i
++) {
522 /* check single sector */
523 param_table
[0] = param_table
[1] = i
;
524 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 53, param_table
, result_table
);
526 switch (status_code
) {
527 case ERROR_FLASH_OPERATION_FAILED
:
528 retval
= ERROR_FLASH_OPERATION_FAILED
;
530 case LPC2000_CMD_SUCCESS
:
531 bank
->sectors
[i
].is_erased
= 1;
533 case LPC2000_SECTOR_NOT_BLANK
:
534 bank
->sectors
[i
].is_erased
= 0;
536 case LPC2000_INVALID_SECTOR
:
537 bank
->sectors
[i
].is_erased
= 0;
540 retval
= ERROR_FLASH_BUSY
;
543 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
548 struct target
*target
= bank
->target
;
549 target_free_working_area(target
, iap_working_area
);
555 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
557 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
560 return ERROR_COMMAND_SYNTAX_ERROR
;
562 struct lpc2000_flash_bank
*lpc2000_info
= malloc(sizeof(struct lpc2000_flash_bank
));
563 bank
->driver_priv
= lpc2000_info
;
565 if (strcmp(CMD_ARGV
[6], "lpc2000_v1") == 0) {
566 lpc2000_info
->variant
= lpc2000_v1
;
567 lpc2000_info
->cmd51_dst_boundary
= 512;
568 lpc2000_info
->cmd51_can_256b
= 0;
569 lpc2000_info
->cmd51_can_8192b
= 1;
570 lpc2000_info
->checksum_vector
= 5;
571 lpc2000_info
->iap_max_stack
= 128;
572 } else if (strcmp(CMD_ARGV
[6], "lpc2000_v2") == 0) {
573 lpc2000_info
->variant
= lpc2000_v2
;
574 lpc2000_info
->cmd51_dst_boundary
= 256;
575 lpc2000_info
->cmd51_can_256b
= 1;
576 lpc2000_info
->cmd51_can_8192b
= 0;
577 lpc2000_info
->checksum_vector
= 5;
578 lpc2000_info
->iap_max_stack
= 128;
579 } else if (strcmp(CMD_ARGV
[6], "lpc1700") == 0) {
580 lpc2000_info
->variant
= lpc1700
;
581 lpc2000_info
->cmd51_dst_boundary
= 256;
582 lpc2000_info
->cmd51_can_256b
= 1;
583 lpc2000_info
->cmd51_can_8192b
= 0;
584 lpc2000_info
->checksum_vector
= 7;
585 lpc2000_info
->iap_max_stack
= 128;
586 } else if (strcmp(CMD_ARGV
[6], "lpc1800") == 0 || strcmp(CMD_ARGV
[6], "lpc4300") == 0) {
587 lpc2000_info
->variant
= lpc4300
;
588 lpc2000_info
->cmd51_dst_boundary
= 512;
589 lpc2000_info
->cmd51_can_256b
= 0;
590 lpc2000_info
->cmd51_can_8192b
= 0;
591 lpc2000_info
->checksum_vector
= 7;
592 lpc2000_info
->iap_max_stack
= 208;
593 } else if (strcmp(CMD_ARGV
[6], "lpc800") == 0) {
594 lpc2000_info
->variant
= lpc800
;
595 lpc2000_info
->cmd51_dst_boundary
= 64;
596 lpc2000_info
->cmd51_can_64b
= 1;
597 lpc2000_info
->cmd51_can_256b
= 0;
598 lpc2000_info
->cmd51_can_8192b
= 0;
599 lpc2000_info
->checksum_vector
= 7;
600 lpc2000_info
->iap_max_stack
= 148;
602 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
604 return ERROR_FLASH_BANK_INVALID
;
607 /* see lpc2000_iap_working_area_init() for the reason behind the 0x34 value */
608 lpc2000_info
->cmd51_src_offset
= 0x34 + lpc2000_info
->iap_max_stack
;
610 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
611 lpc2000_info
->calc_checksum
= 0;
612 lpc2000_build_sector_list(bank
);
614 uint32_t temp_base
= 0;
615 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], temp_base
);
616 if (temp_base
>= 0x1B000000)
617 lpc2000_info
->lpc4300_bank
= 1; /* bank B */
619 lpc2000_info
->lpc4300_bank
= 0; /* bank A */
622 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
623 lpc2000_info
->calc_checksum
= 1;
629 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
631 if (bank
->target
->state
!= TARGET_HALTED
) {
632 LOG_ERROR("Target not halted");
633 return ERROR_TARGET_NOT_HALTED
;
636 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
637 uint32_t param_table
[5] = {0};
639 param_table
[0] = first
;
640 param_table
[1] = last
;
642 if (lpc2000_info
->variant
== lpc4300
)
643 param_table
[2] = lpc2000_info
->lpc4300_bank
;
645 param_table
[2] = lpc2000_info
->cclk
;
647 uint32_t result_table
[4];
648 struct working_area
*iap_working_area
;
650 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
652 if (retval
!= ERROR_OK
)
655 /* Prepare sectors */
656 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 50, param_table
, result_table
);
657 switch (status_code
) {
658 case ERROR_FLASH_OPERATION_FAILED
:
659 retval
= ERROR_FLASH_OPERATION_FAILED
;
661 case LPC2000_CMD_SUCCESS
:
663 case LPC2000_INVALID_SECTOR
:
664 retval
= ERROR_FLASH_SECTOR_INVALID
;
667 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
668 retval
= ERROR_FLASH_OPERATION_FAILED
;
672 if (retval
== ERROR_OK
) {
674 param_table
[2] = lpc2000_info
->cclk
;
675 if (lpc2000_info
->variant
== lpc4300
)
676 param_table
[3] = lpc2000_info
->lpc4300_bank
;
678 status_code
= lpc2000_iap_call(bank
, iap_working_area
, 52, param_table
, result_table
);
679 switch (status_code
) {
680 case ERROR_FLASH_OPERATION_FAILED
:
681 retval
= ERROR_FLASH_OPERATION_FAILED
;
683 case LPC2000_CMD_SUCCESS
:
685 case LPC2000_INVALID_SECTOR
:
686 retval
= ERROR_FLASH_SECTOR_INVALID
;
689 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
690 retval
= ERROR_FLASH_OPERATION_FAILED
;
695 struct target
*target
= bank
->target
;
696 target_free_working_area(target
, iap_working_area
);
701 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
703 /* can't protect/unprotect on the lpc2000 */
707 static int lpc2000_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
709 struct target
*target
= bank
->target
;
711 if (bank
->target
->state
!= TARGET_HALTED
) {
712 LOG_ERROR("Target not halted");
713 return ERROR_TARGET_NOT_HALTED
;
716 if (offset
+ count
> bank
->size
)
717 return ERROR_FLASH_DST_OUT_OF_BANK
;
719 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
721 uint32_t dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
723 if (offset
% dst_min_alignment
) {
724 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
, offset
, dst_min_alignment
);
725 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
728 int first_sector
= 0;
731 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
732 if (offset
>= bank
->sectors
[i
].offset
)
734 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
738 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
740 /* check if exception vectors should be flashed */
741 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
) {
742 uint32_t checksum
= 0;
743 for (int i
= 0; i
< 8; i
++) {
744 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
745 if (i
!= lpc2000_info
->checksum_vector
)
746 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
748 checksum
= 0 - checksum
;
749 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
751 uint32_t original_value
= buf_get_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32);
752 if (original_value
!= checksum
) {
753 LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32
") to be written to flash is "
754 "different from calculated vector checksum (0x%8.8" PRIx32
").", original_value
, checksum
);
755 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector "
759 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
762 struct working_area
*iap_working_area
;
764 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
766 if (retval
!= ERROR_OK
)
769 struct working_area
*download_area
;
771 /* allocate a working area */
772 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
) {
773 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
774 target_free_working_area(target
, iap_working_area
);
775 return ERROR_FLASH_OPERATION_FAILED
;
778 uint32_t bytes_remaining
= count
;
779 uint32_t bytes_written
= 0;
780 uint32_t param_table
[5] = {0};
781 uint32_t result_table
[4];
783 while (bytes_remaining
> 0) {
784 uint32_t thisrun_bytes
;
785 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
786 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
787 else if (bytes_remaining
>= 1024)
788 thisrun_bytes
= 1024;
789 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
791 else if ((bytes_remaining
>= 256) || (!lpc2000_info
->cmd51_can_64b
))
796 /* Prepare sectors */
797 param_table
[0] = first_sector
;
798 param_table
[1] = last_sector
;
800 if (lpc2000_info
->variant
== lpc4300
)
801 param_table
[2] = lpc2000_info
->lpc4300_bank
;
803 param_table
[2] = lpc2000_info
->cclk
;
805 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 50, param_table
, result_table
);
806 switch (status_code
) {
807 case ERROR_FLASH_OPERATION_FAILED
:
808 retval
= ERROR_FLASH_OPERATION_FAILED
;
810 case LPC2000_CMD_SUCCESS
:
812 case LPC2000_INVALID_SECTOR
:
813 retval
= ERROR_FLASH_SECTOR_INVALID
;
816 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
817 retval
= ERROR_FLASH_OPERATION_FAILED
;
821 /* Exit if error occured */
822 if (retval
!= ERROR_OK
)
825 if (bytes_remaining
>= thisrun_bytes
) {
826 retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
);
827 if (retval
!= ERROR_OK
) {
828 retval
= ERROR_FLASH_OPERATION_FAILED
;
832 uint8_t *last_buffer
= malloc(thisrun_bytes
);
833 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
834 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
- bytes_remaining
);
835 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
839 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
,
840 bank
->base
+ offset
+ bytes_written
);
843 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
844 param_table
[1] = download_area
->address
;
845 param_table
[2] = thisrun_bytes
;
846 param_table
[3] = lpc2000_info
->cclk
;
847 status_code
= lpc2000_iap_call(bank
, iap_working_area
, 51, param_table
, result_table
);
848 switch (status_code
) {
849 case ERROR_FLASH_OPERATION_FAILED
:
850 retval
= ERROR_FLASH_OPERATION_FAILED
;
852 case LPC2000_CMD_SUCCESS
:
854 case LPC2000_INVALID_SECTOR
:
855 retval
= ERROR_FLASH_SECTOR_INVALID
;
858 LOG_WARNING("lpc2000 returned %i", status_code
);
859 retval
= ERROR_FLASH_OPERATION_FAILED
;
863 /* Exit if error occured */
864 if (retval
!= ERROR_OK
)
867 if (bytes_remaining
> thisrun_bytes
)
868 bytes_remaining
-= thisrun_bytes
;
871 bytes_written
+= thisrun_bytes
;
874 target_free_working_area(target
, iap_working_area
);
875 target_free_working_area(target
, download_area
);
880 static int lpc2000_probe(struct flash_bank
*bank
)
882 /* we can't probe on an lpc2000 if this is an lpc2xxx, it has the configured flash */
886 static int lpc2000_erase_check(struct flash_bank
*bank
)
888 if (bank
->target
->state
!= TARGET_HALTED
) {
889 LOG_ERROR("Target not halted");
890 return ERROR_TARGET_NOT_HALTED
;
893 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
896 static int lpc2000_protect_check(struct flash_bank
*bank
)
898 /* sectors are always protected */
902 static int get_lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
904 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
906 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz", lpc2000_info
->variant
,
912 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
915 return ERROR_COMMAND_SYNTAX_ERROR
;
917 struct flash_bank
*bank
;
918 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
919 if (ERROR_OK
!= retval
)
922 if (bank
->target
->state
!= TARGET_HALTED
) {
923 LOG_ERROR("Target not halted");
924 return ERROR_TARGET_NOT_HALTED
;
927 uint32_t param_table
[5] = {0};
928 uint32_t result_table
[4];
929 struct working_area
*iap_working_area
;
931 retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
933 if (retval
!= ERROR_OK
)
936 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 54, param_table
, result_table
);
937 if (status_code
!= 0x0) {
938 if (status_code
== ERROR_FLASH_OPERATION_FAILED
) {
939 command_print(CMD_CTX
, "no sufficient working area specified, can't access LPC2000 IAP interface");
941 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
943 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
948 static const struct command_registration lpc2000_exec_command_handlers
[] = {
951 .handler
= lpc2000_handle_part_id_command
,
952 .mode
= COMMAND_EXEC
,
953 .help
= "print part id of lpc2000 flash bank <num>",
956 COMMAND_REGISTRATION_DONE
958 static const struct command_registration lpc2000_command_handlers
[] = {
962 .help
= "lpc2000 flash command group",
964 .chain
= lpc2000_exec_command_handlers
,
966 COMMAND_REGISTRATION_DONE
969 struct flash_driver lpc2000_flash
= {
971 .commands
= lpc2000_command_handlers
,
972 .flash_bank_command
= lpc2000_flash_bank_command
,
973 .erase
= lpc2000_erase
,
974 .protect
= lpc2000_protect
,
975 .write
= lpc2000_write
,
976 .read
= default_flash_read
,
977 .probe
= lpc2000_probe
,
978 .auto_probe
= lpc2000_probe
,
979 .erase_check
= lpc2000_erase_check
,
980 .protect_check
= lpc2000_protect_check
,
981 .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)