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.
39 * The value which is correct after chip reset will rarely still work
40 * right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz).
43 * currently supported devices:
44 * variant 1 (lpc2000_v1):
52 * variant 2 (lpc2000_v2):
61 * - 176x (tested with LPC1768)
70 struct lpc2000_flash_bank
{
71 lpc2000_variant variant
;
72 struct working_area
*iap_working_area
;
74 int cmd51_dst_boundary
;
78 uint32_t cmd51_max_buffer
;
82 enum lpc2000_status_codes
{
83 LPC2000_CMD_SUCCESS
= 0,
84 LPC2000_INVALID_COMMAND
= 1,
85 LPC2000_SRC_ADDR_ERROR
= 2,
86 LPC2000_DST_ADDR_ERROR
= 3,
87 LPC2000_SRC_ADDR_NOT_MAPPED
= 4,
88 LPC2000_DST_ADDR_NOT_MAPPED
= 5,
89 LPC2000_COUNT_ERROR
= 6,
90 LPC2000_INVALID_SECTOR
= 7,
91 LPC2000_SECTOR_NOT_BLANK
= 8,
92 LPC2000_SECTOR_NOT_PREPARED
= 9,
93 LPC2000_COMPARE_ERROR
= 10,
95 LPC2000_PARAM_ERROR
= 12,
96 LPC2000_ADDR_ERROR
= 13,
97 LPC2000_ADDR_NOT_MAPPED
= 14,
98 LPC2000_CMD_NOT_LOCKED
= 15,
99 LPC2000_INVALID_CODE
= 16,
100 LPC2000_INVALID_BAUD_RATE
= 17,
101 LPC2000_INVALID_STOP_BIT
= 18,
102 LPC2000_CRP_ENABLED
= 19
105 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
107 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
111 /* default to a 4096 write buffer */
112 lpc2000_info
->cmd51_max_buffer
= 4096;
114 if (lpc2000_info
->variant
== lpc2000_v1
) {
115 /* variant 1 has different layout for 128kb and 256kb flashes */
116 if (bank
->size
== 128 * 1024) {
117 bank
->num_sectors
= 16;
118 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 16);
119 for (i
= 0; i
< 16; i
++) {
120 bank
->sectors
[i
].offset
= offset
;
121 bank
->sectors
[i
].size
= 8 * 1024;
122 offset
+= bank
->sectors
[i
].size
;
123 bank
->sectors
[i
].is_erased
= -1;
124 bank
->sectors
[i
].is_protected
= 1;
126 } else if (bank
->size
== 256 * 1024) {
127 bank
->num_sectors
= 18;
128 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
130 for (i
= 0; i
< 8; i
++) {
131 bank
->sectors
[i
].offset
= offset
;
132 bank
->sectors
[i
].size
= 8 * 1024;
133 offset
+= bank
->sectors
[i
].size
;
134 bank
->sectors
[i
].is_erased
= -1;
135 bank
->sectors
[i
].is_protected
= 1;
137 for (i
= 8; i
< 10; i
++) {
138 bank
->sectors
[i
].offset
= offset
;
139 bank
->sectors
[i
].size
= 64 * 1024;
140 offset
+= bank
->sectors
[i
].size
;
141 bank
->sectors
[i
].is_erased
= -1;
142 bank
->sectors
[i
].is_protected
= 1;
144 for (i
= 10; i
< 18; i
++) {
145 bank
->sectors
[i
].offset
= offset
;
146 bank
->sectors
[i
].size
= 8 * 1024;
147 offset
+= bank
->sectors
[i
].size
;
148 bank
->sectors
[i
].is_erased
= -1;
149 bank
->sectors
[i
].is_protected
= 1;
152 LOG_ERROR("BUG: unknown bank->size encountered");
155 } else if (lpc2000_info
->variant
== lpc2000_v2
) {
156 /* variant 2 has a uniform layout, only number of sectors differs */
157 switch (bank
->size
) {
159 lpc2000_info
->cmd51_max_buffer
= 1024;
160 bank
->num_sectors
= 1;
163 lpc2000_info
->cmd51_max_buffer
= 1024;
164 bank
->num_sectors
= 2;
167 bank
->num_sectors
= 4;
170 bank
->num_sectors
= 8;
173 bank
->num_sectors
= 9;
176 bank
->num_sectors
= 11;
179 bank
->num_sectors
= 15;
182 bank
->num_sectors
= 27;
186 bank
->num_sectors
= 28;
189 LOG_ERROR("BUG: unknown bank->size encountered");
194 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
196 for (i
= 0; i
< bank
->num_sectors
; i
++) {
198 bank
->sectors
[i
].offset
= offset
;
199 bank
->sectors
[i
].size
= 4 * 1024;
200 offset
+= bank
->sectors
[i
].size
;
201 bank
->sectors
[i
].is_erased
= -1;
202 bank
->sectors
[i
].is_protected
= 1;
204 bank
->sectors
[i
].offset
= offset
;
205 bank
->sectors
[i
].size
= 32 * 1024;
206 offset
+= bank
->sectors
[i
].size
;
207 bank
->sectors
[i
].is_erased
= -1;
208 bank
->sectors
[i
].is_protected
= 1;
210 bank
->sectors
[i
].offset
= offset
;
211 bank
->sectors
[i
].size
= 4 * 1024;
212 offset
+= bank
->sectors
[i
].size
;
213 bank
->sectors
[i
].is_erased
= -1;
214 bank
->sectors
[i
].is_protected
= 1;
217 } else if (lpc2000_info
->variant
== lpc1700
) {
218 switch (bank
->size
) {
220 bank
->num_sectors
= 8;
223 bank
->num_sectors
= 16;
226 bank
->num_sectors
= 18;
229 bank
->num_sectors
= 22;
232 bank
->num_sectors
= 30;
235 LOG_ERROR("BUG: unknown bank->size encountered");
239 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
241 for (i
= 0; i
< bank
->num_sectors
; i
++) {
242 bank
->sectors
[i
].offset
= offset
;
243 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx
245 bank
->sectors
[i
].size
= (i
< 16) ? 4 * 1024 : 32 * 1024;
246 offset
+= bank
->sectors
[i
].size
;
247 bank
->sectors
[i
].is_erased
= -1;
248 bank
->sectors
[i
].is_protected
= 1;
251 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
258 /* call LPC1700/LPC2000 IAP function
259 * uses 180 bytes working area
260 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
261 * 0x8 to 0x1f: command parameter table (1+5 words)
262 * 0x20 to 0x33: command result table (1+4 words)
263 * 0x34 to 0xb3: stack (only 128b needed)
265 static int lpc2000_iap_call(struct flash_bank
*bank
,
267 uint32_t param_table
[5],
268 uint32_t result_table
[4])
271 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
272 struct target
*target
= bank
->target
;
273 struct mem_param mem_params
[2];
274 struct reg_param reg_params
[5];
275 struct arm_algorithm armv4_5_info
; /* for LPC2000 */
276 struct armv7m_algorithm armv7m_info
; /* for LPC1700 */
277 uint32_t status_code
;
278 uint32_t iap_entry_point
= 0; /* to make compiler happier */
280 /* regrab previously allocated working_area, or allocate a new one */
281 if (!lpc2000_info
->iap_working_area
) {
282 uint8_t jump_gate
[8];
284 /* make sure we have a working area */
285 if (target_alloc_working_area(target
, 180,
286 &lpc2000_info
->iap_working_area
) != ERROR_OK
) {
287 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
288 return ERROR_FLASH_OPERATION_FAILED
;
291 /* write IAP code to working area */
292 switch (lpc2000_info
->variant
) {
294 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_T_BX(12));
295 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV5_T_BKPT(0));
299 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
300 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
303 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
307 retval
= target_write_memory(target
,
308 lpc2000_info
->iap_working_area
->address
, 4, 2, jump_gate
);
309 if (retval
!= ERROR_OK
) {
311 "Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)",
312 lpc2000_info
->iap_working_area
->address
);
317 switch (lpc2000_info
->variant
) {
319 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
320 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
321 iap_entry_point
= 0x1fff1ff1;
325 armv4_5_info
.common_magic
= ARM_COMMON_MAGIC
;
326 armv4_5_info
.core_mode
= ARM_MODE_SVC
;
327 armv4_5_info
.core_state
= ARM_STATE_ARM
;
328 iap_entry_point
= 0x7ffffff1;
331 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
335 /* command parameter table */
336 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 6 * 4,
338 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
339 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
340 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
341 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
342 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
343 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
345 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
346 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x08);
348 /* command result table */
349 init_mem_param(&mem_params
[1],
350 lpc2000_info
->iap_working_area
->address
+ 0x20,
354 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
355 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
357 /* IAP entry point */
358 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
359 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
361 switch (lpc2000_info
->variant
) {
364 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
365 buf_set_u32(reg_params
[3].value
, 0, 32,
366 lpc2000_info
->iap_working_area
->address
+ 0xb4);
369 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
370 buf_set_u32(reg_params
[4].value
, 0, 32,
371 (lpc2000_info
->iap_working_area
->address
+ 0x04) | 1);
372 /* bit0 of LR = 1 to return in Thumb mode */
374 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
,
375 lpc2000_info
->iap_working_area
->address
, 0, 10000, &armv7m_info
);
380 init_reg_param(®_params
[3], "sp_svc", 32, PARAM_OUT
);
381 buf_set_u32(reg_params
[3].value
, 0, 32,
382 lpc2000_info
->iap_working_area
->address
+ 0xb4);
385 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
386 buf_set_u32(reg_params
[4].value
, 0, 32,
387 lpc2000_info
->iap_working_area
->address
+ 0x04);
389 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
,
390 lpc2000_info
->iap_working_area
->address
,
391 lpc2000_info
->iap_working_area
->address
+ 0x4,
392 10000, &armv4_5_info
);
395 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
399 status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
400 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
401 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
402 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
403 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
405 LOG_DEBUG("IAP command = %i (0x%8.8" PRIx32
", 0x%8.8" PRIx32
406 ", 0x%8.8" PRIx32
", 0x%8.8" PRIx32
", 0x%8.8"
407 PRIx32
") completed with result = %8.8" PRIx32
,
408 code
, param_table
[0], param_table
[1], param_table
[2],
409 param_table
[3], param_table
[4], status_code
);
411 destroy_mem_param(&mem_params
[0]);
412 destroy_mem_param(&mem_params
[1]);
414 destroy_reg_param(®_params
[0]);
415 destroy_reg_param(®_params
[1]);
416 destroy_reg_param(®_params
[2]);
417 destroy_reg_param(®_params
[3]);
418 destroy_reg_param(®_params
[4]);
423 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
425 uint32_t param_table
[5];
426 uint32_t result_table
[4];
430 if ((first
< 0) || (last
>= bank
->num_sectors
))
431 return ERROR_FLASH_SECTOR_INVALID
;
433 for (i
= first
; i
<= last
; i
++) {
434 /* check single sector */
435 param_table
[0] = param_table
[1] = i
;
436 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
438 switch (status_code
) {
439 case ERROR_FLASH_OPERATION_FAILED
:
440 return ERROR_FLASH_OPERATION_FAILED
;
441 case LPC2000_CMD_SUCCESS
:
442 bank
->sectors
[i
].is_erased
= 1;
444 case LPC2000_SECTOR_NOT_BLANK
:
445 bank
->sectors
[i
].is_erased
= 0;
447 case LPC2000_INVALID_SECTOR
:
448 bank
->sectors
[i
].is_erased
= 0;
451 return ERROR_FLASH_BUSY
;
454 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
463 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
465 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
467 struct lpc2000_flash_bank
*lpc2000_info
;
470 return ERROR_COMMAND_SYNTAX_ERROR
;
472 lpc2000_info
= malloc(sizeof(struct lpc2000_flash_bank
));
473 bank
->driver_priv
= lpc2000_info
;
475 if (strcmp(CMD_ARGV
[6], "lpc2000_v1") == 0) {
476 lpc2000_info
->variant
= lpc2000_v1
;
477 lpc2000_info
->cmd51_dst_boundary
= 512;
478 lpc2000_info
->cmd51_can_256b
= 0;
479 lpc2000_info
->cmd51_can_8192b
= 1;
480 lpc2000_info
->checksum_vector
= 5;
481 } else if (strcmp(CMD_ARGV
[6], "lpc2000_v2") == 0) {
482 lpc2000_info
->variant
= lpc2000_v2
;
483 lpc2000_info
->cmd51_dst_boundary
= 256;
484 lpc2000_info
->cmd51_can_256b
= 1;
485 lpc2000_info
->cmd51_can_8192b
= 0;
486 lpc2000_info
->checksum_vector
= 5;
487 } else if (strcmp(CMD_ARGV
[6], "lpc1700") == 0) {
488 lpc2000_info
->variant
= lpc1700
;
489 lpc2000_info
->cmd51_dst_boundary
= 256;
490 lpc2000_info
->cmd51_can_256b
= 1;
491 lpc2000_info
->cmd51_can_8192b
= 0;
492 lpc2000_info
->checksum_vector
= 7;
494 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
496 return ERROR_FLASH_BANK_INVALID
;
499 lpc2000_info
->iap_working_area
= NULL
;
500 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
501 lpc2000_info
->calc_checksum
= 0;
502 lpc2000_build_sector_list(bank
);
505 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
506 lpc2000_info
->calc_checksum
= 1;
512 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
514 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
515 uint32_t param_table
[5];
516 uint32_t result_table
[4];
519 if (bank
->target
->state
!= TARGET_HALTED
) {
520 LOG_ERROR("Target not halted");
521 return ERROR_TARGET_NOT_HALTED
;
524 param_table
[0] = first
;
525 param_table
[1] = last
;
526 param_table
[2] = lpc2000_info
->cclk
;
528 /* Prepare sectors */
529 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
530 switch (status_code
) {
531 case ERROR_FLASH_OPERATION_FAILED
:
532 return ERROR_FLASH_OPERATION_FAILED
;
533 case LPC2000_CMD_SUCCESS
:
535 case LPC2000_INVALID_SECTOR
:
536 return ERROR_FLASH_SECTOR_INVALID
;
539 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
540 return ERROR_FLASH_OPERATION_FAILED
;
544 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
545 switch (status_code
) {
546 case ERROR_FLASH_OPERATION_FAILED
:
547 return ERROR_FLASH_OPERATION_FAILED
;
548 case LPC2000_CMD_SUCCESS
:
550 case LPC2000_INVALID_SECTOR
:
551 return ERROR_FLASH_SECTOR_INVALID
;
554 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
555 return ERROR_FLASH_OPERATION_FAILED
;
561 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
563 /* can't protect/unprotect on the lpc2000 */
567 static int lpc2000_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
569 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
570 struct target
*target
= bank
->target
;
571 uint32_t dst_min_alignment
;
572 uint32_t bytes_remaining
= count
;
573 uint32_t bytes_written
= 0;
574 int first_sector
= 0;
576 uint32_t param_table
[5];
577 uint32_t result_table
[4];
580 struct working_area
*download_area
;
581 int retval
= ERROR_OK
;
583 if (bank
->target
->state
!= TARGET_HALTED
) {
584 LOG_ERROR("Target not halted");
585 return ERROR_TARGET_NOT_HALTED
;
588 if (offset
+ count
> bank
->size
)
589 return ERROR_FLASH_DST_OUT_OF_BANK
;
591 dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
593 if (offset
% dst_min_alignment
) {
594 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
,
597 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
600 for (i
= 0; i
< bank
->num_sectors
; i
++) {
601 if (offset
>= bank
->sectors
[i
].offset
)
603 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
)
604 * dst_min_alignment
> bank
->sectors
[i
].offset
)
608 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
610 /* check if exception vectors should be flashed */
611 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
) {
612 uint32_t checksum
= 0;
613 for (i
= 0; i
< 8; i
++) {
614 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4,
615 buf_get_u32(buffer
+ (i
* 4), 0, 32));
616 if (i
!= lpc2000_info
->checksum_vector
)
617 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
619 checksum
= 0 - checksum
;
620 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
622 uint32_t original_value
= buf_get_u32(buffer
+
623 (lpc2000_info
->checksum_vector
* 4), 0, 32);
624 if (original_value
!= checksum
) {
625 LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32
") "
626 "to be written to flash is different from calculated vector "
627 "checksum (0x%8.8" PRIx32
").", original_value
, checksum
);
628 LOG_WARNING("To remove this warning modify build tools on developer PC "
629 "to inject correct LPC vector checksum.");
632 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
635 /* allocate a working area */
636 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
,
637 &download_area
) != ERROR_OK
) {
638 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
639 return ERROR_FLASH_OPERATION_FAILED
;
642 while (bytes_remaining
> 0) {
643 uint32_t thisrun_bytes
;
644 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
645 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
646 else if (bytes_remaining
>= 1024)
647 thisrun_bytes
= 1024;
648 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
653 /* Prepare sectors */
654 param_table
[0] = first_sector
;
655 param_table
[1] = last_sector
;
656 status_code
= lpc2000_iap_call(bank
, 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 /* Exit if error occured */
673 if (retval
!= ERROR_OK
)
676 if (bytes_remaining
>= thisrun_bytes
) {
677 retval
= target_write_buffer(bank
->target
, download_area
->address
,
678 thisrun_bytes
, buffer
+ bytes_written
);
679 if (retval
!= ERROR_OK
) {
680 retval
= ERROR_FLASH_OPERATION_FAILED
;
684 uint8_t *last_buffer
= malloc(thisrun_bytes
);
685 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
686 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
-
688 target_write_buffer(bank
->target
,
689 download_area
->address
,
695 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
,
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
, 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
, download_area
);
736 static int lpc2000_probe(struct flash_bank
*bank
)
738 /* we can't probe on an lpc2000
739 * if this is an lpc2xxx, it has the configured flash
744 static int lpc2000_erase_check(struct flash_bank
*bank
)
746 if (bank
->target
->state
!= TARGET_HALTED
) {
747 LOG_ERROR("Target not halted");
748 return ERROR_TARGET_NOT_HALTED
;
751 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
754 static int lpc2000_protect_check(struct flash_bank
*bank
)
756 /* sectors are always protected */
760 static int get_lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
762 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
766 "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz",
767 lpc2000_info
->variant
,
773 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
775 uint32_t param_table
[5];
776 uint32_t result_table
[4];
780 return ERROR_COMMAND_SYNTAX_ERROR
;
782 struct flash_bank
*bank
;
783 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
784 if (ERROR_OK
!= retval
)
787 if (bank
->target
->state
!= TARGET_HALTED
) {
788 LOG_ERROR("Target not halted");
789 return ERROR_TARGET_NOT_HALTED
;
792 status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
);
793 if (status_code
!= 0x0) {
794 if (status_code
== ERROR_FLASH_OPERATION_FAILED
) {
795 command_print(CMD_CTX
,
796 "no sufficient working area specified, can't access LPC2000 IAP interface");
799 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
801 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
806 static const struct command_registration lpc2000_exec_command_handlers
[] = {
809 .handler
= lpc2000_handle_part_id_command
,
810 .mode
= COMMAND_EXEC
,
811 .help
= "print part id of lpc2000 flash bank <num>",
814 COMMAND_REGISTRATION_DONE
816 static const struct command_registration lpc2000_command_handlers
[] = {
820 .help
= "lpc2000 flash command group",
822 .chain
= lpc2000_exec_command_handlers
,
824 COMMAND_REGISTRATION_DONE
827 struct flash_driver lpc2000_flash
= {
829 .commands
= lpc2000_command_handlers
,
830 .flash_bank_command
= lpc2000_flash_bank_command
,
831 .erase
= lpc2000_erase
,
832 .protect
= lpc2000_protect
,
833 .write
= lpc2000_write
,
834 .read
= default_flash_read
,
835 .probe
= lpc2000_probe
,
836 .auto_probe
= lpc2000_probe
,
837 .erase_check
= lpc2000_erase_check
,
838 .protect_check
= lpc2000_protect_check
,
839 .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)