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 ***************************************************************************/
26 #include "algorithm.h"
27 #include "binarybuffer.h"
32 /* flash programming support for Philips LPC2xxx devices
33 * currently supported devices:
34 * variant 1 (lpc2000_v1):
42 * variant 2 (lpc2000_v2):
47 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
);
48 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
49 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
);
50 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
51 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
52 int lpc2000_probe(struct flash_bank_s
*bank
);
53 int lpc2000_erase_check(struct flash_bank_s
*bank
);
54 int lpc2000_protect_check(struct flash_bank_s
*bank
);
55 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
57 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
59 flash_driver_t lpc2000_flash
=
62 .register_commands
= lpc2000_register_commands
,
63 .flash_bank_command
= lpc2000_flash_bank_command
,
64 .erase
= lpc2000_erase
,
65 .protect
= lpc2000_protect
,
66 .write
= lpc2000_write
,
67 .probe
= lpc2000_probe
,
68 .erase_check
= lpc2000_erase_check
,
69 .protect_check
= lpc2000_protect_check
,
73 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
)
75 command_t
*lpc2000_cmd
= register_command(cmd_ctx
, NULL
, "lpc2000", NULL
, COMMAND_ANY
, NULL
);
77 register_command(cmd_ctx
, lpc2000_cmd
, "part_id", lpc2000_handle_part_id_command
, COMMAND_EXEC
,
78 "print part id of lpc2000 flash bank <num>");
83 int lpc2000_build_sector_list(struct flash_bank_s
*bank
)
85 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
87 if (lpc2000_info
->variant
== 1)
92 /* variant 1 has different layout for 128kb and 256kb flashes */
93 if (bank
->size
== 128 * 1024)
95 bank
->num_sectors
= 16;
96 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 16);
97 for (i
= 0; i
< 16; i
++)
99 bank
->sectors
[i
].offset
= offset
;
100 bank
->sectors
[i
].size
= 8 * 1024;
101 offset
+= bank
->sectors
[i
].size
;
102 bank
->sectors
[i
].is_erased
= -1;
103 bank
->sectors
[i
].is_protected
= 1;
106 else if (bank
->size
== 256 * 1024)
108 bank
->num_sectors
= 18;
109 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 18);
111 for (i
= 0; i
< 8; i
++)
113 bank
->sectors
[i
].offset
= offset
;
114 bank
->sectors
[i
].size
= 8 * 1024;
115 offset
+= bank
->sectors
[i
].size
;
116 bank
->sectors
[i
].is_erased
= -1;
117 bank
->sectors
[i
].is_protected
= 1;
119 for (i
= 8; i
< 10; i
++)
121 bank
->sectors
[i
].offset
= offset
;
122 bank
->sectors
[i
].size
= 64 * 1024;
123 offset
+= bank
->sectors
[i
].size
;
124 bank
->sectors
[i
].is_erased
= -1;
125 bank
->sectors
[i
].is_protected
= 1;
127 for (i
= 10; i
< 18; i
++)
129 bank
->sectors
[i
].offset
= offset
;
130 bank
->sectors
[i
].size
= 8 * 1024;
131 offset
+= bank
->sectors
[i
].size
;
132 bank
->sectors
[i
].is_erased
= -1;
133 bank
->sectors
[i
].is_protected
= 1;
138 ERROR("BUG: unknown bank->size encountered");
142 else if (lpc2000_info
->variant
== 2)
148 /* variant 2 has a uniform layout, only number of sectors differs */
167 ERROR("BUG: unknown bank->size encountered");
172 bank
->num_sectors
= num_sectors
;
173 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
175 for (i
= 0; i
< num_sectors
; i
++)
177 if ((i
>= 0) && (i
< 8))
179 bank
->sectors
[i
].offset
= offset
;
180 bank
->sectors
[i
].size
= 4 * 1024;
181 offset
+= bank
->sectors
[i
].size
;
182 bank
->sectors
[i
].is_erased
= -1;
183 bank
->sectors
[i
].is_protected
= 1;
185 if ((i
>= 8) && (i
< 22))
187 bank
->sectors
[i
].offset
= offset
;
188 bank
->sectors
[i
].size
= 32 * 1024;
189 offset
+= bank
->sectors
[i
].size
;
190 bank
->sectors
[i
].is_erased
= -1;
191 bank
->sectors
[i
].is_protected
= 1;
193 if ((i
>= 22) && (i
< 27))
195 bank
->sectors
[i
].offset
= offset
;
196 bank
->sectors
[i
].size
= 4 * 1024;
197 offset
+= bank
->sectors
[i
].size
;
198 bank
->sectors
[i
].is_erased
= -1;
199 bank
->sectors
[i
].is_protected
= 1;
205 ERROR("BUG: unknown lpc2000_info->variant encountered");
212 /* call LPC2000 IAP function
213 * uses 172 bytes working area
214 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
215 * 0x8 to 0x1f: command parameter table
216 * 0x20 to 0x2b: command result table
217 * 0x2c to 0xac: stack (only 128b needed)
219 int lpc2000_iap_call(flash_bank_t
*bank
, int code
, u32 param_table
[5], u32 result_table
[2])
221 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
222 target_t
*target
= lpc2000_info
->target
;
223 mem_param_t mem_params
[2];
224 reg_param_t reg_params
[5];
225 armv4_5_algorithm_t armv4_5_info
;
228 /* regrab previously allocated working_area, or allocate a new one */
229 if (!lpc2000_info
->iap_working_area
)
233 /* make sure we have a working area */
234 if (target_alloc_working_area(target
, 172, &lpc2000_info
->iap_working_area
) != ERROR_OK
)
236 ERROR("no working area specified, can't write LPC2000 internal flash");
237 return ERROR_FLASH_OPERATION_FAILED
;
240 /* write IAP code to working area */
241 buf_set_u32(jump_gate
, 0, 32, ARMV4_5_BX(12));
242 buf_set_u32(jump_gate
, 32, 32, 0xeafffffe);
243 target
->type
->write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, (u8
*)jump_gate
);
246 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
247 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
248 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
250 /* command parameter table */
251 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 4 * 6, PARAM_OUT
);
252 buf_set_u32(mem_params
[0].value
, 0, 32, code
);
253 buf_set_u32(mem_params
[0].value
, 32, 32, param_table
[0]);
254 buf_set_u32(mem_params
[0].value
, 64, 32, param_table
[1]);
255 buf_set_u32(mem_params
[0].value
, 96, 32, param_table
[2]);
256 buf_set_u32(mem_params
[0].value
, 128, 32, param_table
[3]);
257 buf_set_u32(mem_params
[0].value
, 160, 32, param_table
[4]);
259 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
260 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x8);
262 /* command result table */
263 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 4 * 3, PARAM_IN
);
265 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
266 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
268 /* IAP entry point */
269 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
270 buf_set_u32(reg_params
[2].value
, 0, 32, 0x7ffffff1);
273 init_reg_param(®_params
[3], "r13_svc", 32, PARAM_OUT
);
274 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xac);
277 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
278 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x4);
280 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
);
282 status_code
= buf_get_u32(mem_params
[1].value
, 0, 32);
283 result_table
[0] = buf_get_u32(mem_params
[1].value
, 32, 32);
284 result_table
[1] = buf_get_u32(mem_params
[1].value
, 64, 32);
286 destroy_mem_param(&mem_params
[0]);
287 destroy_mem_param(&mem_params
[1]);
289 destroy_reg_param(®_params
[0]);
290 destroy_reg_param(®_params
[1]);
291 destroy_reg_param(®_params
[2]);
292 destroy_reg_param(®_params
[3]);
293 destroy_reg_param(®_params
[4]);
298 int lpc2000_iap_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
305 if ((first
< 0) || (last
> bank
->num_sectors
))
306 return ERROR_FLASH_SECTOR_INVALID
;
308 for (i
= first
; i
<= last
; i
++)
310 /* check single sector */
311 param_table
[0] = param_table
[1] = i
;
312 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
316 case ERROR_FLASH_OPERATION_FAILED
:
317 return ERROR_FLASH_OPERATION_FAILED
;
318 case LPC2000_CMD_SUCCESS
:
319 bank
->sectors
[i
].is_erased
= 1;
321 case LPC2000_SECTOR_NOT_BLANK
:
322 bank
->sectors
[i
].is_erased
= 0;
324 case LPC2000_INVALID_SECTOR
:
325 bank
->sectors
[i
].is_erased
= 0;
328 return ERROR_FLASH_BUSY
;
331 ERROR("BUG: unknown LPC2000 status code");
339 /* flash_bank lpc2000 <base> <size> 0 0 <lpc_variant> <target#> <cclk> [calc_checksum]
341 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
343 lpc2000_flash_bank_t
*lpc2000_info
;
347 WARNING("incomplete flash_bank lpc2000 configuration");
348 return ERROR_FLASH_BANK_INVALID
;
351 lpc2000_info
= malloc(sizeof(lpc2000_flash_bank_t
));
352 bank
->driver_priv
= lpc2000_info
;
354 if (strcmp(args
[5], "lpc2000_v1") == 0)
356 lpc2000_info
->variant
= 1;
357 lpc2000_info
->cmd51_dst_boundary
= 512;
358 lpc2000_info
->cmd51_can_256b
= 0;
359 lpc2000_info
->cmd51_can_8192b
= 1;
361 else if (strcmp(args
[5], "lpc2000_v2") == 0)
363 lpc2000_info
->variant
= 2;
364 lpc2000_info
->cmd51_dst_boundary
= 256;
365 lpc2000_info
->cmd51_can_256b
= 1;
366 lpc2000_info
->cmd51_can_8192b
= 0;
370 ERROR("unknown LPC2000 variant");
372 return ERROR_FLASH_BANK_INVALID
;
375 lpc2000_info
->target
= get_target_by_num(strtoul(args
[6], NULL
, 0));
376 if (!lpc2000_info
->target
)
378 ERROR("no target '%s' configured", args
[6]);
381 lpc2000_info
->iap_working_area
= NULL
;
382 lpc2000_info
->cclk
= strtoul(args
[7], NULL
, 0);
383 lpc2000_info
->calc_checksum
= 0;
384 lpc2000_build_sector_list(bank
);
389 if (strcmp(args
[8], "calc_checksum") == 0)
390 lpc2000_info
->calc_checksum
= 1;
396 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
)
398 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
403 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
405 return ERROR_TARGET_NOT_HALTED
;
408 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
410 return ERROR_FLASH_SECTOR_INVALID
;
413 param_table
[0] = first
;
414 param_table
[1] = last
;
415 param_table
[2] = lpc2000_info
->cclk
;
417 /* Prepare sectors */
418 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
421 case ERROR_FLASH_OPERATION_FAILED
:
422 return ERROR_FLASH_OPERATION_FAILED
;
423 case LPC2000_CMD_SUCCESS
:
425 case LPC2000_INVALID_SECTOR
:
426 return ERROR_FLASH_SECTOR_INVALID
;
429 WARNING("lpc2000 prepare sectors returned %i", status_code
);
430 return ERROR_FLASH_OPERATION_FAILED
;
434 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
437 case ERROR_FLASH_OPERATION_FAILED
:
438 return ERROR_FLASH_OPERATION_FAILED
;
439 case LPC2000_CMD_SUCCESS
:
441 case LPC2000_INVALID_SECTOR
:
442 return ERROR_FLASH_SECTOR_INVALID
;
445 WARNING("lpc2000 erase sectors returned %i", status_code
);
446 return ERROR_FLASH_OPERATION_FAILED
;
452 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
454 /* can't protect/unprotect on the lpc2000 */
458 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
460 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
461 target_t
*target
= lpc2000_info
->target
;
462 u32 dst_min_alignment
;
463 u32 bytes_remaining
= count
;
464 u32 bytes_written
= 0;
465 int first_sector
= 0;
471 working_area_t
*download_area
;
473 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
475 return ERROR_TARGET_NOT_HALTED
;
478 /* allocate a working area */
479 if (target_alloc_working_area(target
, 4096, &download_area
) != ERROR_OK
)
481 ERROR("no working area specified, can't write LPC2000 internal flash");
482 return ERROR_FLASH_OPERATION_FAILED
;
485 if (offset
+ count
> bank
->size
)
486 return ERROR_FLASH_DST_OUT_OF_BANK
;
488 if (lpc2000_info
->cmd51_can_256b
)
489 dst_min_alignment
= 256;
491 dst_min_alignment
= 512;
493 if (offset
% dst_min_alignment
)
495 WARNING("offset 0x%x breaks required alignment 0x%x", offset
, dst_min_alignment
);
496 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
499 for (i
= 0; i
< bank
->num_sectors
; i
++)
501 if (offset
>= bank
->sectors
[i
].offset
)
503 if (offset
+ CEIL(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
507 DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
509 /* check if exception vectors should be flashed */
510 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
514 for (i
= 0; i
< 8; i
++)
516 DEBUG("0x%2.2x: 0x%8.8x", i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
518 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
520 checksum
= 0 - checksum
;
521 DEBUG("checksum: 0x%8.8x", checksum
);
522 buf_set_u32(buffer
+ 0x14, 0, 32, checksum
);
525 while (bytes_remaining
> 0)
528 if (bytes_remaining
>= 4096)
529 thisrun_bytes
= 4096;
530 else if (bytes_remaining
>= 1024)
531 thisrun_bytes
= 1024;
532 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
537 /* Prepare sectors */
538 param_table
[0] = first_sector
;
539 param_table
[1] = last_sector
;
540 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
543 case ERROR_FLASH_OPERATION_FAILED
:
544 return ERROR_FLASH_OPERATION_FAILED
;
545 case LPC2000_CMD_SUCCESS
:
547 case LPC2000_INVALID_SECTOR
:
548 return ERROR_FLASH_SECTOR_INVALID
;
551 WARNING("lpc2000 prepare sectors returned %i", status_code
);
552 return ERROR_FLASH_OPERATION_FAILED
;
555 if (bytes_remaining
>= thisrun_bytes
)
557 if (target_write_buffer(lpc2000_info
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
) != ERROR_OK
)
559 target_free_working_area(target
, download_area
);
560 return ERROR_FLASH_OPERATION_FAILED
;
565 u8
*last_buffer
= malloc(thisrun_bytes
);
567 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
568 for (i
= bytes_remaining
; i
< thisrun_bytes
; i
++)
569 last_buffer
[i
] = 0xff;
570 target_write_buffer(lpc2000_info
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
574 DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
577 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
578 param_table
[1] = download_area
->address
;
579 param_table
[2] = thisrun_bytes
;
580 param_table
[3] = lpc2000_info
->cclk
;
581 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
584 case ERROR_FLASH_OPERATION_FAILED
:
585 return ERROR_FLASH_OPERATION_FAILED
;
586 case LPC2000_CMD_SUCCESS
:
588 case LPC2000_INVALID_SECTOR
:
589 return ERROR_FLASH_SECTOR_INVALID
;
592 WARNING("lpc2000 returned %i", status_code
);
593 return ERROR_FLASH_OPERATION_FAILED
;
596 if (bytes_remaining
> thisrun_bytes
)
597 bytes_remaining
-= thisrun_bytes
;
600 bytes_written
+= thisrun_bytes
;
603 target_free_working_area(target
, download_area
);
608 int lpc2000_probe(struct flash_bank_s
*bank
)
610 /* we can't probe on an lpc2000
611 * if this is an lpc2xxx, it has the configured flash
616 int lpc2000_erase_check(struct flash_bank_s
*bank
)
618 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
620 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
622 return ERROR_TARGET_NOT_HALTED
;
625 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
628 int lpc2000_protect_check(struct flash_bank_s
*bank
)
630 /* sectors are always protected */
634 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
636 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
638 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info
->variant
, lpc2000_info
->cclk
);
643 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
649 lpc2000_flash_bank_t
*lpc2000_info
;
653 command_print(cmd_ctx
, "usage: lpc2000 part_id <num>");
657 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
660 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
664 lpc2000_info
= bank
->driver_priv
;
665 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
667 return ERROR_TARGET_NOT_HALTED
;
670 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
672 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
674 command_print(cmd_ctx
, "no sufficient working area specified, can't access LPC2000 IAP interface");
677 command_print(cmd_ctx
, "lpc2000 IAP returned status code %i", status_code
);
681 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)