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)
69 struct lpc2000_flash_bank
{
70 lpc2000_variant variant
;
72 int cmd51_dst_boundary
;
76 uint32_t cmd51_max_buffer
;
80 enum lpc2000_status_codes
{
81 LPC2000_CMD_SUCCESS
= 0,
82 LPC2000_INVALID_COMMAND
= 1,
83 LPC2000_SRC_ADDR_ERROR
= 2,
84 LPC2000_DST_ADDR_ERROR
= 3,
85 LPC2000_SRC_ADDR_NOT_MAPPED
= 4,
86 LPC2000_DST_ADDR_NOT_MAPPED
= 5,
87 LPC2000_COUNT_ERROR
= 6,
88 LPC2000_INVALID_SECTOR
= 7,
89 LPC2000_SECTOR_NOT_BLANK
= 8,
90 LPC2000_SECTOR_NOT_PREPARED
= 9,
91 LPC2000_COMPARE_ERROR
= 10,
93 LPC2000_PARAM_ERROR
= 12,
94 LPC2000_ADDR_ERROR
= 13,
95 LPC2000_ADDR_NOT_MAPPED
= 14,
96 LPC2000_CMD_NOT_LOCKED
= 15,
97 LPC2000_INVALID_CODE
= 16,
98 LPC2000_INVALID_BAUD_RATE
= 17,
99 LPC2000_INVALID_STOP_BIT
= 18,
100 LPC2000_CRP_ENABLED
= 19
103 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
105 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
108 /* default to a 4096 write buffer */
109 lpc2000_info
->cmd51_max_buffer
= 4096;
111 if (lpc2000_info
->variant
== lpc2000_v1
) {
112 /* variant 1 has different layout for 128kb and 256kb flashes */
113 if (bank
->size
== 128 * 1024) {
114 bank
->num_sectors
= 16;
115 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 16);
116 for (int i
= 0; i
< 16; i
++) {
117 bank
->sectors
[i
].offset
= offset
;
118 bank
->sectors
[i
].size
= 8 * 1024;
119 offset
+= bank
->sectors
[i
].size
;
120 bank
->sectors
[i
].is_erased
= -1;
121 bank
->sectors
[i
].is_protected
= 1;
123 } else if (bank
->size
== 256 * 1024) {
124 bank
->num_sectors
= 18;
125 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
127 for (int i
= 0; i
< 8; 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 for (int i
= 8; i
< 10; i
++) {
135 bank
->sectors
[i
].offset
= offset
;
136 bank
->sectors
[i
].size
= 64 * 1024;
137 offset
+= bank
->sectors
[i
].size
;
138 bank
->sectors
[i
].is_erased
= -1;
139 bank
->sectors
[i
].is_protected
= 1;
141 for (int i
= 10; i
< 18; i
++) {
142 bank
->sectors
[i
].offset
= offset
;
143 bank
->sectors
[i
].size
= 8 * 1024;
144 offset
+= bank
->sectors
[i
].size
;
145 bank
->sectors
[i
].is_erased
= -1;
146 bank
->sectors
[i
].is_protected
= 1;
149 LOG_ERROR("BUG: unknown bank->size encountered");
152 } else if (lpc2000_info
->variant
== lpc2000_v2
) {
153 /* variant 2 has a uniform layout, only number of sectors differs */
154 switch (bank
->size
) {
156 lpc2000_info
->cmd51_max_buffer
= 1024;
157 bank
->num_sectors
= 1;
160 lpc2000_info
->cmd51_max_buffer
= 1024;
161 bank
->num_sectors
= 2;
164 bank
->num_sectors
= 4;
167 bank
->num_sectors
= 8;
170 bank
->num_sectors
= 9;
173 bank
->num_sectors
= 11;
176 bank
->num_sectors
= 15;
179 bank
->num_sectors
= 27;
183 bank
->num_sectors
= 28;
186 LOG_ERROR("BUG: unknown bank->size encountered");
191 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
193 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
195 bank
->sectors
[i
].offset
= offset
;
196 bank
->sectors
[i
].size
= 4 * 1024;
197 offset
+= bank
->sectors
[i
].size
;
198 bank
->sectors
[i
].is_erased
= -1;
199 bank
->sectors
[i
].is_protected
= 1;
201 bank
->sectors
[i
].offset
= offset
;
202 bank
->sectors
[i
].size
= 32 * 1024;
203 offset
+= bank
->sectors
[i
].size
;
204 bank
->sectors
[i
].is_erased
= -1;
205 bank
->sectors
[i
].is_protected
= 1;
207 bank
->sectors
[i
].offset
= offset
;
208 bank
->sectors
[i
].size
= 4 * 1024;
209 offset
+= bank
->sectors
[i
].size
;
210 bank
->sectors
[i
].is_erased
= -1;
211 bank
->sectors
[i
].is_protected
= 1;
214 } else if (lpc2000_info
->variant
== lpc1700
) {
215 switch (bank
->size
) {
217 bank
->num_sectors
= 8;
220 bank
->num_sectors
= 16;
223 bank
->num_sectors
= 18;
226 bank
->num_sectors
= 22;
229 bank
->num_sectors
= 30;
232 LOG_ERROR("BUG: unknown bank->size encountered");
236 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
238 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
239 bank
->sectors
[i
].offset
= offset
;
240 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
241 bank
->sectors
[i
].size
= (i
< 16) ? 4 * 1024 : 32 * 1024;
242 offset
+= bank
->sectors
[i
].size
;
243 bank
->sectors
[i
].is_erased
= -1;
244 bank
->sectors
[i
].is_protected
= 1;
247 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
254 /* this function allocates and initializes working area used for IAP algorithm
255 * uses 180 bytes working area
256 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
257 * 0x8 to 0x1f: command parameter table (1+5 words)
258 * 0x20 to 0x33: command result table (1+4 words)
259 * 0x34 to 0xb3: stack (only 128b needed)
262 static int lpc2000_iap_working_area_init(struct flash_bank
*bank
, struct working_area
**iap_working_area
)
264 struct target
*target
= bank
->target
;
266 if (target_alloc_working_area(target
, 180, iap_working_area
) != ERROR_OK
) {
267 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
268 return ERROR_FLASH_OPERATION_FAILED
;
271 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
272 uint8_t jump_gate
[8];
274 /* write IAP code to working area */
275 switch (lpc2000_info
->variant
) {
277 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_T_BX(12));
278 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV5_T_BKPT(0));
282 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
283 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
286 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
290 int retval
= target_write_memory(target
, (*iap_working_area
)->address
, 4, 2, jump_gate
);
291 if (retval
!= ERROR_OK
)
292 LOG_ERROR("Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)",
293 (*iap_working_area
)->address
);
298 /* call LPC1700/LPC2000 IAP function */
300 static int lpc2000_iap_call(struct flash_bank
*bank
, struct working_area
*iap_working_area
, int code
,
301 uint32_t param_table
[5], uint32_t result_table
[4])
303 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
305 struct arm_algorithm arm_algo
; /* for LPC2000 */
306 struct armv7m_algorithm armv7m_info
; /* for LPC1700 */
307 uint32_t iap_entry_point
= 0; /* to make compiler happier */
309 switch (lpc2000_info
->variant
) {
311 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
312 armv7m_info
.core_mode
= ARM_MODE_ANY
;
313 iap_entry_point
= 0x1fff1ff1;
317 arm_algo
.common_magic
= ARM_COMMON_MAGIC
;
318 arm_algo
.core_mode
= ARM_MODE_SVC
;
319 arm_algo
.core_state
= ARM_STATE_ARM
;
320 iap_entry_point
= 0x7ffffff1;
323 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
327 struct target
*target
= bank
->target
;
328 struct mem_param mem_params
[2];
330 /* command parameter table */
331 init_mem_param(&mem_params
[0], iap_working_area
->address
+ 8, 6 * 4, PARAM_OUT
);
332 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
333 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
334 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
335 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
336 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
337 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
339 struct reg_param reg_params
[5];
341 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
342 buf_set_u32(reg_params
[0].value
, 0, 32, iap_working_area
->address
+ 0x08);
344 /* command result table */
345 init_mem_param(&mem_params
[1], iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
347 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
348 buf_set_u32(reg_params
[1].value
, 0, 32, iap_working_area
->address
+ 0x20);
350 /* IAP entry point */
351 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
352 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
354 switch (lpc2000_info
->variant
) {
357 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
358 buf_set_u32(reg_params
[3].value
, 0, 32, iap_working_area
->address
+ 0xb4);
361 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
362 buf_set_u32(reg_params
[4].value
, 0, 32, (iap_working_area
->address
+ 0x04) | 1);
363 /* bit0 of LR = 1 to return in Thumb mode */
365 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
, 0, 10000,
371 init_reg_param(®_params
[3], "sp_svc", 32, PARAM_OUT
);
372 buf_set_u32(reg_params
[3].value
, 0, 32, iap_working_area
->address
+ 0xb4);
375 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
376 buf_set_u32(reg_params
[4].value
, 0, 32, iap_working_area
->address
+ 0x04);
378 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, iap_working_area
->address
,
379 iap_working_area
->address
+ 0x4, 10000, &arm_algo
);
382 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
386 int status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
387 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
388 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
389 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
390 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
392 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
393 ") completed with result = %8.8" PRIx32
,
394 code
, param_table
[0], param_table
[1], param_table
[2], param_table
[3], param_table
[4], status_code
);
396 destroy_mem_param(&mem_params
[0]);
397 destroy_mem_param(&mem_params
[1]);
399 destroy_reg_param(®_params
[0]);
400 destroy_reg_param(®_params
[1]);
401 destroy_reg_param(®_params
[2]);
402 destroy_reg_param(®_params
[3]);
403 destroy_reg_param(®_params
[4]);
408 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
410 if ((first
< 0) || (last
>= bank
->num_sectors
))
411 return ERROR_FLASH_SECTOR_INVALID
;
413 uint32_t param_table
[5] = {0};
414 uint32_t result_table
[4];
415 struct working_area
*iap_working_area
;
417 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
419 if (retval
!= ERROR_OK
)
422 for (int i
= first
; i
<= last
&& retval
== ERROR_OK
; i
++) {
423 /* check single sector */
424 param_table
[0] = param_table
[1] = i
;
425 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 53, param_table
, result_table
);
427 switch (status_code
) {
428 case ERROR_FLASH_OPERATION_FAILED
:
429 retval
= ERROR_FLASH_OPERATION_FAILED
;
431 case LPC2000_CMD_SUCCESS
:
432 bank
->sectors
[i
].is_erased
= 1;
434 case LPC2000_SECTOR_NOT_BLANK
:
435 bank
->sectors
[i
].is_erased
= 0;
437 case LPC2000_INVALID_SECTOR
:
438 bank
->sectors
[i
].is_erased
= 0;
441 retval
= ERROR_FLASH_BUSY
;
444 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
449 struct target
*target
= bank
->target
;
450 target_free_working_area(target
, iap_working_area
);
456 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
458 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
461 return ERROR_COMMAND_SYNTAX_ERROR
;
463 struct lpc2000_flash_bank
*lpc2000_info
= malloc(sizeof(struct lpc2000_flash_bank
));
464 bank
->driver_priv
= lpc2000_info
;
466 if (strcmp(CMD_ARGV
[6], "lpc2000_v1") == 0) {
467 lpc2000_info
->variant
= lpc2000_v1
;
468 lpc2000_info
->cmd51_dst_boundary
= 512;
469 lpc2000_info
->cmd51_can_256b
= 0;
470 lpc2000_info
->cmd51_can_8192b
= 1;
471 lpc2000_info
->checksum_vector
= 5;
472 } else if (strcmp(CMD_ARGV
[6], "lpc2000_v2") == 0) {
473 lpc2000_info
->variant
= lpc2000_v2
;
474 lpc2000_info
->cmd51_dst_boundary
= 256;
475 lpc2000_info
->cmd51_can_256b
= 1;
476 lpc2000_info
->cmd51_can_8192b
= 0;
477 lpc2000_info
->checksum_vector
= 5;
478 } else if (strcmp(CMD_ARGV
[6], "lpc1700") == 0) {
479 lpc2000_info
->variant
= lpc1700
;
480 lpc2000_info
->cmd51_dst_boundary
= 256;
481 lpc2000_info
->cmd51_can_256b
= 1;
482 lpc2000_info
->cmd51_can_8192b
= 0;
483 lpc2000_info
->checksum_vector
= 7;
485 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
487 return ERROR_FLASH_BANK_INVALID
;
490 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
491 lpc2000_info
->calc_checksum
= 0;
492 lpc2000_build_sector_list(bank
);
495 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
496 lpc2000_info
->calc_checksum
= 1;
502 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
504 if (bank
->target
->state
!= TARGET_HALTED
) {
505 LOG_ERROR("Target not halted");
506 return ERROR_TARGET_NOT_HALTED
;
509 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
510 uint32_t param_table
[5] = {0};
512 param_table
[0] = first
;
513 param_table
[1] = last
;
514 param_table
[2] = lpc2000_info
->cclk
;
516 uint32_t result_table
[4];
517 struct working_area
*iap_working_area
;
519 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
521 if (retval
!= ERROR_OK
)
524 /* Prepare sectors */
525 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 50, 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
:
532 case LPC2000_INVALID_SECTOR
:
533 retval
= ERROR_FLASH_SECTOR_INVALID
;
536 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
537 retval
= ERROR_FLASH_OPERATION_FAILED
;
541 if (retval
== ERROR_OK
) {
543 status_code
= lpc2000_iap_call(bank
, iap_working_area
, 52, param_table
, result_table
);
544 switch (status_code
) {
545 case ERROR_FLASH_OPERATION_FAILED
:
546 retval
= ERROR_FLASH_OPERATION_FAILED
;
548 case LPC2000_CMD_SUCCESS
:
550 case LPC2000_INVALID_SECTOR
:
551 retval
= ERROR_FLASH_SECTOR_INVALID
;
554 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
555 retval
= ERROR_FLASH_OPERATION_FAILED
;
560 struct target
*target
= bank
->target
;
561 target_free_working_area(target
, iap_working_area
);
566 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
568 /* can't protect/unprotect on the lpc2000 */
572 static int lpc2000_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
574 struct target
*target
= bank
->target
;
576 if (bank
->target
->state
!= TARGET_HALTED
) {
577 LOG_ERROR("Target not halted");
578 return ERROR_TARGET_NOT_HALTED
;
581 if (offset
+ count
> bank
->size
)
582 return ERROR_FLASH_DST_OUT_OF_BANK
;
584 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
586 uint32_t dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
588 if (offset
% dst_min_alignment
) {
589 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
, offset
, dst_min_alignment
);
590 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
593 int first_sector
= 0;
596 for (int i
= 0; i
< bank
->num_sectors
; i
++) {
597 if (offset
>= bank
->sectors
[i
].offset
)
599 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
603 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
605 /* check if exception vectors should be flashed */
606 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
) {
607 uint32_t checksum
= 0;
608 for (int i
= 0; i
< 8; i
++) {
609 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
610 if (i
!= lpc2000_info
->checksum_vector
)
611 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
613 checksum
= 0 - checksum
;
614 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
616 uint32_t original_value
= buf_get_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32);
617 if (original_value
!= checksum
) {
618 LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32
") to be written to flash is "
619 "different from calculated vector checksum (0x%8.8" PRIx32
").", original_value
, checksum
);
620 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector "
624 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
627 struct working_area
*iap_working_area
;
629 int retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
631 if (retval
!= ERROR_OK
)
634 struct working_area
*download_area
;
636 /* allocate a working area */
637 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
) {
638 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
639 target_free_working_area(target
, iap_working_area
);
640 return ERROR_FLASH_OPERATION_FAILED
;
643 uint32_t bytes_remaining
= count
;
644 uint32_t bytes_written
= 0;
645 uint32_t param_table
[5] = {0};
646 uint32_t result_table
[4];
648 while (bytes_remaining
> 0) {
649 uint32_t thisrun_bytes
;
650 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
651 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
652 else if (bytes_remaining
>= 1024)
653 thisrun_bytes
= 1024;
654 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
659 /* Prepare sectors */
660 param_table
[0] = first_sector
;
661 param_table
[1] = last_sector
;
662 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 50, param_table
, result_table
);
663 switch (status_code
) {
664 case ERROR_FLASH_OPERATION_FAILED
:
665 retval
= ERROR_FLASH_OPERATION_FAILED
;
667 case LPC2000_CMD_SUCCESS
:
669 case LPC2000_INVALID_SECTOR
:
670 retval
= ERROR_FLASH_SECTOR_INVALID
;
673 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
674 retval
= ERROR_FLASH_OPERATION_FAILED
;
678 /* Exit if error occured */
679 if (retval
!= ERROR_OK
)
682 if (bytes_remaining
>= thisrun_bytes
) {
683 retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
);
684 if (retval
!= ERROR_OK
) {
685 retval
= ERROR_FLASH_OPERATION_FAILED
;
689 uint8_t *last_buffer
= malloc(thisrun_bytes
);
690 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
691 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
- bytes_remaining
);
692 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
696 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
,
697 bank
->base
+ offset
+ bytes_written
);
700 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
701 param_table
[1] = download_area
->address
;
702 param_table
[2] = thisrun_bytes
;
703 param_table
[3] = lpc2000_info
->cclk
;
704 status_code
= lpc2000_iap_call(bank
, iap_working_area
, 51, param_table
, result_table
);
705 switch (status_code
) {
706 case ERROR_FLASH_OPERATION_FAILED
:
707 retval
= ERROR_FLASH_OPERATION_FAILED
;
709 case LPC2000_CMD_SUCCESS
:
711 case LPC2000_INVALID_SECTOR
:
712 retval
= ERROR_FLASH_SECTOR_INVALID
;
715 LOG_WARNING("lpc2000 returned %i", status_code
);
716 retval
= ERROR_FLASH_OPERATION_FAILED
;
720 /* Exit if error occured */
721 if (retval
!= ERROR_OK
)
724 if (bytes_remaining
> thisrun_bytes
)
725 bytes_remaining
-= thisrun_bytes
;
728 bytes_written
+= thisrun_bytes
;
731 target_free_working_area(target
, iap_working_area
);
732 target_free_working_area(target
, download_area
);
737 static int lpc2000_probe(struct flash_bank
*bank
)
739 /* we can't probe on an lpc2000 if this is an lpc2xxx, it has the configured flash */
743 static int lpc2000_erase_check(struct flash_bank
*bank
)
745 if (bank
->target
->state
!= TARGET_HALTED
) {
746 LOG_ERROR("Target not halted");
747 return ERROR_TARGET_NOT_HALTED
;
750 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
753 static int lpc2000_protect_check(struct flash_bank
*bank
)
755 /* sectors are always protected */
759 static int get_lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
761 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
763 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz", lpc2000_info
->variant
,
769 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
772 return ERROR_COMMAND_SYNTAX_ERROR
;
774 struct flash_bank
*bank
;
775 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
776 if (ERROR_OK
!= retval
)
779 if (bank
->target
->state
!= TARGET_HALTED
) {
780 LOG_ERROR("Target not halted");
781 return ERROR_TARGET_NOT_HALTED
;
784 uint32_t param_table
[5] = {0};
785 uint32_t result_table
[4];
786 struct working_area
*iap_working_area
;
788 retval
= lpc2000_iap_working_area_init(bank
, &iap_working_area
);
790 if (retval
!= ERROR_OK
)
793 int status_code
= lpc2000_iap_call(bank
, iap_working_area
, 54, param_table
, result_table
);
794 if (status_code
!= 0x0) {
795 if (status_code
== ERROR_FLASH_OPERATION_FAILED
) {
796 command_print(CMD_CTX
, "no sufficient working area specified, can't access LPC2000 IAP interface");
798 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
800 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
805 static const struct command_registration lpc2000_exec_command_handlers
[] = {
808 .handler
= lpc2000_handle_part_id_command
,
809 .mode
= COMMAND_EXEC
,
810 .help
= "print part id of lpc2000 flash bank <num>",
813 COMMAND_REGISTRATION_DONE
815 static const struct command_registration lpc2000_command_handlers
[] = {
819 .help
= "lpc2000 flash command group",
821 .chain
= lpc2000_exec_command_handlers
,
823 COMMAND_REGISTRATION_DONE
826 struct flash_driver lpc2000_flash
= {
828 .commands
= lpc2000_command_handlers
,
829 .flash_bank_command
= lpc2000_flash_bank_command
,
830 .erase
= lpc2000_erase
,
831 .protect
= lpc2000_protect
,
832 .write
= lpc2000_write
,
833 .read
= default_flash_read
,
834 .probe
= lpc2000_probe
,
835 .auto_probe
= lpc2000_probe
,
836 .erase_check
= lpc2000_erase_check
,
837 .protect_check
= lpc2000_protect_check
,
838 .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)