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):
51 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
);
52 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
53 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
);
54 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
55 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
56 int lpc2000_probe(struct flash_bank_s
*bank
);
57 int lpc2000_erase_check(struct flash_bank_s
*bank
);
58 int lpc2000_protect_check(struct flash_bank_s
*bank
);
59 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
61 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
63 flash_driver_t lpc2000_flash
=
66 .register_commands
= lpc2000_register_commands
,
67 .flash_bank_command
= lpc2000_flash_bank_command
,
68 .erase
= lpc2000_erase
,
69 .protect
= lpc2000_protect
,
70 .write
= lpc2000_write
,
71 .probe
= lpc2000_probe
,
72 .erase_check
= lpc2000_erase_check
,
73 .protect_check
= lpc2000_protect_check
,
77 int lpc2000_register_commands(struct command_context_s
*cmd_ctx
)
79 command_t
*lpc2000_cmd
= register_command(cmd_ctx
, NULL
, "lpc2000", NULL
, COMMAND_ANY
, NULL
);
81 register_command(cmd_ctx
, lpc2000_cmd
, "part_id", lpc2000_handle_part_id_command
, COMMAND_EXEC
,
82 "print part id of lpc2000 flash bank <num>");
87 int lpc2000_build_sector_list(struct flash_bank_s
*bank
)
89 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
91 if (lpc2000_info
->variant
== 1)
96 /* variant 1 has different layout for 128kb and 256kb flashes */
97 if (bank
->size
== 128 * 1024)
99 bank
->num_sectors
= 16;
100 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 16);
101 for (i
= 0; i
< 16; i
++)
103 bank
->sectors
[i
].offset
= offset
;
104 bank
->sectors
[i
].size
= 8 * 1024;
105 offset
+= bank
->sectors
[i
].size
;
106 bank
->sectors
[i
].is_erased
= -1;
107 bank
->sectors
[i
].is_protected
= 1;
110 else if (bank
->size
== 256 * 1024)
112 bank
->num_sectors
= 18;
113 bank
->sectors
= malloc(sizeof(flash_sector_t
) * 18);
115 for (i
= 0; i
< 8; i
++)
117 bank
->sectors
[i
].offset
= offset
;
118 bank
->sectors
[i
].size
= 8 * 1024;
119 offset
+= bank
->sectors
[i
].size
;
120 bank
->sectors
[i
].is_erased
= -1;
121 bank
->sectors
[i
].is_protected
= 1;
123 for (i
= 8; i
< 10; i
++)
125 bank
->sectors
[i
].offset
= offset
;
126 bank
->sectors
[i
].size
= 64 * 1024;
127 offset
+= bank
->sectors
[i
].size
;
128 bank
->sectors
[i
].is_erased
= -1;
129 bank
->sectors
[i
].is_protected
= 1;
131 for (i
= 10; i
< 18; i
++)
133 bank
->sectors
[i
].offset
= offset
;
134 bank
->sectors
[i
].size
= 8 * 1024;
135 offset
+= bank
->sectors
[i
].size
;
136 bank
->sectors
[i
].is_erased
= -1;
137 bank
->sectors
[i
].is_protected
= 1;
142 ERROR("BUG: unknown bank->size encountered");
146 else if (lpc2000_info
->variant
== 2)
152 /* variant 2 has a uniform layout, only number of sectors differs */
171 ERROR("BUG: unknown bank->size encountered");
176 bank
->num_sectors
= num_sectors
;
177 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
179 for (i
= 0; i
< num_sectors
; i
++)
181 if ((i
>= 0) && (i
< 8))
183 bank
->sectors
[i
].offset
= offset
;
184 bank
->sectors
[i
].size
= 4 * 1024;
185 offset
+= bank
->sectors
[i
].size
;
186 bank
->sectors
[i
].is_erased
= -1;
187 bank
->sectors
[i
].is_protected
= 1;
189 if ((i
>= 8) && (i
< 22))
191 bank
->sectors
[i
].offset
= offset
;
192 bank
->sectors
[i
].size
= 32 * 1024;
193 offset
+= bank
->sectors
[i
].size
;
194 bank
->sectors
[i
].is_erased
= -1;
195 bank
->sectors
[i
].is_protected
= 1;
197 if ((i
>= 22) && (i
< 27))
199 bank
->sectors
[i
].offset
= offset
;
200 bank
->sectors
[i
].size
= 4 * 1024;
201 offset
+= bank
->sectors
[i
].size
;
202 bank
->sectors
[i
].is_erased
= -1;
203 bank
->sectors
[i
].is_protected
= 1;
209 ERROR("BUG: unknown lpc2000_info->variant encountered");
216 /* call LPC2000 IAP function
217 * uses 172 bytes working area
218 * 0x0 to 0x7: jump gate (BX to thumb state, b -2 to wait)
219 * 0x8 to 0x1f: command parameter table
220 * 0x20 to 0x2b: command result table
221 * 0x2c to 0xac: stack (only 128b needed)
223 int lpc2000_iap_call(flash_bank_t
*bank
, int code
, u32 param_table
[5], u32 result_table
[2])
225 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
226 target_t
*target
= lpc2000_info
->target
;
227 mem_param_t mem_params
[2];
228 reg_param_t reg_params
[5];
229 armv4_5_algorithm_t armv4_5_info
;
232 /* regrab previously allocated working_area, or allocate a new one */
233 if (!lpc2000_info
->iap_working_area
)
237 /* make sure we have a working area */
238 if (target_alloc_working_area(target
, 172, &lpc2000_info
->iap_working_area
) != ERROR_OK
)
240 ERROR("no working area specified, can't write LPC2000 internal flash");
241 return ERROR_FLASH_OPERATION_FAILED
;
244 /* write IAP code to working area */
245 buf_set_u32(jump_gate
, 0, 32, ARMV4_5_BX(12));
246 buf_set_u32(jump_gate
, 32, 32, 0xeafffffe);
247 target
->type
->write_memory(target
, lpc2000_info
->iap_working_area
->address
, 4, 2, (u8
*)jump_gate
);
250 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
251 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
252 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
254 /* command parameter table */
255 init_mem_param(&mem_params
[0], lpc2000_info
->iap_working_area
->address
+ 8, 4 * 6, PARAM_OUT
);
256 buf_set_u32(mem_params
[0].value
, 0, 32, code
);
257 buf_set_u32(mem_params
[0].value
, 32, 32, param_table
[0]);
258 buf_set_u32(mem_params
[0].value
, 64, 32, param_table
[1]);
259 buf_set_u32(mem_params
[0].value
, 96, 32, param_table
[2]);
260 buf_set_u32(mem_params
[0].value
, 128, 32, param_table
[3]);
261 buf_set_u32(mem_params
[0].value
, 160, 32, param_table
[4]);
263 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
264 buf_set_u32(reg_params
[0].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x8);
266 /* command result table */
267 init_mem_param(&mem_params
[1], lpc2000_info
->iap_working_area
->address
+ 0x20, 4 * 3, PARAM_IN
);
269 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
270 buf_set_u32(reg_params
[1].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x20);
272 /* IAP entry point */
273 init_reg_param(®_params
[2], "r12", 32, PARAM_OUT
);
274 buf_set_u32(reg_params
[2].value
, 0, 32, 0x7ffffff1);
277 init_reg_param(®_params
[3], "r13_svc", 32, PARAM_OUT
);
278 buf_set_u32(reg_params
[3].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0xac);
281 init_reg_param(®_params
[4], "lr_svc", 32, PARAM_OUT
);
282 buf_set_u32(reg_params
[4].value
, 0, 32, lpc2000_info
->iap_working_area
->address
+ 0x4);
284 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
);
286 status_code
= buf_get_u32(mem_params
[1].value
, 0, 32);
287 result_table
[0] = buf_get_u32(mem_params
[1].value
, 32, 32);
288 result_table
[1] = buf_get_u32(mem_params
[1].value
, 64, 32);
290 destroy_mem_param(&mem_params
[0]);
291 destroy_mem_param(&mem_params
[1]);
293 destroy_reg_param(®_params
[0]);
294 destroy_reg_param(®_params
[1]);
295 destroy_reg_param(®_params
[2]);
296 destroy_reg_param(®_params
[3]);
297 destroy_reg_param(®_params
[4]);
302 int lpc2000_iap_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
309 if ((first
< 0) || (last
> bank
->num_sectors
))
310 return ERROR_FLASH_SECTOR_INVALID
;
312 for (i
= first
; i
<= last
; i
++)
314 /* check single sector */
315 param_table
[0] = param_table
[1] = i
;
316 status_code
= lpc2000_iap_call(bank
, 53, param_table
, result_table
);
320 case ERROR_FLASH_OPERATION_FAILED
:
321 return ERROR_FLASH_OPERATION_FAILED
;
322 case LPC2000_CMD_SUCCESS
:
323 bank
->sectors
[i
].is_erased
= 1;
325 case LPC2000_SECTOR_NOT_BLANK
:
326 bank
->sectors
[i
].is_erased
= 0;
328 case LPC2000_INVALID_SECTOR
:
329 bank
->sectors
[i
].is_erased
= 0;
332 return ERROR_FLASH_BUSY
;
335 ERROR("BUG: unknown LPC2000 status code");
343 /* flash_bank lpc2000 <base> <size> 0 0 <lpc_variant> <target#> <cclk> [calc_checksum]
345 int lpc2000_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
347 lpc2000_flash_bank_t
*lpc2000_info
;
351 WARNING("incomplete flash_bank lpc2000 configuration");
352 return ERROR_FLASH_BANK_INVALID
;
355 lpc2000_info
= malloc(sizeof(lpc2000_flash_bank_t
));
356 bank
->driver_priv
= lpc2000_info
;
358 if (strcmp(args
[5], "lpc2000_v1") == 0)
360 lpc2000_info
->variant
= 1;
361 lpc2000_info
->cmd51_dst_boundary
= 512;
362 lpc2000_info
->cmd51_can_256b
= 0;
363 lpc2000_info
->cmd51_can_8192b
= 1;
365 else if (strcmp(args
[5], "lpc2000_v2") == 0)
367 lpc2000_info
->variant
= 2;
368 lpc2000_info
->cmd51_dst_boundary
= 256;
369 lpc2000_info
->cmd51_can_256b
= 1;
370 lpc2000_info
->cmd51_can_8192b
= 0;
374 ERROR("unknown LPC2000 variant");
376 return ERROR_FLASH_BANK_INVALID
;
379 lpc2000_info
->target
= get_target_by_num(strtoul(args
[6], NULL
, 0));
380 if (!lpc2000_info
->target
)
382 ERROR("no target '%s' configured", args
[6]);
385 lpc2000_info
->iap_working_area
= NULL
;
386 lpc2000_info
->cclk
= strtoul(args
[7], NULL
, 0);
387 lpc2000_info
->calc_checksum
= 0;
388 lpc2000_build_sector_list(bank
);
393 if (strcmp(args
[8], "calc_checksum") == 0)
394 lpc2000_info
->calc_checksum
= 1;
400 int lpc2000_erase(struct flash_bank_s
*bank
, int first
, int last
)
402 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
407 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
409 return ERROR_TARGET_NOT_HALTED
;
412 if ((first
< 0) || (last
< first
) || (last
>= bank
->num_sectors
))
414 return ERROR_FLASH_SECTOR_INVALID
;
417 param_table
[0] = first
;
418 param_table
[1] = last
;
419 param_table
[2] = lpc2000_info
->cclk
;
421 /* Prepare sectors */
422 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
425 case ERROR_FLASH_OPERATION_FAILED
:
426 return ERROR_FLASH_OPERATION_FAILED
;
427 case LPC2000_CMD_SUCCESS
:
429 case LPC2000_INVALID_SECTOR
:
430 return ERROR_FLASH_SECTOR_INVALID
;
433 WARNING("lpc2000 prepare sectors returned %i", status_code
);
434 return ERROR_FLASH_OPERATION_FAILED
;
438 status_code
= lpc2000_iap_call(bank
, 52, param_table
, result_table
);
441 case ERROR_FLASH_OPERATION_FAILED
:
442 return ERROR_FLASH_OPERATION_FAILED
;
443 case LPC2000_CMD_SUCCESS
:
445 case LPC2000_INVALID_SECTOR
:
446 return ERROR_FLASH_SECTOR_INVALID
;
449 WARNING("lpc2000 erase sectors returned %i", status_code
);
450 return ERROR_FLASH_OPERATION_FAILED
;
456 int lpc2000_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
458 /* can't protect/unprotect on the lpc2000 */
462 int lpc2000_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
464 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
465 target_t
*target
= lpc2000_info
->target
;
466 u32 dst_min_alignment
;
467 u32 bytes_remaining
= count
;
468 u32 bytes_written
= 0;
469 int first_sector
= 0;
475 working_area_t
*download_area
;
477 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
479 return ERROR_TARGET_NOT_HALTED
;
482 /* allocate a working area */
483 if (target_alloc_working_area(target
, 4096, &download_area
) != ERROR_OK
)
485 ERROR("no working area specified, can't write LPC2000 internal flash");
486 return ERROR_FLASH_OPERATION_FAILED
;
489 if (offset
+ count
> bank
->size
)
490 return ERROR_FLASH_DST_OUT_OF_BANK
;
492 if (lpc2000_info
->cmd51_can_256b
)
493 dst_min_alignment
= 256;
495 dst_min_alignment
= 512;
497 if (offset
% dst_min_alignment
)
499 WARNING("offset 0x%x breaks required alignment 0x%x", offset
, dst_min_alignment
);
500 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
503 for (i
= 0; i
< bank
->num_sectors
; i
++)
505 if (offset
>= bank
->sectors
[i
].offset
)
507 if (offset
+ CEIL(count
, dst_min_alignment
) * dst_min_alignment
> bank
->sectors
[i
].offset
)
511 DEBUG("first_sector: %i, last_sector: %i", first_sector
, last_sector
);
513 /* check if exception vectors should be flashed */
514 if ((offset
== 0) && (count
>= 0x20) && lpc2000_info
->calc_checksum
)
518 for (i
= 0; i
< 8; i
++)
520 DEBUG("0x%2.2x: 0x%8.8x", i
* 4, buf_get_u32(buffer
+ (i
* 4), 0, 32));
522 checksum
+= buf_get_u32(buffer
+ (i
* 4), 0, 32);
524 checksum
= 0 - checksum
;
525 DEBUG("checksum: 0x%8.8x", checksum
);
526 buf_set_u32(buffer
+ 0x14, 0, 32, checksum
);
529 while (bytes_remaining
> 0)
532 if (bytes_remaining
>= 4096)
533 thisrun_bytes
= 4096;
534 else if (bytes_remaining
>= 1024)
535 thisrun_bytes
= 1024;
536 else if ((bytes_remaining
>= 512) || (!lpc2000_info
->cmd51_can_256b
))
541 /* Prepare sectors */
542 param_table
[0] = first_sector
;
543 param_table
[1] = last_sector
;
544 status_code
= lpc2000_iap_call(bank
, 50, param_table
, result_table
);
547 case ERROR_FLASH_OPERATION_FAILED
:
548 return ERROR_FLASH_OPERATION_FAILED
;
549 case LPC2000_CMD_SUCCESS
:
551 case LPC2000_INVALID_SECTOR
:
552 return ERROR_FLASH_SECTOR_INVALID
;
555 WARNING("lpc2000 prepare sectors returned %i", status_code
);
556 return ERROR_FLASH_OPERATION_FAILED
;
559 if (bytes_remaining
>= thisrun_bytes
)
561 if (target_write_buffer(lpc2000_info
->target
, download_area
->address
, thisrun_bytes
, buffer
+ bytes_written
) != ERROR_OK
)
563 target_free_working_area(target
, download_area
);
564 return ERROR_FLASH_OPERATION_FAILED
;
569 u8
*last_buffer
= malloc(thisrun_bytes
);
571 memcpy(last_buffer
, buffer
+ bytes_written
, bytes_remaining
);
572 for (i
= bytes_remaining
; i
< thisrun_bytes
; i
++)
573 last_buffer
[i
] = 0xff;
574 target_write_buffer(lpc2000_info
->target
, download_area
->address
, thisrun_bytes
, last_buffer
);
578 DEBUG("writing 0x%x bytes to address 0x%x", thisrun_bytes
, bank
->base
+ offset
+ bytes_written
);
581 param_table
[0] = bank
->base
+ offset
+ bytes_written
;
582 param_table
[1] = download_area
->address
;
583 param_table
[2] = thisrun_bytes
;
584 param_table
[3] = lpc2000_info
->cclk
;
585 status_code
= lpc2000_iap_call(bank
, 51, param_table
, result_table
);
588 case ERROR_FLASH_OPERATION_FAILED
:
589 return ERROR_FLASH_OPERATION_FAILED
;
590 case LPC2000_CMD_SUCCESS
:
592 case LPC2000_INVALID_SECTOR
:
593 return ERROR_FLASH_SECTOR_INVALID
;
596 WARNING("lpc2000 returned %i", status_code
);
597 return ERROR_FLASH_OPERATION_FAILED
;
600 if (bytes_remaining
> thisrun_bytes
)
601 bytes_remaining
-= thisrun_bytes
;
604 bytes_written
+= thisrun_bytes
;
607 target_free_working_area(target
, download_area
);
612 int lpc2000_probe(struct flash_bank_s
*bank
)
614 /* we can't probe on an lpc2000
615 * if this is an lpc2xxx, it has the configured flash
620 int lpc2000_erase_check(struct flash_bank_s
*bank
)
622 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
624 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
626 return ERROR_TARGET_NOT_HALTED
;
629 return lpc2000_iap_blank_check(bank
, 0, bank
->num_sectors
- 1);
632 int lpc2000_protect_check(struct flash_bank_s
*bank
)
634 /* sectors are always protected */
638 int lpc2000_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
640 lpc2000_flash_bank_t
*lpc2000_info
= bank
->driver_priv
;
642 snprintf(buf
, buf_size
, "lpc2000 flash driver variant: %i, clk: %i", lpc2000_info
->variant
, lpc2000_info
->cclk
);
647 int lpc2000_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
653 lpc2000_flash_bank_t
*lpc2000_info
;
657 command_print(cmd_ctx
, "usage: lpc2000 part_id <num>");
661 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
664 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
668 lpc2000_info
= bank
->driver_priv
;
669 if (lpc2000_info
->target
->state
!= TARGET_HALTED
)
671 return ERROR_TARGET_NOT_HALTED
;
674 if ((status_code
= lpc2000_iap_call(bank
, 54, param_table
, result_table
)) != 0x0)
676 if (status_code
== ERROR_FLASH_OPERATION_FAILED
)
678 command_print(cmd_ctx
, "no sufficient working area specified, can't access LPC2000 IAP interface");
681 command_print(cmd_ctx
, "lpc2000 IAP returned status code %i", status_code
);
685 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)