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 ***************************************************************************/
31 #include "binarybuffer.h"
34 /* flash programming support for NXP LPC17xx and LPC2xxx devices
35 * currently supported devices:
36 * variant 1 (lpc2000_v1):
44 * variant 2 (lpc2000_v2):
53 * - 176x (tested with LPC1768)
56 static int lpc2000_build_sector_list(struct flash_bank_s
*bank
)
58 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
62 /* default to a 4096 write buffer */
63 lpc2000_info
->cmd51_max_buffer
= 4096;
65 if (lpc2000_info
->variant
== lpc2000_v1
)
67 /* variant 1 has different layout for 128kb and 256kb flashes */
68 if (bank
->size
== 128 * 1024)
70 bank
->num_sectors
= 16;
71 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 16);
72 for (i
= 0; i
< 16; i
++)
74 bank
->sectors
[i
].offset
= offset
;
75 bank
->sectors
[i
].size
= 8 * 1024;
76 offset
+= bank
->sectors
[i
].size
;
77 bank
->sectors
[i
].is_erased
= -1;
78 bank
->sectors
[i
].is_protected
= 1;
81 else if (bank
->size
== 256 * 1024)
83 bank
->num_sectors
= 18;
84 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 18);
86 for (i
= 0; i
< 8; i
++)
88 bank
->sectors
[i
].offset
= offset
;
89 bank
->sectors
[i
].size
= 8 * 1024;
90 offset
+= bank
->sectors
[i
].size
;
91 bank
->sectors
[i
].is_erased
= -1;
92 bank
->sectors
[i
].is_protected
= 1;
94 for (i
= 8; i
< 10; i
++)
96 bank
->sectors
[i
].offset
= offset
;
97 bank
->sectors
[i
].size
= 64 * 1024;
98 offset
+= bank
->sectors
[i
].size
;
99 bank
->sectors
[i
].is_erased
= -1;
100 bank
->sectors
[i
].is_protected
= 1;
102 for (i
= 10; i
< 18; i
++)
104 bank
->sectors
[i
].offset
= offset
;
105 bank
->sectors
[i
].size
= 8 * 1024;
106 offset
+= bank
->sectors
[i
].size
;
107 bank
->sectors
[i
].is_erased
= -1;
108 bank
->sectors
[i
].is_protected
= 1;
113 LOG_ERROR("BUG: unknown bank->size encountered");
117 else if (lpc2000_info
->variant
== lpc2000_v2
)
119 /* variant 2 has a uniform layout, only number of sectors differs */
123 lpc2000_info
->cmd51_max_buffer
= 1024;
124 bank
->num_sectors
= 1;
127 lpc2000_info
->cmd51_max_buffer
= 1024;
128 bank
->num_sectors
= 2;
131 bank
->num_sectors
= 4;
134 bank
->num_sectors
= 8;
137 bank
->num_sectors
= 9;
140 bank
->num_sectors
= 11;
143 bank
->num_sectors
= 15;
147 bank
->num_sectors
= 27;
150 LOG_ERROR("BUG: unknown bank->size encountered");
155 bank
->sectors
= malloc(sizeof(flash_sector_t
) * bank
->num_sectors
);
157 for (i
= 0; i
< bank
->num_sectors
; i
++)
159 if ((i
>= 0) && (i
< 8))
161 bank
->sectors
[i
].offset
= offset
;
162 bank
->sectors
[i
].size
= 4 * 1024;
163 offset
+= bank
->sectors
[i
].size
;
164 bank
->sectors
[i
].is_erased
= -1;
165 bank
->sectors
[i
].is_protected
= 1;
167 if ((i
>= 8) && (i
< 22))
169 bank
->sectors
[i
].offset
= offset
;
170 bank
->sectors
[i
].size
= 32 * 1024;
171 offset
+= bank
->sectors
[i
].size
;
172 bank
->sectors
[i
].is_erased
= -1;
173 bank
->sectors
[i
].is_protected
= 1;
175 if ((i
>= 22) && (i
< 27))
177 bank
->sectors
[i
].offset
= offset
;
178 bank
->sectors
[i
].size
= 4 * 1024;
179 offset
+= bank
->sectors
[i
].size
;
180 bank
->sectors
[i
].is_erased
= -1;
181 bank
->sectors
[i
].is_protected
= 1;
185 else if (lpc2000_info
->variant
== lpc1700
)
190 bank
->num_sectors
= 8;
193 bank
->num_sectors
= 16;
196 bank
->num_sectors
= 18;
199 bank
->num_sectors
= 22;
202 bank
->num_sectors
= 30;
205 LOG_ERROR("BUG: unknown bank->size encountered");
209 bank
->sectors
= malloc(sizeof(flash_sector_t
) * bank
->num_sectors
);
211 for(i
= 0; i
< bank
->num_sectors
; i
++)
213 bank
->sectors
[i
].offset
= offset
;
214 /* sectors 0-15 are 4kB-sized, 16 and above are 32kB-sized for LPC17xx devices */
215 bank
->sectors
[i
].size
= (i
< 16)? 4 * 1024 : 32 * 1024;
216 offset
+= bank
->sectors
[i
].size
;
217 bank
->sectors
[i
].is_erased
= -1;
218 bank
->sectors
[i
].is_protected
= 1;
223 LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
230 /* call LPC1700/LPC2000 IAP function
231 * uses 180 bytes working area
232 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
233 * 0x8 to 0x1f: command parameter table (1+5 words)
234 * 0x20 to 0x33: command result table (1+4 words)
235 * 0x34 to 0xb3: stack (only 128b needed)
237 static int lpc2000_iap_call(flash_bank_t
*bank
, int code
, uint32_t param_table
[5], uint32_t result_table
[4])
240 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
241 target_t
*target
= bank
->target
;
242 mem_param_t mem_params
[2];
243 reg_param_t reg_params
[5];
244 armv4_5_algorithm_t armv4_5_info
; /* for LPC2000 */
245 armv7m_algorithm_t armv7m_info
; /* for LPC1700 */
246 uint32_t status_code
;
247 uint32_t iap_entry_point
= 0; /* to make compiler happier */
249 /* regrab previously allocated working_area, or allocate a new one */
250 if (!lpc2000_info
->iap_working_area
)
252 uint8_t jump_gate
[8];
254 /* make sure we have a working area */
255 if (target_alloc_working_area(target
, 180, &lpc2000_info
->iap_working_area
) != ERROR_OK
)
257 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
258 return ERROR_FLASH_OPERATION_FAILED
;
261 /* write IAP code to working area */
262 switch(lpc2000_info
->variant
)
265 target_buffer_set_u32(target
, jump_gate
, ARMV7M_T_BX(12));
266 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV7M_T_B(0xfffffe));
270 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
271 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
274 LOG_ERROR("BUG: unknown bank->size encountered");
278 if ((retval
= target_write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, jump_gate
)) != ERROR_OK
)
280 LOG_ERROR("Write memory at address 0x%8.8" PRIx32
" failed (check work_area definition)", lpc2000_info
->iap_working_area
->address
);
285 switch(lpc2000_info
->variant
)
288 armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
289 armv7m_info
.core_mode
= ARMV7M_MODE_ANY
;
290 iap_entry_point
= 0x1fff1ff1;
294 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
295 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
296 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
297 iap_entry_point
= 0x7ffffff1;
300 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
304 /* command parameter table */
305 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 6 * 4, PARAM_OUT
);
306 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
307 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x04, param_table
[0]);
308 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x08, param_table
[1]);
309 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x0c, param_table
[2]);
310 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
311 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
313 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
314 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x08);
316 /* command result table */
317 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 5 * 4, PARAM_IN
);
319 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
320 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
322 /* IAP entry point */
323 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
324 buf_set_u32(reg_params
[2].value
, 0, 32, iap_entry_point
);
326 switch(lpc2000_info
->variant
)
330 init_reg_param(®_params
[3], "sp", 32, PARAM_OUT
);
331 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xb4);
334 init_reg_param(®_params
[4], "lr", 32, PARAM_OUT
);
335 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 */
337 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
);
342 init_reg_param(®_params
[3], "r13_svc", 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_svc", 32, PARAM_OUT
);
347 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x04);
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, &armv4_5_info
);
352 LOG_ERROR("BUG: unknown lpc2000->variant encountered");
357 status_code
= target_buffer_get_u32(target
, mem_params
[1].value
);
358 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x04);
359 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x08);
360 result_table
[2] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x0c);
361 result_table
[3] = target_buffer_get_u32(target
, mem_params
[1].value
+ 0x10);
363 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
,
364 code
, param_table
[0], param_table
[1], param_table
[2], param_table
[3], param_table
[4], status_code
);
366 destroy_mem_param(&mem_params
[0]);
367 destroy_mem_param(&mem_params
[1]);
369 destroy_reg_param(®_params
[0]);
370 destroy_reg_param(®_params
[1]);
371 destroy_reg_param(®_params
[2]);
372 destroy_reg_param(®_params
[3]);
373 destroy_reg_param(®_params
[4]);
378 static int lpc2000_iap_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
380 uint32_t param_table
[5];
381 uint32_t result_table
[4];
385 if ((first
< 0) || (last
>= bank
->num_sectors
))
386 return ERROR_FLASH_SECTOR_INVALID
;
388 for (i
= first
; i
<= last
; i
++)
390 /* check single sector */
391 param_table
[0] = param_table
[1] = i
;
392 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
396 case ERROR_FLASH_OPERATION_FAILED
:
397 return ERROR_FLASH_OPERATION_FAILED
;
398 case LPC2000_CMD_SUCCESS
:
399 bank
->sectors
[i
].is_erased
= 1;
401 case LPC2000_SECTOR_NOT_BLANK
:
402 bank
->sectors
[i
].is_erased
= 0;
404 case LPC2000_INVALID_SECTOR
:
405 bank
->sectors
[i
].is_erased
= 0;
408 return ERROR_FLASH_BUSY
;
411 LOG_ERROR("BUG: unknown LPC2000 status code %i", status_code
);
420 * flash bank lpc2000 <base> <size> 0 0 <target#> <lpc_variant> <cclk> [calc_checksum]
422 FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command
)
424 lpc2000_flash_bank_t
*lpc2000_info
;
428 LOG_WARNING("incomplete flash_bank lpc2000 configuration");
429 return ERROR_FLASH_BANK_INVALID
;
432 lpc2000_info
= malloc(sizeof(lpc2000_flash_bank_t
));
433 bank
->driver_priv
= lpc2000_info
;
435 if (strcmp(args
[6], "lpc2000_v1") == 0)
437 lpc2000_info
->variant
= lpc2000_v1
;
438 lpc2000_info
->cmd51_dst_boundary
= 512;
439 lpc2000_info
->cmd51_can_256b
= 0;
440 lpc2000_info
->cmd51_can_8192b
= 1;
441 lpc2000_info
->checksum_vector
= 5;
443 else if (strcmp(args
[6], "lpc2000_v2") == 0)
445 lpc2000_info
->variant
= lpc2000_v2
;
446 lpc2000_info
->cmd51_dst_boundary
= 256;
447 lpc2000_info
->cmd51_can_256b
= 1;
448 lpc2000_info
->cmd51_can_8192b
= 0;
449 lpc2000_info
->checksum_vector
= 5;
451 else if (strcmp(args
[6], "lpc1700") == 0)
453 lpc2000_info
->variant
= lpc1700
;
454 lpc2000_info
->cmd51_dst_boundary
= 256;
455 lpc2000_info
->cmd51_can_256b
= 1;
456 lpc2000_info
->cmd51_can_8192b
= 0;
457 lpc2000_info
->checksum_vector
= 7;
461 LOG_ERROR("unknown LPC2000 variant: %s", args
[6]);
463 return ERROR_FLASH_BANK_INVALID
;
466 lpc2000_info
->iap_working_area
= NULL
;
467 COMMAND_PARSE_NUMBER(u32
, args
[7], lpc2000_info
->cclk
);
468 lpc2000_info
->calc_checksum
= 0;
469 lpc2000_build_sector_list(bank
);
473 if (strcmp(args
[8], "calc_checksum") == 0)
474 lpc2000_info
->calc_checksum
= 1;
480 static int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
)
482 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
483 uint32_t param_table
[5];
484 uint32_t result_table
[4];
487 if (bank
->target
->state
!= TARGET_HALTED
)
489 LOG_ERROR("Target not halted");
490 return ERROR_TARGET_NOT_HALTED
;
493 param_table
[0] = first
;
494 param_table
[1] = last
;
495 param_table
[2] = lpc2000_info
->cclk
;
497 /* Prepare sectors */
498 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
501 case ERROR_FLASH_OPERATION_FAILED
:
502 return ERROR_FLASH_OPERATION_FAILED
;
503 case LPC2000_CMD_SUCCESS
:
505 case LPC2000_INVALID_SECTOR
:
506 return ERROR_FLASH_SECTOR_INVALID
;
509 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
510 return ERROR_FLASH_OPERATION_FAILED
;
514 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
517 case ERROR_FLASH_OPERATION_FAILED
:
518 return ERROR_FLASH_OPERATION_FAILED
;
519 case LPC2000_CMD_SUCCESS
:
521 case LPC2000_INVALID_SECTOR
:
522 return ERROR_FLASH_SECTOR_INVALID
;
525 LOG_WARNING("lpc2000 erase sectors returned %i", status_code
);
526 return ERROR_FLASH_OPERATION_FAILED
;
532 static int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
534 /* can't protect/unprotect on the lpc2000 */
538 static int lpc2000_write(struct flash_bank_s
*bank
, uint8_t *buffer
, uint32_t offset
, uint32_t count
)
540 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
541 target_t
*target
= bank
->target
;
542 uint32_t dst_min_alignment
;
543 uint32_t bytes_remaining
= count
;
544 uint32_t bytes_written
= 0;
545 int first_sector
= 0;
547 uint32_t param_table
[5];
548 uint32_t result_table
[4];
551 working_area_t
*download_area
;
552 int retval
= ERROR_OK
;
554 if (bank
->target
->state
!= TARGET_HALTED
)
556 LOG_ERROR("Target not halted");
557 return ERROR_TARGET_NOT_HALTED
;
560 if (offset
+ count
> bank
->size
)
561 return ERROR_FLASH_DST_OUT_OF_BANK
;
563 dst_min_alignment
= lpc2000_info
->cmd51_dst_boundary
;
565 if (offset
% dst_min_alignment
)
567 LOG_WARNING("offset 0x%" PRIx32
" breaks required alignment 0x%" PRIx32
, offset
, dst_min_alignment
);
568 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
571 for (i
= 0; i
< bank
->num_sectors
; i
++)
573 if (offset
>= bank
->sectors
[i
].offset
)
575 if (offset
+ CEIL(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
579 LOG_DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
581 /* check if exception vectors should be flashed */
582 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
584 uint32_t checksum
= 0;
586 for (i
= 0; i
< 8; i
++)
588 LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32
, i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
589 if (i
!= lpc2000_info
->checksum_vector
)
590 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
592 checksum
= 0 - checksum
;
593 LOG_DEBUG("checksum: 0x%8.8" PRIx32
, checksum
);
595 uint32_t original_value
= buf_get_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32);
596 if (original_value
!= checksum
)
598 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
").",
599 original_value
, checksum
);
600 LOG_WARNING("To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.");
603 buf_set_u32(buffer
+ (lpc2000_info
->checksum_vector
* 4), 0, 32, checksum
);
606 /* allocate a working area */
607 if (target_alloc_working_area(target
, lpc2000_info
->cmd51_max_buffer
, &download_area
) != ERROR_OK
)
609 LOG_ERROR("no working area specified, can't write LPC2000 internal flash");
610 return ERROR_FLASH_OPERATION_FAILED
;
613 while (bytes_remaining
> 0)
615 uint32_t thisrun_bytes
;
616 if (bytes_remaining
>= lpc2000_info
->cmd51_max_buffer
)
617 thisrun_bytes
= lpc2000_info
->cmd51_max_buffer
;
618 else if (bytes_remaining
>= 1024)
619 thisrun_bytes
= 1024;
620 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
625 /* Prepare sectors */
626 param_table
[0] = first_sector
;
627 param_table
[1] = last_sector
;
628 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
631 case ERROR_FLASH_OPERATION_FAILED
:
632 retval
= ERROR_FLASH_OPERATION_FAILED
;
634 case LPC2000_CMD_SUCCESS
:
636 case LPC2000_INVALID_SECTOR
:
637 retval
= ERROR_FLASH_SECTOR_INVALID
;
640 LOG_WARNING("lpc2000 prepare sectors returned %i", status_code
);
641 retval
= ERROR_FLASH_OPERATION_FAILED
;
645 /* Exit if error occured */
646 if (retval
!= ERROR_OK
)
649 if (bytes_remaining
>= thisrun_bytes
)
651 if ((retval
= target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
)) != ERROR_OK
)
653 retval
= ERROR_FLASH_OPERATION_FAILED
;
659 uint8_t *last_buffer
= malloc(thisrun_bytes
);
660 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
661 memset(last_buffer
+ bytes_remaining
, 0xff, thisrun_bytes
- bytes_remaining
);
662 target_write_buffer(bank
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
666 LOG_DEBUG("writing 0x%" PRIx32
" bytes to address 0x%" PRIx32
, thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
669 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
670 param_table
[1] = download_area
->address
;
671 param_table
[2] = thisrun_bytes
;
672 param_table
[3] = lpc2000_info
->cclk
;
673 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
676 case ERROR_FLASH_OPERATION_FAILED
:
677 retval
= ERROR_FLASH_OPERATION_FAILED
;
679 case LPC2000_CMD_SUCCESS
:
681 case LPC2000_INVALID_SECTOR
:
682 retval
= ERROR_FLASH_SECTOR_INVALID
;
685 LOG_WARNING("lpc2000 returned %i", status_code
);
686 retval
= ERROR_FLASH_OPERATION_FAILED
;
690 /* Exit if error occured */
691 if (retval
!= ERROR_OK
)
694 if (bytes_remaining
> thisrun_bytes
)
695 bytes_remaining
-= thisrun_bytes
;
698 bytes_written
+= thisrun_bytes
;
701 target_free_working_area(target
, download_area
);
706 static int lpc2000_probe(struct flash_bank_s
*bank
)
708 /* we can't probe on an lpc2000
709 * if this is an lpc2xxx, it has the configured flash
714 static int lpc2000_erase_check(struct flash_bank_s
*bank
)
716 if (bank
->target
->state
!= TARGET_HALTED
)
718 LOG_ERROR("Target not halted");
719 return ERROR_TARGET_NOT_HALTED
;
722 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
725 static int lpc2000_protect_check(struct flash_bank_s
*bank
)
727 /* sectors are always protected */
731 static int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
733 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
735 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %" PRIi32
"kHz" , lpc2000_info
->variant
, lpc2000_info
->cclk
);
740 COMMAND_HANDLER(lpc2000_handle_part_id_command
)
742 uint32_t param_table
[5];
743 uint32_t result_table
[4];
748 return ERROR_COMMAND_SYNTAX_ERROR
;
752 int retval
= flash_command_get_bank_by_num(cmd_ctx
, args
[0], &bank
);
753 if (ERROR_OK
!= retval
)
756 if (bank
->target
->state
!= TARGET_HALTED
)
758 LOG_ERROR("Target not halted");
759 return ERROR_TARGET_NOT_HALTED
;
762 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
764 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
766 command_print(cmd_ctx
, "no sufficient working area specified, can't access LPC2000 IAP interface");
769 command_print(cmd_ctx
, "lpc2000 IAP returned status code %i", status_code
);
773 command_print(cmd_ctx
, "lpc2000 part id: 0x%8.8" PRIx32
, result_table
[0]);
779 static int lpc2000_register_commands(struct command_context_s
*cmd_ctx
)
781 command_t
*lpc2000_cmd
= register_command(cmd_ctx
, NULL
, "lpc2000",
782 NULL
, COMMAND_ANY
, NULL
);
784 register_command(cmd_ctx
, lpc2000_cmd
, "part_id",
785 lpc2000_handle_part_id_command
, COMMAND_EXEC
,
786 "print part id of lpc2000 flash bank <num>");
791 flash_driver_t lpc2000_flash
= {
793 .register_commands
= &lpc2000_register_commands
,
794 .flash_bank_command
= &lpc2000_flash_bank_command
,
795 .erase
= &lpc2000_erase
,
796 .protect
= &lpc2000_protect
,
797 .write
= &lpc2000_write
,
798 .probe
= &lpc2000_probe
,
799 .auto_probe
= &lpc2000_probe
,
800 .erase_check
= &lpc2000_erase_check
,
801 .protect_check
= &lpc2000_protect_check
,
802 .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)