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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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)
63 * - 43x2 | 3 | 5 | 7 (tested with 4337)
74 struct lpc2000_flash_bank
{
75 lpc2000_variant variant
;
77 int cmd51_dst_boundary
;
81 uint32_t cmd51_max_buffer
;
83 uint32_t iap_max_stack
;
84 uint32_t cmd51_src_offset
;
85 uint32_t lpc4300_bank
;
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,
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,
114 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
116 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
119 /* default to a 4096 write buffer */
120 lpc2000_info
->cmd51_max_buffer
= 4096;
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;
134 } else if (bank
->size
== 256 * 1024) {
135 bank
->num_sectors
= 18;
136 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
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;
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;
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;
160 LOG_ERROR("BUG: unknown bank->size encountered");
163 } else if (lpc2000_info
->variant
== lpc2000_v2
) {
164 /* variant 2 has a uniform layout, only number of sectors differs */
165 switch (bank
->size
) {
167 lpc2000_info
->cmd51_max_buffer
= 1024;
168 bank
->num_sectors
= 1;
171 lpc2000_info
->cmd51_max_buffer
= 1024;
172 bank
->num_sectors
= 2;
175 bank
->num_sectors
= 4;
178 bank
->num_sectors
= 8;
181 bank
->num_sectors
= 9;
184 bank
->num_sectors
= 11;
187 bank
->num_sectors
= 15;
190 bank
->num_sectors
= 27;
194 bank
->num_sectors
= 28;
197 LOG_ERROR("BUG: unknown bank->size encountered");
202 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
204 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
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;
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;
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;
225 } else if (lpc2000_info
->variant
== lpc1700
) {
226 switch (bank
->size
) {
228 bank
->num_sectors
= 8;
231 bank
->num_sectors
= 16;
234 bank
->num_sectors
= 18;
237 bank
->num_sectors
= 22;
240 bank
->num_sectors
= 30;
243 LOG_ERROR("BUG: unknown bank->size encountered");
247 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
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;
257 } else if (lpc2000_info
->variant
== lpc4300
) {
258 switch (bank
->size
) {
260 bank
->num_sectors
= 11;
263 bank
->num_sectors
= 13;
266 bank
->num_sectors
= 15;
269 LOG_ERROR("BUG: unknown bank->size encountered");
273 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
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;
284 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
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)
299 static int lpc2000_iap_working_area_init(struct flash_bank
*bank
, struct working_area
**iap_working_area
)
301 struct target
*target
= bank
->target
;
302 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
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
;
309 uint8_t jump_gate
[8];
311 /* write IAP code to working area */
312 switch (lpc2000_info
->variant
) {
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));
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));
324 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
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
);
336 /* call LPC1700/LPC2000 IAP function */
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])
341 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
342 struct target
*target
= bank
->target
;
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 */
348 switch (lpc2000_info
->variant
) {
350 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
351 armv7m_info
.core_mode
= ARM_MODE_THREAD
;
352 iap_entry_point
= 0x1fff1ff1;
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;
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
);
368 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
372 struct mem_param mem_params
[2];
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]);
383 struct reg_param reg_params
[5];
385 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
386 buf_set_u32(reg_params
[0].value
, 0, 32, iap_working_area
->address
+ 0x08);
388 /* command result table */
389 init_mem_param(&mem_params
[1], iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
391 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
392 buf_set_u32(reg_params
[1].value
, 0, 32, iap_working_area
->address
+ 0x20);
394 /* IAP entry point */
395 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
396 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
398 switch (lpc2000_info
->variant
) {
402 init_reg_param(®_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
);
406 init_reg_param(®_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 */
410 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
, 0, 10000,
416 init_reg_param(®_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
);
420 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
421 buf_set_u32(reg_params
[4].value
, 0, 32, iap_working_area
->address
+ 0x04);
423 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
,
424 iap_working_area
->address
+ 0x4, 10000, &arm_algo
);
427 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
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);
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
);
441 destroy_mem_param(&mem_params
[0]);
442 destroy_mem_param(&mem_params
[1]);
444 destroy_reg_param(®_params
[0]);
445 destroy_reg_param(®_params
[1]);
446 destroy_reg_param(®_params
[2]);
447 destroy_reg_param(®_params
[3]);
448 destroy_reg_param(®_params
[4]);
453 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
455 if ((first
< 0) || (last
>= bank
->num_sectors
))
456 return ERROR_FLASH_SECTOR_INVALID
;
458 uint32_t param_table
[5] = {0};
459 uint32_t result_table
[4];
460 struct working_area
*iap_working_area
;
462 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
464 if (retval
!= ERROR_OK
)
467 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
468 if (lpc2000_info
->variant
== lpc4300
)
469 param_table
[2] = lpc2000_info
->lpc4300_bank
;
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
);
476 switch (status_code
) {
477 case ERROR_FLASH_OPERATION_FAILED
:
478 retval
= ERROR_FLASH_OPERATION_FAILED
;
480 case LPC2000_CMD_SUCCESS
:
481 bank
->sectors
[i
].is_erased
= 1;
483 case LPC2000_SECTOR_NOT_BLANK
:
484 bank
->sectors
[i
].is_erased
= 0;
486 case LPC2000_INVALID_SECTOR
:
487 bank
->sectors
[i
].is_erased
= 0;
490 retval
= ERROR_FLASH_BUSY
;
493 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
498 struct target
*target
= bank
->target
;
499 target_free_working_area(target
, iap_working_area
);
505 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
507 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
510 return ERROR_COMMAND_SYNTAX_ERROR
;
512 struct lpc2000_flash_bank
*lpc2000_info
= malloc(sizeof(struct lpc2000_flash_bank
));
513 bank
->driver_priv
= lpc2000_info
;
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;
544 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
546 return ERROR_FLASH_BANK_INVALID
;
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
;
552 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
553 lpc2000_info
->calc_checksum
= 0;
554 lpc2000_build_sector_list(bank
);
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 */
561 lpc2000_info
->lpc4300_bank
= 0; /* bank A */
564 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
565 lpc2000_info
->calc_checksum
= 1;
571 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
573 if (bank
->target
->state
!= TARGET_HALTED
) {
574 LOG_ERROR("Target not halted");
575 return ERROR_TARGET_NOT_HALTED
;
578 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
579 uint32_t param_table
[5] = {0};
581 param_table
[0] = first
;
582 param_table
[1] = last
;
584 if (lpc2000_info
->variant
== lpc4300
)
585 param_table
[2] = lpc2000_info
->lpc4300_bank
;
587 param_table
[2] = lpc2000_info
->cclk
;
589 uint32_t result_table
[4];
590 struct working_area
*iap_working_area
;
592 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
594 if (retval
!= ERROR_OK
)
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
;
603 case LPC2000_CMD_SUCCESS
:
605 case LPC2000_INVALID_SECTOR
:
606 retval
= ERROR_FLASH_SECTOR_INVALID
;
609 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
610 retval
= ERROR_FLASH_OPERATION_FAILED
;
614 if (retval
== ERROR_OK
) {
616 param_table
[2] = lpc2000_info
->cclk
;
617 if (lpc2000_info
->variant
== lpc4300
)
618 param_table
[3] = lpc2000_info
->lpc4300_bank
;
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
;
625 case LPC2000_CMD_SUCCESS
:
627 case LPC2000_INVALID_SECTOR
:
628 retval
= ERROR_FLASH_SECTOR_INVALID
;
631 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
632 retval
= ERROR_FLASH_OPERATION_FAILED
;
637 struct target
*target
= bank
->target
;
638 target_free_working_area(target
, iap_working_area
);
643 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
645 /* can't protect/unprotect on the lpc2000 */
649 static int lpc2000_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
651 struct target
*target
= bank
->target
;
653 if (bank
->target
->state
!= TARGET_HALTED
) {
654 LOG_ERROR("Target not halted");
655 return ERROR_TARGET_NOT_HALTED
;
658 if (offset
+ count
> bank
->size
)
659 return ERROR_FLASH_DST_OUT_OF_BANK
;
661 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
663 uint32_t dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
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
;
670 int first_sector
= 0;
673 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
674 if (offset
>= bank
->sectors
[i
].offset
)
676 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
680 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
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);
690 checksum
= 0 - checksum
;
691 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
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 "
701 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
704 struct working_area
*iap_working_area
;
706 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
708 if (retval
!= ERROR_OK
)
711 struct working_area
*download_area
;
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
;
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];
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
))
736 /* Prepare sectors */
737 param_table
[0] = first_sector
;
738 param_table
[1] = last_sector
;
740 if (lpc2000_info
->variant
== lpc4300
)
741 param_table
[2] = lpc2000_info
->lpc4300_bank
;
743 param_table
[2] = lpc2000_info
->cclk
;
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
;
750 case LPC2000_CMD_SUCCESS
:
752 case LPC2000_INVALID_SECTOR
:
753 retval
= ERROR_FLASH_SECTOR_INVALID
;
756 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
757 retval
= ERROR_FLASH_OPERATION_FAILED
;
761 /* Exit if error occured */
762 if (retval
!= ERROR_OK
)
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
;
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
);
779 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
,
780 bank
->base
+ offset
+ bytes_written
);
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
;
792 case LPC2000_CMD_SUCCESS
:
794 case LPC2000_INVALID_SECTOR
:
795 retval
= ERROR_FLASH_SECTOR_INVALID
;
798 LOG_WARNING("lpc2000 returned %i", status_code
);
799 retval
= ERROR_FLASH_OPERATION_FAILED
;
803 /* Exit if error occured */
804 if (retval
!= ERROR_OK
)
807 if (bytes_remaining
> thisrun_bytes
)
808 bytes_remaining
-= thisrun_bytes
;
811 bytes_written
+= thisrun_bytes
;
814 target_free_working_area(target
, iap_working_area
);
815 target_free_working_area(target
, download_area
);
820 static int lpc2000_probe(struct flash_bank
*bank
)
822 /* we can't probe on an lpc2000 if this is an lpc2xxx, it has the configured flash */
826 static int lpc2000_erase_check(struct flash_bank
*bank
)
828 if (bank
->target
->state
!= TARGET_HALTED
) {
829 LOG_ERROR("Target not halted");
830 return ERROR_TARGET_NOT_HALTED
;
833 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
836 static int lpc2000_protect_check(struct flash_bank
*bank
)
838 /* sectors are always protected */
842 static int get_lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
844 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
846 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz", lpc2000_info
->variant
,
852 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
855 return ERROR_COMMAND_SYNTAX_ERROR
;
857 struct flash_bank
*bank
;
858 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
859 if (ERROR_OK
!= retval
)
862 if (bank
->target
->state
!= TARGET_HALTED
) {
863 LOG_ERROR("Target not halted");
864 return ERROR_TARGET_NOT_HALTED
;
867 uint32_t param_table
[5] = {0};
868 uint32_t result_table
[4];
869 struct working_area
*iap_working_area
;
871 retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
873 if (retval
!= ERROR_OK
)
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");
881 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
883 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
888 static const struct command_registration lpc2000_exec_command_handlers
[] = {
891 .handler
= lpc2000_handle_part_id_command
,
892 .mode
= COMMAND_EXEC
,
893 .help
= "print part id of lpc2000 flash bank <num>",
896 COMMAND_REGISTRATION_DONE
898 static const struct command_registration lpc2000_command_handlers
[] = {
902 .help
= "lpc2000 flash command group",
904 .chain
= lpc2000_exec_command_handlers
,
906 COMMAND_REGISTRATION_DONE
909 struct flash_driver lpc2000_flash
= {
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
,
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)