1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
30 #include "algorithm.h"
31 #include "binarybuffer.h"
36 /* flash programming support for Philips LPC2xxx devices
37 * currently supported devices:
38 * variant 1 (lpc2000_v1):
46 * variant 2 (lpc2000_v2):
54 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
);
55 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
56 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
);
57 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
58 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
59 int lpc2000_probe(struct flash_bank_s
*bank
);
60 int lpc2000_erase_check(struct flash_bank_s
*bank
);
61 int lpc2000_protect_check(struct flash_bank_s
*bank
);
62 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
64 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
66 flash_driver_t lpc2000_flash
=
69 .register_commands
= lpc2000_register_commands
,
70 .flash_bank_command
= lpc2000_flash_bank_command
,
71 .erase
= lpc2000_erase
,
72 .protect
= lpc2000_protect
,
73 .write
= lpc2000_write
,
74 .probe
= lpc2000_probe
,
75 .erase_check
= lpc2000_erase_check
,
76 .protect_check
= lpc2000_protect_check
,
80 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
)
82 command_t
*lpc2000_cmd
= register_command(cmd_ctx
, NULL
, "lpc2000", NULL
, COMMAND_ANY
, NULL
);
84 register_command(cmd_ctx
, lpc2000_cmd
, "part_id", lpc2000_handle_part_id_command
, COMMAND_EXEC
,
85 "print part id of lpc2000 flash bank <num>");
90 int lpc2000_build_sector_list(struct flash_bank_s
*bank
)
92 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
94 if (lpc2000_info
->variant
== 1)
99 /* variant 1 has different layout for 128kb and 256kb flashes */
100 if (bank
->size
== 128 * 1024)
102 bank
->num_sectors
= 16;
103 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 16);
104 for (i
= 0; i
< 16; i
++)
106 bank
->sectors
[i
].offset
= offset
;
107 bank
->sectors
[i
].size
= 8 * 1024;
108 offset
+= bank
->sectors
[i
].size
;
109 bank
->sectors
[i
].is_erased
= -1;
110 bank
->sectors
[i
].is_protected
= 1;
113 else if (bank
->size
== 256 * 1024)
115 bank
->num_sectors
= 18;
116 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 18);
118 for (i
= 0; i
< 8; 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 for (i
= 8; i
< 10; i
++)
128 bank
->sectors
[i
].offset
= offset
;
129 bank
->sectors
[i
].size
= 64 * 1024;
130 offset
+= bank
->sectors
[i
].size
;
131 bank
->sectors
[i
].is_erased
= -1;
132 bank
->sectors
[i
].is_protected
= 1;
134 for (i
= 10; i
< 18; i
++)
136 bank
->sectors
[i
].offset
= offset
;
137 bank
->sectors
[i
].size
= 8 * 1024;
138 offset
+= bank
->sectors
[i
].size
;
139 bank
->sectors
[i
].is_erased
= -1;
140 bank
->sectors
[i
].is_protected
= 1;
145 ERROR("BUG: unknown bank->size encountered");
149 else if (lpc2000_info
->variant
== 2)
155 /* variant 2 has a uniform layout, only number of sectors differs */
181 ERROR("BUG: unknown bank->size encountered");
186 bank
->num_sectors
= num_sectors
;
187 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
189 for (i
= 0; i
< num_sectors
; i
++)
191 if ((i
>= 0) && (i
< 8))
193 bank
->sectors
[i
].offset
= offset
;
194 bank
->sectors
[i
].size
= 4 * 1024;
195 offset
+= bank
->sectors
[i
].size
;
196 bank
->sectors
[i
].is_erased
= -1;
197 bank
->sectors
[i
].is_protected
= 1;
199 if ((i
>= 8) && (i
< 22))
201 bank
->sectors
[i
].offset
= offset
;
202 bank
->sectors
[i
].size
= 32 * 1024;
203 offset
+= bank
->sectors
[i
].size
;
204 bank
->sectors
[i
].is_erased
= -1;
205 bank
->sectors
[i
].is_protected
= 1;
207 if ((i
>= 22) && (i
< 27))
209 bank
->sectors
[i
].offset
= offset
;
210 bank
->sectors
[i
].size
= 4 * 1024;
211 offset
+= bank
->sectors
[i
].size
;
212 bank
->sectors
[i
].is_erased
= -1;
213 bank
->sectors
[i
].is_protected
= 1;
219 ERROR("BUG: unknown lpc2000_info->variant encountered");
226 /* call LPC2000 IAP function
227 * uses 172 bytes working area
228 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
229 * 0x8 to 0x1f: command parameter table
230 * 0x20 to 0x2b: command result table
231 * 0x2c to 0xac: stack (only 128b needed)
233 int lpc2000_iap_call(flash_bank_t
*bank
, int code
, u32 param_table
[5], u32 result_table
[2])
235 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
236 target_t
*target
= lpc2000_info
->target
;
237 mem_param_t mem_params
[2];
238 reg_param_t reg_params
[5];
239 armv4_5_algorithm_t armv4_5_info
;
242 /* regrab previously allocated working_area, or allocate a new one */
243 if (!lpc2000_info
->iap_working_area
)
247 /* make sure we have a working area */
248 if (target_alloc_working_area(target
, 172, &lpc2000_info
->iap_working_area
) != ERROR_OK
)
250 ERROR("no working area specified, can't write LPC2000 internal flash");
251 return ERROR_FLASH_OPERATION_FAILED
;
254 /* write IAP code to working area */
255 target_buffer_set_u32(target
, jump_gate
, ARMV4_5_BX(12));
256 target_buffer_set_u32(target
, jump_gate
+ 4, ARMV4_5_B(0xfffffe, 0));
257 target
->type
->write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, jump_gate
);
260 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
261 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
262 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
264 /* command parameter table */
265 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 4 * 6, PARAM_OUT
);
266 target_buffer_set_u32(target
, mem_params
[0].value
, code
);
267 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x4, param_table
[0]);
268 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x8, param_table
[1]);
269 target_buffer_set_u32(target
, mem_params
[0].value
+ 0xc, param_table
[2]);
270 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x10, param_table
[3]);
271 target_buffer_set_u32(target
, mem_params
[0].value
+ 0x14, param_table
[4]);
273 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
274 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x8);
276 /* command result table */
277 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 4 * 3, PARAM_IN
);
279 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
280 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
282 /* IAP entry point */
283 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
284 buf_set_u32(reg_params
[2].value
, 0, 32, 0x7ffffff1);
287 init_reg_param(®_params
[3], "r13_svc", 32, PARAM_OUT
);
288 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xac);
291 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
292 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x4);
294 target
->type
->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
);
296 status_code
= buf_get_u32(mem_params
[1].value
, 0, 32);
297 result_table
[0] = target_buffer_get_u32(target
, mem_params
[1].value
);
298 result_table
[1] = target_buffer_get_u32(target
, mem_params
[1].value
+ 4);
300 destroy_mem_param(&mem_params
[0]);
301 destroy_mem_param(&mem_params
[1]);
303 destroy_reg_param(®_params
[0]);
304 destroy_reg_param(®_params
[1]);
305 destroy_reg_param(®_params
[2]);
306 destroy_reg_param(®_params
[3]);
307 destroy_reg_param(®_params
[4]);
312 int lpc2000_iap_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
319 if ((first
< 0) || (last
> bank
->num_sectors
))
320 return ERROR_FLASH_SECTOR_INVALID
;
322 for (i
= first
; i
<= last
; i
++)
324 /* check single sector */
325 param_table
[0] = param_table
[1] = i
;
326 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
330 case ERROR_FLASH_OPERATION_FAILED
:
331 return ERROR_FLASH_OPERATION_FAILED
;
332 case LPC2000_CMD_SUCCESS
:
333 bank
->sectors
[i
].is_erased
= 1;
335 case LPC2000_SECTOR_NOT_BLANK
:
336 bank
->sectors
[i
].is_erased
= 0;
338 case LPC2000_INVALID_SECTOR
:
339 bank
->sectors
[i
].is_erased
= 0;
342 return ERROR_FLASH_BUSY
;
345 ERROR("BUG: unknown LPC2000 status code");
353 /* flash bank lpc2000 <base> <size> 0 0 <lpc_variant> <target#> <cclk> [calc_checksum]
355 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
357 lpc2000_flash_bank_t
*lpc2000_info
;
361 WARNING("incomplete flash_bank lpc2000 configuration");
362 return ERROR_FLASH_BANK_INVALID
;
365 lpc2000_info
= malloc(sizeof(lpc2000_flash_bank_t
));
366 bank
->driver_priv
= lpc2000_info
;
368 if (strcmp(args
[5], "lpc2000_v1") == 0)
370 lpc2000_info
->variant
= 1;
371 lpc2000_info
->cmd51_dst_boundary
= 512;
372 lpc2000_info
->cmd51_can_256b
= 0;
373 lpc2000_info
->cmd51_can_8192b
= 1;
375 else if (strcmp(args
[5], "lpc2000_v2") == 0)
377 lpc2000_info
->variant
= 2;
378 lpc2000_info
->cmd51_dst_boundary
= 256;
379 lpc2000_info
->cmd51_can_256b
= 1;
380 lpc2000_info
->cmd51_can_8192b
= 0;
384 ERROR("unknown LPC2000 variant");
386 return ERROR_FLASH_BANK_INVALID
;
389 lpc2000_info
->target
= get_target_by_num(strtoul(args
[6], NULL
, 0));
390 if (!lpc2000_info
->target
)
392 ERROR("no target '%s' configured", args
[6]);
395 lpc2000_info
->iap_working_area
= NULL
;
396 lpc2000_info
->cclk
= strtoul(args
[7], NULL
, 0);
397 lpc2000_info
->calc_checksum
= 0;
398 lpc2000_build_sector_list(bank
);
403 if (strcmp(args
[8], "calc_checksum") == 0)
404 lpc2000_info
->calc_checksum
= 1;
410 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
)
412 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
417 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
419 return ERROR_TARGET_NOT_HALTED
;
422 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
424 return ERROR_FLASH_SECTOR_INVALID
;
427 param_table
[0] = first
;
428 param_table
[1] = last
;
429 param_table
[2] = lpc2000_info
->cclk
;
431 /* Prepare sectors */
432 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
435 case ERROR_FLASH_OPERATION_FAILED
:
436 return ERROR_FLASH_OPERATION_FAILED
;
437 case LPC2000_CMD_SUCCESS
:
439 case LPC2000_INVALID_SECTOR
:
440 return ERROR_FLASH_SECTOR_INVALID
;
443 WARNING("lpc2000 prepare sectors returned %i", status_code
);
444 return ERROR_FLASH_OPERATION_FAILED
;
448 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
451 case ERROR_FLASH_OPERATION_FAILED
:
452 return ERROR_FLASH_OPERATION_FAILED
;
453 case LPC2000_CMD_SUCCESS
:
455 case LPC2000_INVALID_SECTOR
:
456 return ERROR_FLASH_SECTOR_INVALID
;
459 WARNING("lpc2000 erase sectors returned %i", status_code
);
460 return ERROR_FLASH_OPERATION_FAILED
;
466 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
468 /* can't protect/unprotect on the lpc2000 */
472 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
474 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
475 target_t
*target
= lpc2000_info
->target
;
476 u32 dst_min_alignment
;
477 u32 bytes_remaining
= count
;
478 u32 bytes_written
= 0;
479 int first_sector
= 0;
485 working_area_t
*download_area
;
487 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
489 return ERROR_TARGET_NOT_HALTED
;
492 /* allocate a working area */
493 if (target_alloc_working_area(target
, 4096, &download_area
) != ERROR_OK
)
495 ERROR("no working area specified, can't write LPC2000 internal flash");
496 return ERROR_FLASH_OPERATION_FAILED
;
499 if (offset
+ count
> bank
->size
)
500 return ERROR_FLASH_DST_OUT_OF_BANK
;
502 if (lpc2000_info
->cmd51_can_256b
)
503 dst_min_alignment
= 256;
505 dst_min_alignment
= 512;
507 if (offset
% dst_min_alignment
)
509 WARNING("offset 0x%x breaks required alignment 0x%x", offset
, dst_min_alignment
);
510 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
513 for (i
= 0; i
< bank
->num_sectors
; i
++)
515 if (offset
>= bank
->sectors
[i
].offset
)
517 if (offset
+ CEIL(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
521 DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
523 /* check if exception vectors should be flashed */
524 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
528 for (i
= 0; i
< 8; i
++)
530 DEBUG("0x%2.2x: 0x%8.8x", i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
532 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
534 checksum
= 0 - checksum
;
535 DEBUG("checksum: 0x%8.8x", checksum
);
536 buf_set_u32(buffer
+ 0x14, 0, 32, checksum
);
539 while (bytes_remaining
> 0)
542 if (bytes_remaining
>= 4096)
543 thisrun_bytes
= 4096;
544 else if (bytes_remaining
>= 1024)
545 thisrun_bytes
= 1024;
546 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
551 /* Prepare sectors */
552 param_table
[0] = first_sector
;
553 param_table
[1] = last_sector
;
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 WARNING("lpc2000 prepare sectors returned %i", status_code
);
566 return ERROR_FLASH_OPERATION_FAILED
;
569 if (bytes_remaining
>= thisrun_bytes
)
571 if (target_write_buffer(lpc2000_info
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
) != ERROR_OK
)
573 target_free_working_area(target
, download_area
);
574 return ERROR_FLASH_OPERATION_FAILED
;
579 u8
*last_buffer
= malloc(thisrun_bytes
);
581 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
582 for (i
= bytes_remaining
; i
< thisrun_bytes
; i
++)
583 last_buffer
[i
] = 0xff;
584 target_write_buffer(lpc2000_info
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
588 DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
591 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
592 param_table
[1] = download_area
->address
;
593 param_table
[2] = thisrun_bytes
;
594 param_table
[3] = lpc2000_info
->cclk
;
595 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
598 case ERROR_FLASH_OPERATION_FAILED
:
599 return ERROR_FLASH_OPERATION_FAILED
;
600 case LPC2000_CMD_SUCCESS
:
602 case LPC2000_INVALID_SECTOR
:
603 return ERROR_FLASH_SECTOR_INVALID
;
606 WARNING("lpc2000 returned %i", status_code
);
607 return ERROR_FLASH_OPERATION_FAILED
;
610 if (bytes_remaining
> thisrun_bytes
)
611 bytes_remaining
-= thisrun_bytes
;
614 bytes_written
+= thisrun_bytes
;
617 target_free_working_area(target
, download_area
);
622 int lpc2000_probe(struct flash_bank_s
*bank
)
624 /* we can't probe on an lpc2000
625 * if this is an lpc2xxx, it has the configured flash
630 int lpc2000_erase_check(struct flash_bank_s
*bank
)
632 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
634 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
636 return ERROR_TARGET_NOT_HALTED
;
639 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
642 int lpc2000_protect_check(struct flash_bank_s
*bank
)
644 /* sectors are always protected */
648 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
650 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
652 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info
->variant
, lpc2000_info
->cclk
);
657 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
663 lpc2000_flash_bank_t
*lpc2000_info
;
667 command_print(cmd_ctx
, "usage: lpc2000 part_id <num>");
671 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
674 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
678 lpc2000_info
= bank
->driver_priv
;
679 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
681 return ERROR_TARGET_NOT_HALTED
;
684 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
686 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
688 command_print(cmd_ctx
, "no sufficient working area specified, can't access LPC2000 IAP interface");
691 command_print(cmd_ctx
, "lpc2000 IAP returned status code %i", status_code
);
695 command_print(cmd_ctx
, "lpc2000 part id: 0x%8.8x", result_table
[0]);
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)