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 ***************************************************************************/
30 #include <helper/binarybuffer.h>
31 #include <target/algorithm.h>
32 #include <target/arm_opcodes.h>
33 #include <target/armv7m.h>
38 * flash programming support for NXP LPC17xx and LPC2xxx devices.
40 * @todo Provide a way to update CCLK after declaring the flash bank.
41 * The value which is correct after chip reset will rarely still work
42 * right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz).
45 * currently supported devices:
46 * variant 1 (lpc2000_v1):
54 * variant 2 (lpc2000_v2):
63 * - 176x (tested with LPC1768)
66 static int lpc2000_build_sector_list(struct flash_bank
*bank
)
68 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
72 /* default to a 4096 write buffer */
73 lpc2000_info
->cmd51_max_buffer
= 4096;
75 if (lpc2000_info
->variant
== lpc2000_v1
)
77 /* variant 1 has different layout for 128kb and 256kb flashes */
78 if (bank
->size
== 128 * 1024)
80 bank
->num_sectors
= 16;
81 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 16);
82 for (i
= 0; i
< 16; i
++)
84 bank
->sectors
[i
].offset
= offset
;
85 bank
->sectors
[i
].size
= 8 * 1024;
86 offset
+= bank
->sectors
[i
].size
;
87 bank
->sectors
[i
].is_erased
= -1;
88 bank
->sectors
[i
].is_protected
= 1;
91 else if (bank
->size
== 256 * 1024)
93 bank
->num_sectors
= 18;
94 bank
->sectors
= malloc(sizeof(struct flash_sector
) * 18);
96 for (i
= 0; i
< 8; i
++)
98 bank
->sectors
[i
].offset
= offset
;
99 bank
->sectors
[i
].size
= 8 * 1024;
100 offset
+= bank
->sectors
[i
].size
;
101 bank
->sectors
[i
].is_erased
= -1;
102 bank
->sectors
[i
].is_protected
= 1;
104 for (i
= 8; i
< 10; i
++)
106 bank
->sectors
[i
].offset
= offset
;
107 bank
->sectors
[i
].size
= 64 * 1024;
108 offset
+= bank
->sectors
[i
].size
;
109 bank
->sectors
[i
].is_erased
= -1;
110 bank
->sectors
[i
].is_protected
= 1;
112 for (i
= 10; i
< 18; i
++)
114 bank
->sectors
[i
].offset
= offset
;
115 bank
->sectors
[i
].size
= 8 * 1024;
116 offset
+= bank
->sectors
[i
].size
;
117 bank
->sectors
[i
].is_erased
= -1;
118 bank
->sectors
[i
].is_protected
= 1;
123 LOG_ERROR("BUG: unknown bank->size encountered");
127 else if (lpc2000_info
->variant
== lpc2000_v2
)
129 /* variant 2 has a uniform layout, only number of sectors differs */
133 lpc2000_info
->cmd51_max_buffer
= 1024;
134 bank
->num_sectors
= 1;
137 lpc2000_info
->cmd51_max_buffer
= 1024;
138 bank
->num_sectors
= 2;
141 bank
->num_sectors
= 4;
144 bank
->num_sectors
= 8;
147 bank
->num_sectors
= 9;
150 bank
->num_sectors
= 11;
153 bank
->num_sectors
= 15;
157 bank
->num_sectors
= 27;
160 LOG_ERROR("BUG: unknown bank->size encountered");
165 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
167 for (i
= 0; i
< bank
->num_sectors
; i
++)
169 if ((i
>= 0) && (i
< 8))
171 bank
->sectors
[i
].offset
= offset
;
172 bank
->sectors
[i
].size
= 4 * 1024;
173 offset
+= bank
->sectors
[i
].size
;
174 bank
->sectors
[i
].is_erased
= -1;
175 bank
->sectors
[i
].is_protected
= 1;
177 if ((i
>= 8) && (i
< 22))
179 bank
->sectors
[i
].offset
= offset
;
180 bank
->sectors
[i
].size
= 32 * 1024;
181 offset
+= bank
->sectors
[i
].size
;
182 bank
->sectors
[i
].is_erased
= -1;
183 bank
->sectors
[i
].is_protected
= 1;
185 if ((i
>= 22) && (i
< 27))
187 bank
->sectors
[i
].offset
= offset
;
188 bank
->sectors
[i
].size
= 4 * 1024;
189 offset
+= bank
->sectors
[i
].size
;
190 bank
->sectors
[i
].is_erased
= -1;
191 bank
->sectors
[i
].is_protected
= 1;
195 else if (lpc2000_info
->variant
== lpc1700
)
200 bank
->num_sectors
= 8;
203 bank
->num_sectors
= 16;
206 bank
->num_sectors
= 18;
209 bank
->num_sectors
= 22;
212 bank
->num_sectors
= 30;
215 LOG_ERROR("BUG: unknown bank->size encountered");
219 bank
->sectors
= malloc(sizeof(struct flash_sector
) * bank
->num_sectors
);
221 for(i
= 0; i
< bank
->num_sectors
; i
++)
223 bank
->sectors
[i
].offset
= offset
;
224 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
225 bank
->sectors
[i
].size
= (i
< 16)? 4 * 1024 : 32 * 1024;
226 offset
+= bank
->sectors
[i
].size
;
227 bank
->sectors
[i
].is_erased
= -1;
228 bank
->sectors
[i
].is_protected
= 1;
233 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
240 /* call LPC1700/LPC2000 IAP function
241 * uses 180 bytes working area
242 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
243 * 0x8 to 0x1f: command parameter table (1+5 words)
244 * 0x20 to 0x33: command result table (1+4 words)
245 * 0x34 to 0xb3: stack (only 128b needed)
247 static int lpc2000_iap_call(struct flash_bank
*bank
, int code
, uint32_t param_table
[5], uint32_t result_table
[4])
250 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
251 struct target
*target
= bank
->target
;
252 struct mem_param mem_params
[2];
253 struct reg_param reg_params
[5];
254 struct arm_algorithm armv4_5_info
; /* for LPC2000 */
255 struct armv7m_algorithm armv7m_info
; /* for LPC1700 */
256 uint32_t status_code
;
257 uint32_t iap_entry_point
= 0; /* to make compiler happier */
259 /* regrab previously allocated working_area, or allocate a new one */
260 if (!lpc2000_info
->iap_working_area
)
262 uint8_t jump_gate
[8];
264 /* make sure we have a working area */
265 if (target_alloc_working_area(target
, 180, &lpc2000_info
->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 /* write IAP code to working area */
272 switch(lpc2000_info
->variant
)
275 target_buffer_set_u32(target
, jump_gate
,
277 target_buffer_set_u32(target
, jump_gate
+ 4,
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 bank->size encountered");
290 if ((retval
= target_write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, jump_gate
)) != ERROR_OK
)
292 LOG_ERROR("Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)", lpc2000_info
->iap_working_area
->address
);
297 switch(lpc2000_info
->variant
)
300 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
301 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
302 iap_entry_point
= 0x1fff1ff1;
306 armv4_5_info
.common_magic
= ARM_COMMON_MAGIC
;
307 armv4_5_info
.core_mode
= ARM_MODE_SVC
;
308 armv4_5_info
.core_state
= ARM_STATE_ARM
;
309 iap_entry_point
= 0x7ffffff1;
312 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
316 /* command parameter table */
317 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 6 * 4, PARAM_OUT
);
318 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
319 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
320 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
321 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
322 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
323 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
325 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
326 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x08);
328 /* command result table */
329 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
331 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
332 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
334 /* IAP entry point */
335 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
336 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
338 switch(lpc2000_info
->variant
)
342 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
343 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xb4);
346 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
347 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 */
349 target_run_algorithm(target
, 2, mem_params
, 5, reg_params
, lpc2000_info
->iap_working_area
->address
, lpc2000_info
->iap_working_area
->address
+ 0x4, 10000, &armv7m_info
);
354 init_reg_param(®_params
[3], "sp_svc", 32, PARAM_OUT
);
355 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xb4);
358 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
359 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x04);
361 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
);
364 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
369 status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
370 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
371 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
372 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
373 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
375 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
,
376 code
, param_table
[0], param_table
[1], param_table
[2], param_table
[3], param_table
[4], status_code
);
378 destroy_mem_param(&mem_params
[0]);
379 destroy_mem_param(&mem_params
[1]);
381 destroy_reg_param(®_params
[0]);
382 destroy_reg_param(®_params
[1]);
383 destroy_reg_param(®_params
[2]);
384 destroy_reg_param(®_params
[3]);
385 destroy_reg_param(®_params
[4]);
390 static int lpc2000_iap_blank_check(struct flash_bank
*bank
, int first
, int last
)
392 uint32_t param_table
[5];
393 uint32_t result_table
[4];
397 if ((first
< 0) || (last
>= bank
->num_sectors
))
398 return ERROR_FLASH_SECTOR_INVALID
;
400 for (i
= first
; i
<= last
; i
++)
402 /* check single sector */
403 param_table
[0] = param_table
[1] = i
;
404 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
408 case ERROR_FLASH_OPERATION_FAILED
:
409 return ERROR_FLASH_OPERATION_FAILED
;
410 case LPC2000_CMD_SUCCESS
:
411 bank
->sectors
[i
].is_erased
= 1;
413 case LPC2000_SECTOR_NOT_BLANK
:
414 bank
->sectors
[i
].is_erased
= 0;
416 case LPC2000_INVALID_SECTOR
:
417 bank
->sectors
[i
].is_erased
= 0;
420 return ERROR_FLASH_BUSY
;
423 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
432 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
434 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
436 struct lpc2000_flash_bank
*lpc2000_info
;
440 LOG_WARNING("incomplete flash_bank lpc2000 configuration");
441 return ERROR_FLASH_BANK_INVALID
;
444 lpc2000_info
= malloc(sizeof(struct lpc2000_flash_bank
));
445 bank
->driver_priv
= lpc2000_info
;
447 if (strcmp(CMD_ARGV
[6], "lpc2000_v1") == 0)
449 lpc2000_info
->variant
= lpc2000_v1
;
450 lpc2000_info
->cmd51_dst_boundary
= 512;
451 lpc2000_info
->cmd51_can_256b
= 0;
452 lpc2000_info
->cmd51_can_8192b
= 1;
453 lpc2000_info
->checksum_vector
= 5;
455 else if (strcmp(CMD_ARGV
[6], "lpc2000_v2") == 0)
457 lpc2000_info
->variant
= lpc2000_v2
;
458 lpc2000_info
->cmd51_dst_boundary
= 256;
459 lpc2000_info
->cmd51_can_256b
= 1;
460 lpc2000_info
->cmd51_can_8192b
= 0;
461 lpc2000_info
->checksum_vector
= 5;
463 else if (strcmp(CMD_ARGV
[6], "lpc1700") == 0)
465 lpc2000_info
->variant
= lpc1700
;
466 lpc2000_info
->cmd51_dst_boundary
= 256;
467 lpc2000_info
->cmd51_can_256b
= 1;
468 lpc2000_info
->cmd51_can_8192b
= 0;
469 lpc2000_info
->checksum_vector
= 7;
473 LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV
[6]);
475 return ERROR_FLASH_BANK_INVALID
;
478 lpc2000_info
->iap_working_area
= NULL
;
479 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[7], lpc2000_info
->cclk
);
480 lpc2000_info
->calc_checksum
= 0;
481 lpc2000_build_sector_list(bank
);
485 if (strcmp(CMD_ARGV
[8], "calc_checksum") == 0)
486 lpc2000_info
->calc_checksum
= 1;
492 static int lpc2000_erase(struct flash_bank
*bank
, int first
, int last
)
494 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
495 uint32_t param_table
[5];
496 uint32_t result_table
[4];
499 if (bank
->target
->state
!= TARGET_HALTED
)
501 LOG_ERROR("Target not halted");
502 return ERROR_TARGET_NOT_HALTED
;
505 param_table
[0] = first
;
506 param_table
[1] = last
;
507 param_table
[2] = lpc2000_info
->cclk
;
509 /* Prepare sectors */
510 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
513 case ERROR_FLASH_OPERATION_FAILED
:
514 return ERROR_FLASH_OPERATION_FAILED
;
515 case LPC2000_CMD_SUCCESS
:
517 case LPC2000_INVALID_SECTOR
:
518 return ERROR_FLASH_SECTOR_INVALID
;
521 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
522 return ERROR_FLASH_OPERATION_FAILED
;
526 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
529 case ERROR_FLASH_OPERATION_FAILED
:
530 return ERROR_FLASH_OPERATION_FAILED
;
531 case LPC2000_CMD_SUCCESS
:
533 case LPC2000_INVALID_SECTOR
:
534 return ERROR_FLASH_SECTOR_INVALID
;
537 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
538 return ERROR_FLASH_OPERATION_FAILED
;
544 static int lpc2000_protect(struct flash_bank
*bank
, int set
, int first
, int last
)
546 /* can't protect/unprotect on the lpc2000 */
550 static int lpc2000_write(struct flash_bank
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
552 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
553 struct target
*target
= bank
->target
;
554 uint32_t dst_min_alignment
;
555 uint32_t bytes_remaining
= count
;
556 uint32_t bytes_written
= 0;
557 int first_sector
= 0;
559 uint32_t param_table
[5];
560 uint32_t result_table
[4];
563 struct working_area
*download_area
;
564 int retval
= ERROR_OK
;
566 if (bank
->target
->state
!= TARGET_HALTED
)
568 LOG_ERROR("Target not halted");
569 return ERROR_TARGET_NOT_HALTED
;
572 if (offset
+ count
> bank
->size
)
573 return ERROR_FLASH_DST_OUT_OF_BANK
;
575 dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
577 if (offset
% dst_min_alignment
)
579 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
, offset
, dst_min_alignment
);
580 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
583 for (i
= 0; i
< bank
->num_sectors
; i
++)
585 if (offset
>= bank
->sectors
[i
].offset
)
587 if (offset
+ DIV_ROUND_UP(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
591 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
593 /* check if exception vectors should be flashed */
594 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
596 uint32_t checksum
= 0;
598 for (i
= 0; i
< 8; i
++)
600 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
601 if (i
!= lpc2000_info
->checksum_vector
)
602 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
604 checksum
= 0 - checksum
;
605 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
607 uint32_t original_value
= buf_get_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32);
608 if (original_value
!= checksum
)
610 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
").",
611 original_value
, checksum
);
612 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
615 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
618 /* allocate a working area */
619 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
)
621 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
622 return ERROR_FLASH_OPERATION_FAILED
;
625 while (bytes_remaining
> 0)
627 uint32_t thisrun_bytes
;
628 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
629 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
630 else if (bytes_remaining
>= 1024)
631 thisrun_bytes
= 1024;
632 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
637 /* Prepare sectors */
638 param_table
[0] = first_sector
;
639 param_table
[1] = last_sector
;
640 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
643 case ERROR_FLASH_OPERATION_FAILED
:
644 retval
= ERROR_FLASH_OPERATION_FAILED
;
646 case LPC2000_CMD_SUCCESS
:
648 case LPC2000_INVALID_SECTOR
:
649 retval
= ERROR_FLASH_SECTOR_INVALID
;
652 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
653 retval
= ERROR_FLASH_OPERATION_FAILED
;
657 /* Exit if error occured */
658 if (retval
!= ERROR_OK
)
661 if (bytes_remaining
>= thisrun_bytes
)
663 if ((retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
)) != ERROR_OK
)
665 retval
= ERROR_FLASH_OPERATION_FAILED
;
671 uint8_t *last_buffer
= malloc(thisrun_bytes
);
672 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
673 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
- bytes_remaining
);
674 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
678 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
681 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
682 param_table
[1] = download_area
->address
;
683 param_table
[2] = thisrun_bytes
;
684 param_table
[3] = lpc2000_info
->cclk
;
685 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
688 case ERROR_FLASH_OPERATION_FAILED
:
689 retval
= ERROR_FLASH_OPERATION_FAILED
;
691 case LPC2000_CMD_SUCCESS
:
693 case LPC2000_INVALID_SECTOR
:
694 retval
= ERROR_FLASH_SECTOR_INVALID
;
697 LOG_WARNING("lpc2000 returned %i", status_code
);
698 retval
= ERROR_FLASH_OPERATION_FAILED
;
702 /* Exit if error occured */
703 if (retval
!= ERROR_OK
)
706 if (bytes_remaining
> thisrun_bytes
)
707 bytes_remaining
-= thisrun_bytes
;
710 bytes_written
+= thisrun_bytes
;
713 target_free_working_area(target
, download_area
);
718 static int lpc2000_probe(struct flash_bank
*bank
)
720 /* we can't probe on an lpc2000
721 * if this is an lpc2xxx, it has the configured flash
726 static int lpc2000_erase_check(struct flash_bank
*bank
)
728 if (bank
->target
->state
!= TARGET_HALTED
)
730 LOG_ERROR("Target not halted");
731 return ERROR_TARGET_NOT_HALTED
;
734 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
737 static int lpc2000_protect_check(struct flash_bank
*bank
)
739 /* sectors are always protected */
743 static int lpc2000_info(struct flash_bank
*bank
, char *buf
, int buf_size
)
745 struct lpc2000_flash_bank
*lpc2000_info
= bank
->driver_priv
;
747 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz" , lpc2000_info
->variant
, lpc2000_info
->cclk
);
752 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
754 uint32_t param_table
[5];
755 uint32_t result_table
[4];
760 return ERROR_COMMAND_SYNTAX_ERROR
;
763 struct flash_bank
*bank
;
764 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
765 if (ERROR_OK
!= retval
)
768 if (bank
->target
->state
!= TARGET_HALTED
)
770 LOG_ERROR("Target not halted");
771 return ERROR_TARGET_NOT_HALTED
;
774 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
776 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
778 command_print(CMD_CTX
, "no sufficient working area specified, can't access LPC2000 IAP interface");
781 command_print(CMD_CTX
, "lpc2000 IAP returned status code %i", status_code
);
785 command_print(CMD_CTX
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
791 static const struct command_registration lpc2000_exec_command_handlers
[] = {
794 .handler
= lpc2000_handle_part_id_command
,
795 .mode
= COMMAND_EXEC
,
796 .help
= "print part id of lpc2000 flash bank <num>",
798 COMMAND_REGISTRATION_DONE
800 static const struct command_registration lpc2000_command_handlers
[] = {
804 .help
= "lpc2000 flash command group",
805 .chain
= lpc2000_exec_command_handlers
,
807 COMMAND_REGISTRATION_DONE
810 struct flash_driver lpc2000_flash
= {
812 .commands
= lpc2000_command_handlers
,
813 .flash_bank_command
= lpc2000_flash_bank_command
,
814 .erase
= lpc2000_erase
,
815 .protect
= lpc2000_protect
,
816 .write
= lpc2000_write
,
817 .probe
= lpc2000_probe
,
818 .auto_probe
= lpc2000_probe
,
819 .erase_check
= lpc2000_erase_check
,
820 .protect_check
= lpc2000_protect_check
,
821 .info
= 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)