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)
71 struct lpc2000_flash_bank
73 lpc2000_variant variant
;
74 struct working_area
*iap_working_area
;
76 int cmd51_dst_boundary
;
80 uint32_t cmd51_max_buffer
;
84 enum lpc2000_status_codes
86 LPC2000_CMD_SUCCESS
= 0,
87 LPC2000_INVALID_COMMAND
= 1,
88 LPC2000_SRC_ADDR_ERROR
= 2,
89 LPC2000_DST_ADDR_ERROR
= 3,
90 LPC2000_SRC_ADDR_NOT_MAPPED
= 4,
91 LPC2000_DST_ADDR_NOT_MAPPED
= 5,
92 LPC2000_COUNT_ERROR
= 6,
93 LPC2000_INVALID_SECTOR
= 7,
94 LPC2000_SECTOR_NOT_BLANK
= 8,
95 LPC2000_SECTOR_NOT_PREPARED
= 9,
96 LPC2000_COMPARE_ERROR
= 10,
98 LPC2000_PARAM_ERROR
= 12,
99 LPC2000_ADDR_ERROR
= 13,
100 LPC2000_ADDR_NOT_MAPPED
= 14,
101 LPC2000_CMD_NOT_LOCKED
= 15,
102 LPC2000_INVALID_CODE
= 16,
103 LPC2000_INVALID_BAUD_RATE
= 17,
104 LPC2000_INVALID_STOP_BIT
= 18,
105 LPC2000_CRP_ENABLED
= 19
108 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
110 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
114 /* default to a 4096 write buffer */
115 lpc2000_info
->cmd51_max_buffer
= 4096;
117 if (lpc2000_info
->variant
== lpc2000_v1
)
119 /* variant 1 has different layout for 128kb and 256kb flashes */
120 if (bank
->size
== 128 * 1024)
122 bank
->num_sectors
= 16;
123 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 16);
124 for (i
= 0; i
< 16; i
++)
126 bank
->sectors
[i
].offset
= offset
;
127 bank
->sectors
[i
].size
= 8 * 1024;
128 offset
+= bank
->sectors
[i
].size
;
129 bank
->sectors
[i
].is_erased
= -1;
130 bank
->sectors
[i
].is_protected
= 1;
133 else if (bank
->size
== 256 * 1024)
135 bank
->num_sectors
= 18;
136 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
138 for (i
= 0; i
< 8; i
++)
140 bank
->sectors
[i
].offset
= offset
;
141 bank
->sectors
[i
].size
= 8 * 1024;
142 offset
+= bank
->sectors
[i
].size
;
143 bank
->sectors
[i
].is_erased
= -1;
144 bank
->sectors
[i
].is_protected
= 1;
146 for (i
= 8; i
< 10; i
++)
148 bank
->sectors
[i
].offset
= offset
;
149 bank
->sectors
[i
].size
= 64 * 1024;
150 offset
+= bank
->sectors
[i
].size
;
151 bank
->sectors
[i
].is_erased
= -1;
152 bank
->sectors
[i
].is_protected
= 1;
154 for (i
= 10; i
< 18; i
++)
156 bank
->sectors
[i
].offset
= offset
;
157 bank
->sectors
[i
].size
= 8 * 1024;
158 offset
+= bank
->sectors
[i
].size
;
159 bank
->sectors
[i
].is_erased
= -1;
160 bank
->sectors
[i
].is_protected
= 1;
165 LOG_ERROR("BUG: unknown bank->size encountered");
169 else if (lpc2000_info
->variant
== lpc2000_v2
)
171 /* variant 2 has a uniform layout, only number of sectors differs */
175 lpc2000_info
->cmd51_max_buffer
= 1024;
176 bank
->num_sectors
= 1;
179 lpc2000_info
->cmd51_max_buffer
= 1024;
180 bank
->num_sectors
= 2;
183 bank
->num_sectors
= 4;
186 bank
->num_sectors
= 8;
189 bank
->num_sectors
= 9;
192 bank
->num_sectors
= 11;
195 bank
->num_sectors
= 15;
198 bank
->num_sectors
= 27;
202 bank
->num_sectors
= 28;
205 LOG_ERROR("BUG: unknown bank->size encountered");
210 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
212 for (i
= 0; i
< bank
->num_sectors
; i
++)
216 bank
->sectors
[i
].offset
= offset
;
217 bank
->sectors
[i
].size
= 4 * 1024;
218 offset
+= bank
->sectors
[i
].size
;
219 bank
->sectors
[i
].is_erased
= -1;
220 bank
->sectors
[i
].is_protected
= 1;
224 bank
->sectors
[i
].offset
= offset
;
225 bank
->sectors
[i
].size
= 32 * 1024;
226 offset
+= bank
->sectors
[i
].size
;
227 bank
->sectors
[i
].is_erased
= -1;
228 bank
->sectors
[i
].is_protected
= 1;
232 bank
->sectors
[i
].offset
= offset
;
233 bank
->sectors
[i
].size
= 4 * 1024;
234 offset
+= bank
->sectors
[i
].size
;
235 bank
->sectors
[i
].is_erased
= -1;
236 bank
->sectors
[i
].is_protected
= 1;
240 else if (lpc2000_info
->variant
== lpc1700
)
245 bank
->num_sectors
= 8;
248 bank
->num_sectors
= 16;
251 bank
->num_sectors
= 18;
254 bank
->num_sectors
= 22;
257 bank
->num_sectors
= 30;
260 LOG_ERROR("BUG: unknown bank->size encountered");
264 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
266 for(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;
278 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
285 /* call LPC1700/LPC2000 IAP function
286 * uses 180 bytes working area
287 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
288 * 0x8 to 0x1f: command parameter table (1+5 words)
289 * 0x20 to 0x33: command result table (1+4 words)
290 * 0x34 to 0xb3: stack (only 128b needed)
292 static int lpc2000_iap_call(struct flash_bank
*bank
, int code
, uint32_t param_table
[5], uint32_t result_table
[4])
295 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
296 struct target
*target
= bank
->target
;
297 struct mem_param mem_params
[2];
298 struct reg_param reg_params
[5];
299 struct arm_algorithm armv4_5_info
; /* for LPC2000 */
300 struct armv7m_algorithm armv7m_info
; /* for LPC1700 */
301 uint32_t status_code
;
302 uint32_t iap_entry_point
= 0; /* to make compiler happier */
304 /* regrab previously allocated working_area, or allocate a new one */
305 if (!lpc2000_info
->iap_working_area
)
307 uint8_t jump_gate
[8];
309 /* make sure we have a working area */
310 if (target_alloc_working_area(target
, 180, &lpc2000_info
->iap_working_area
) != ERROR_OK
)
312 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
313 return ERROR_FLASH_OPERATION_FAILED
;
316 /* write IAP code to working area */
317 switch(lpc2000_info
->variant
)
320 target_buffer_set_u32(target
, jump_gate
,
322 target_buffer_set_u32(target
, jump_gate
+ 4,
327 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
328 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
331 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
335 if ((retval
= target_write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, jump_gate
)) != ERROR_OK
)
337 LOG_ERROR("Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)", lpc2000_info
->iap_working_area
->address
);
342 switch(lpc2000_info
->variant
)
345 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
346 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
347 iap_entry_point
= 0x1fff1ff1;
351 armv4_5_info
.common_magic
= ARM_COMMON_MAGIC
;
352 armv4_5_info
.core_mode
= ARM_MODE_SVC
;
353 armv4_5_info
.core_state
= ARM_STATE_ARM
;
354 iap_entry_point
= 0x7ffffff1;
357 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
361 /* command parameter table */
362 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 6 * 4, PARAM_OUT
);
363 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
364 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
365 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
366 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
367 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
368 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
370 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
371 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x08);
373 /* command result table */
374 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
376 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
377 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
379 /* IAP entry point */
380 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
381 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
383 switch(lpc2000_info
->variant
)
387 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
388 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xb4);
391 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
392 buf_set_u32(reg_params
[4].value
, 0, 32, (lpc2000_info
->iap_working_area
->address
+ 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */
394 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, lpc2000_info
->iap_working_area
->address
, 0, 10000, &armv7m_info
);
399 init_reg_param(®_params
[3], "sp_svc", 32, PARAM_OUT
);
400 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xb4);
403 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
404 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x04);
406 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, lpc2000_info
->iap_working_area
->address
, lpc2000_info
->iap_working_area
->address
+ 0x4, 10000, &armv4_5_info
);
409 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
413 status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
414 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
415 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
416 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
417 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
419 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
") completed with result = %8.8" PRIx32
,
420 code
, param_table
[0], param_table
[1], param_table
[2], param_table
[3], param_table
[4], status_code
);
422 destroy_mem_param(&mem_params
[0]);
423 destroy_mem_param(&mem_params
[1]);
425 destroy_reg_param(®_params
[0]);
426 destroy_reg_param(®_params
[1]);
427 destroy_reg_param(®_params
[2]);
428 destroy_reg_param(®_params
[3]);
429 destroy_reg_param(®_params
[4]);
434 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
436 uint32_t param_table
[5];
437 uint32_t result_table
[4];
441 if ((first
< 0) || (last
>= bank
->num_sectors
))
442 return ERROR_FLASH_SECTOR_INVALID
;
444 for (i
= first
; i
<= last
; i
++)
446 /* check single sector */
447 param_table
[0] = param_table
[1] = i
;
448 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
452 case ERROR_FLASH_OPERATION_FAILED
:
453 return ERROR_FLASH_OPERATION_FAILED
;
454 case LPC2000_CMD_SUCCESS
:
455 bank
->sectors
[i
].is_erased
= 1;
457 case LPC2000_SECTOR_NOT_BLANK
:
458 bank
->sectors
[i
].is_erased
= 0;
460 case LPC2000_INVALID_SECTOR
:
461 bank
->sectors
[i
].is_erased
= 0;
464 return ERROR_FLASH_BUSY
;
467 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
476 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
478 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
480 struct lpc2000_flash_bank
*lpc2000_info
;
484 LOG_WARNING("incomplete flash_bank lpc2000 configuration");
485 return ERROR_FLASH_BANK_INVALID
;
488 lpc2000_info
= malloc(sizeof(struct lpc2000_flash_bank
));
489 bank
->driver_priv
= lpc2000_info
;
491 if (strcmp(CMD_ARGV
[6], "lpc2000_v1") == 0)
493 lpc2000_info
->variant
= lpc2000_v1
;
494 lpc2000_info
->cmd51_dst_boundary
= 512;
495 lpc2000_info
->cmd51_can_256b
= 0;
496 lpc2000_info
->cmd51_can_8192b
= 1;
497 lpc2000_info
->checksum_vector
= 5;
499 else if (strcmp(CMD_ARGV
[6], "lpc2000_v2") == 0)
501 lpc2000_info
->variant
= lpc2000_v2
;
502 lpc2000_info
->cmd51_dst_boundary
= 256;
503 lpc2000_info
->cmd51_can_256b
= 1;
504 lpc2000_info
->cmd51_can_8192b
= 0;
505 lpc2000_info
->checksum_vector
= 5;
507 else if (strcmp(CMD_ARGV
[6], "lpc1700") == 0)
509 lpc2000_info
->variant
= lpc1700
;
510 lpc2000_info
->cmd51_dst_boundary
= 256;
511 lpc2000_info
->cmd51_can_256b
= 1;
512 lpc2000_info
->cmd51_can_8192b
= 0;
513 lpc2000_info
->checksum_vector
= 7;
517 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
519 return ERROR_FLASH_BANK_INVALID
;
522 lpc2000_info
->iap_working_area
= NULL
;
523 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
524 lpc2000_info
->calc_checksum
= 0;
525 lpc2000_build_sector_list(bank
);
529 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
530 lpc2000_info
->calc_checksum
= 1;
536 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
538 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
539 uint32_t param_table
[5];
540 uint32_t result_table
[4];
543 if (bank
->target
->state
!= TARGET_HALTED
)
545 LOG_ERROR("Target not halted");
546 return ERROR_TARGET_NOT_HALTED
;
549 param_table
[0] = first
;
550 param_table
[1] = last
;
551 param_table
[2] = lpc2000_info
->cclk
;
553 /* Prepare sectors */
554 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
557 case ERROR_FLASH_OPERATION_FAILED
:
558 return ERROR_FLASH_OPERATION_FAILED
;
559 case LPC2000_CMD_SUCCESS
:
561 case LPC2000_INVALID_SECTOR
:
562 return ERROR_FLASH_SECTOR_INVALID
;
565 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
566 return ERROR_FLASH_OPERATION_FAILED
;
570 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
573 case ERROR_FLASH_OPERATION_FAILED
:
574 return ERROR_FLASH_OPERATION_FAILED
;
575 case LPC2000_CMD_SUCCESS
:
577 case LPC2000_INVALID_SECTOR
:
578 return ERROR_FLASH_SECTOR_INVALID
;
581 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
582 return ERROR_FLASH_OPERATION_FAILED
;
588 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
590 /* can't protect/unprotect on the lpc2000 */
594 static int lpc2000_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
596 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
597 struct target
*target
= bank
->target
;
598 uint32_t dst_min_alignment
;
599 uint32_t bytes_remaining
= count
;
600 uint32_t bytes_written
= 0;
601 int first_sector
= 0;
603 uint32_t param_table
[5];
604 uint32_t result_table
[4];
607 struct working_area
*download_area
;
608 int retval
= ERROR_OK
;
610 if (bank
->target
->state
!= TARGET_HALTED
)
612 LOG_ERROR("Target not halted");
613 return ERROR_TARGET_NOT_HALTED
;
616 if (offset
+ count
> bank
->size
)
617 return ERROR_FLASH_DST_OUT_OF_BANK
;
619 dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
621 if (offset
% dst_min_alignment
)
623 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
, offset
, dst_min_alignment
);
624 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
627 for (i
= 0; i
< bank
->num_sectors
; i
++)
629 if (offset
>= bank
->sectors
[i
].offset
)
631 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
635 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
637 /* check if exception vectors should be flashed */
638 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
640 uint32_t checksum
= 0;
641 for (i
= 0; i
< 8; i
++)
643 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
644 if (i
!= lpc2000_info
->checksum_vector
)
645 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
647 checksum
= 0 - checksum
;
648 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
650 uint32_t original_value
= buf_get_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32);
651 if (original_value
!= checksum
)
653 LOG_WARNING("Verification will fail since checksum in image (0x%8.8" PRIx32
") to be written to flash is different from calculated vector checksum (0x%8.8" PRIx32
").",
654 original_value
, checksum
);
655 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
658 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
661 /* allocate a working area */
662 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
)
664 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
665 return ERROR_FLASH_OPERATION_FAILED
;
668 while (bytes_remaining
> 0)
670 uint32_t thisrun_bytes
;
671 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
672 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
673 else if (bytes_remaining
>= 1024)
674 thisrun_bytes
= 1024;
675 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
680 /* Prepare sectors */
681 param_table
[0] = first_sector
;
682 param_table
[1] = last_sector
;
683 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
686 case ERROR_FLASH_OPERATION_FAILED
:
687 retval
= ERROR_FLASH_OPERATION_FAILED
;
689 case LPC2000_CMD_SUCCESS
:
691 case LPC2000_INVALID_SECTOR
:
692 retval
= ERROR_FLASH_SECTOR_INVALID
;
695 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
696 retval
= ERROR_FLASH_OPERATION_FAILED
;
700 /* Exit if error occured */
701 if (retval
!= ERROR_OK
)
704 if (bytes_remaining
>= thisrun_bytes
)
706 if ((retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
)) != ERROR_OK
)
708 retval
= ERROR_FLASH_OPERATION_FAILED
;
714 uint8_t *last_buffer
= malloc(thisrun_bytes
);
715 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
716 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
- bytes_remaining
);
717 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
721 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
724 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
725 param_table
[1] = download_area
->address
;
726 param_table
[2] = thisrun_bytes
;
727 param_table
[3] = lpc2000_info
->cclk
;
728 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
731 case ERROR_FLASH_OPERATION_FAILED
:
732 retval
= ERROR_FLASH_OPERATION_FAILED
;
734 case LPC2000_CMD_SUCCESS
:
736 case LPC2000_INVALID_SECTOR
:
737 retval
= ERROR_FLASH_SECTOR_INVALID
;
740 LOG_WARNING("lpc2000 returned %i", status_code
);
741 retval
= ERROR_FLASH_OPERATION_FAILED
;
745 /* Exit if error occured */
746 if (retval
!= ERROR_OK
)
749 if (bytes_remaining
> thisrun_bytes
)
750 bytes_remaining
-= thisrun_bytes
;
753 bytes_written
+= thisrun_bytes
;
756 target_free_working_area(target
, download_area
);
761 static int lpc2000_probe(struct flash_bank
*bank
)
763 /* we can't probe on an lpc2000
764 * if this is an lpc2xxx, it has the configured flash
769 static int lpc2000_erase_check(struct flash_bank
*bank
)
771 if (bank
->target
->state
!= TARGET_HALTED
)
773 LOG_ERROR("Target not halted");
774 return ERROR_TARGET_NOT_HALTED
;
777 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
780 static int lpc2000_protect_check(struct flash_bank
*bank
)
782 /* sectors are always protected */
786 static int get_lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
788 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
790 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz" , lpc2000_info
->variant
, lpc2000_info
->cclk
);
795 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
797 uint32_t param_table
[5];
798 uint32_t result_table
[4];
803 return ERROR_COMMAND_SYNTAX_ERROR
;
806 struct flash_bank
*bank
;
807 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
808 if (ERROR_OK
!= retval
)
811 if (bank
->target
->state
!= TARGET_HALTED
)
813 LOG_ERROR("Target not halted");
814 return ERROR_TARGET_NOT_HALTED
;
817 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
819 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
821 command_print(CMD_CTX
, "no sufficient working area specified, can't access LPC2000 IAP interface");
824 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
828 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
834 static const struct command_registration lpc2000_exec_command_handlers
[] = {
837 .handler
= lpc2000_handle_part_id_command
,
838 .mode
= COMMAND_EXEC
,
839 .help
= "print part id of lpc2000 flash bank <num>",
841 COMMAND_REGISTRATION_DONE
843 static const struct command_registration lpc2000_command_handlers
[] = {
847 .help
= "lpc2000 flash command group",
848 .chain
= lpc2000_exec_command_handlers
,
850 COMMAND_REGISTRATION_DONE
853 struct flash_driver lpc2000_flash
= {
855 .commands
= lpc2000_command_handlers
,
856 .flash_bank_command
= lpc2000_flash_bank_command
,
857 .erase
= lpc2000_erase
,
858 .protect
= lpc2000_protect
,
859 .write
= lpc2000_write
,
860 .read
= default_flash_read
,
861 .probe
= lpc2000_probe
,
862 .auto_probe
= lpc2000_probe
,
863 .erase_check
= lpc2000_erase_check
,
864 .protect_check
= lpc2000_protect_check
,
865 .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)