1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
30 #include "replacements.h"
38 #include "algorithm.h"
39 #include "binarybuffer.h"
45 static u32 bank1start
= 0x00080000;
47 static int str9x_register_commands(struct command_context_s
*cmd_ctx
);
48 static int str9x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
49 static int str9x_erase(struct flash_bank_s
*bank
, int first
, int last
);
50 static int str9x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
51 static int str9x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
52 static int str9x_probe(struct flash_bank_s
*bank
);
53 //static int str9x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
54 static int str9x_protect_check(struct flash_bank_s
*bank
);
55 static int str9x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
57 static int str9x_handle_flash_config_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
59 flash_driver_t str9x_flash
=
62 .register_commands
= str9x_register_commands
,
63 .flash_bank_command
= str9x_flash_bank_command
,
65 .protect
= str9x_protect
,
68 .auto_probe
= str9x_probe
,
69 .erase_check
= default_flash_blank_check
,
70 .protect_check
= str9x_protect_check
,
74 static int str9x_register_commands(struct command_context_s
*cmd_ctx
)
76 command_t
*str9x_cmd
= register_command(cmd_ctx
, NULL
, "str9x", NULL
, COMMAND_ANY
, NULL
);
78 register_command(cmd_ctx
, str9x_cmd
, "flash_config", str9x_handle_flash_config_command
, COMMAND_EXEC
,
79 "configure str9 flash controller");
84 static int str9x_build_block_list(struct flash_bank_s
*bank
)
86 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
90 int b0_sectors
= 0, b1_sectors
= 0;
93 /* set if we have large flash str9 */
94 str9x_info
->variant
= 0;
95 str9x_info
->bank1
= 0;
106 bank1start
= 0x00100000;
107 str9x_info
->variant
= 1;
111 bank1start
= 0x00200000;
112 str9x_info
->variant
= 1;
116 str9x_info
->variant
= 1;
117 str9x_info
->bank1
= 1;
119 bank1start
= bank
->base
;
122 str9x_info
->bank1
= 1;
124 bank1start
= bank
->base
;
127 LOG_ERROR("BUG: unknown bank->size encountered");
131 num_sectors
= b0_sectors
+ b1_sectors
;
133 bank
->num_sectors
= num_sectors
;
134 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
135 str9x_info
->sector_bits
= malloc(sizeof(u32
) * num_sectors
);
139 for (i
= 0; i
< b0_sectors
; i
++)
141 bank
->sectors
[num_sectors
].offset
= offset
;
142 bank
->sectors
[num_sectors
].size
= 0x10000;
143 offset
+= bank
->sectors
[i
].size
;
144 bank
->sectors
[num_sectors
].is_erased
= -1;
145 bank
->sectors
[num_sectors
].is_protected
= 1;
146 str9x_info
->sector_bits
[num_sectors
++] = (1<<i
);
149 for (i
= 0; i
< b1_sectors
; i
++)
151 bank
->sectors
[num_sectors
].offset
= offset
;
152 bank
->sectors
[num_sectors
].size
= str9x_info
->variant
== 0 ? 0x2000 : 0x4000;
153 offset
+= bank
->sectors
[i
].size
;
154 bank
->sectors
[num_sectors
].is_erased
= -1;
155 bank
->sectors
[num_sectors
].is_protected
= 1;
156 if (str9x_info
->variant
)
157 str9x_info
->sector_bits
[num_sectors
++] = (1<<i
);
159 str9x_info
->sector_bits
[num_sectors
++] = (1<<(i
+8));
165 /* flash bank str9x <base> <size> 0 0 <target#>
167 static int str9x_flash_bank_command(struct command_context_s
*cmd_ctx
,
168 char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
170 str9x_flash_bank_t
*str9x_info
;
174 LOG_WARNING("incomplete flash_bank str9x configuration");
175 return ERROR_FLASH_BANK_INVALID
;
178 str9x_info
= malloc(sizeof(str9x_flash_bank_t
));
179 bank
->driver_priv
= str9x_info
;
181 str9x_build_block_list(bank
);
183 str9x_info
->write_algorithm
= NULL
;
188 static int str9x_protect_check(struct flash_bank_s
*bank
)
191 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
192 target_t
*target
= bank
->target
;
199 if (bank
->target
->state
!= TARGET_HALTED
)
201 LOG_ERROR("Target not halted");
202 return ERROR_TARGET_NOT_HALTED
;
205 /* read level one protection */
207 if (str9x_info
->variant
)
209 if (str9x_info
->bank1
)
211 adr
= bank1start
+ 0x18;
212 if ((retval
=target_write_u16(target
, adr
, 0x90))!=ERROR_OK
)
216 if ((retval
=target_read_u16(target
, adr
, &hstatus
))!=ERROR_OK
)
224 adr
= bank1start
+ 0x14;
225 if ((retval
=target_write_u16(target
, adr
, 0x90))!=ERROR_OK
)
229 if ((retval
=target_read_u32(target
, adr
, &status
))!=ERROR_OK
)
237 adr
= bank1start
+ 0x10;
238 if ((retval
=target_write_u16(target
, adr
, 0x90))!=ERROR_OK
)
242 if ((retval
=target_read_u16(target
, adr
, &hstatus
))!=ERROR_OK
)
249 /* read array command */
250 if ((retval
=target_write_u16(target
, adr
, 0xFF))!=ERROR_OK
)
255 for (i
= 0; i
< bank
->num_sectors
; i
++)
257 if (status
& str9x_info
->sector_bits
[i
])
258 bank
->sectors
[i
].is_protected
= 1;
260 bank
->sectors
[i
].is_protected
= 0;
266 static int str9x_erase(struct flash_bank_s
*bank
, int first
, int last
)
268 target_t
*target
= bank
->target
;
274 if (bank
->target
->state
!= TARGET_HALTED
)
276 LOG_ERROR("Target not halted");
277 return ERROR_TARGET_NOT_HALTED
;
280 /* Check if we erase whole bank */
281 if ((first
== 0) && (last
== (bank
->num_sectors
- 1)))
283 /* Optimize to run erase bank command instead of sector */
288 /* Erase sector command */
292 for (i
= first
; i
<= last
; i
++)
295 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
298 if ((retval
=target_write_u16(target
, adr
, erase_cmd
))!=ERROR_OK
)
302 if ((retval
=target_write_u16(target
, adr
, 0xD0))!=ERROR_OK
)
308 if ((retval
=target_write_u16(target
, adr
, 0x70))!=ERROR_OK
)
314 for (timeout
=0; timeout
<1000; timeout
++) {
315 if ((retval
=target_read_u8(target
, adr
, &status
))!=ERROR_OK
)
325 LOG_ERROR("erase timed out");
329 /* clear status, also clear read array */
330 if ((retval
=target_write_u16(target
, adr
, 0x50))!=ERROR_OK
)
335 /* read array command */
336 if ((retval
=target_write_u16(target
, adr
, 0xFF))!=ERROR_OK
)
343 LOG_ERROR("error erasing flash bank, status: 0x%x", status
);
344 return ERROR_FLASH_OPERATION_FAILED
;
347 /* If we ran erase bank command, we are finished */
348 if (erase_cmd
== 0x80)
352 for (i
= first
; i
<= last
; i
++)
353 bank
->sectors
[i
].is_erased
= 1;
358 static int str9x_protect(struct flash_bank_s
*bank
,
359 int set
, int first
, int last
)
361 target_t
*target
= bank
->target
;
366 if (bank
->target
->state
!= TARGET_HALTED
)
368 LOG_ERROR("Target not halted");
369 return ERROR_TARGET_NOT_HALTED
;
372 for (i
= first
; i
<= last
; i
++)
374 /* Level One Protection */
376 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
378 target_write_u16(target
, adr
, 0x60);
380 target_write_u16(target
, adr
, 0x01);
382 target_write_u16(target
, adr
, 0xD0);
385 target_read_u8(target
, adr
, &status
);
387 /* clear status, also clear read array */
388 target_write_u16(target
, adr
, 0x50);
390 /* read array command */
391 target_write_u16(target
, adr
, 0xFF);
397 static int str9x_write_block(struct flash_bank_s
*bank
,
398 u8
*buffer
, u32 offset
, u32 count
)
400 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
401 target_t
*target
= bank
->target
;
402 u32 buffer_size
= 8192;
403 working_area_t
*source
;
404 u32 address
= bank
->base
+ offset
;
405 reg_param_t reg_params
[4];
406 armv4_5_algorithm_t armv4_5_info
;
407 int retval
= ERROR_OK
;
409 u32 str9x_flash_write_code
[] = {
411 0xe3c14003, /* bic r4, r1, #3 */
412 0xe3a03040, /* mov r3, #0x40 */
413 0xe1c430b0, /* strh r3, [r4, #0] */
414 0xe0d030b2, /* ldrh r3, [r0], #2 */
415 0xe0c130b2, /* strh r3, [r1], #2 */
416 0xe3a03070, /* mov r3, #0x70 */
417 0xe1c430b0, /* strh r3, [r4, #0] */
419 0xe5d43000, /* ldrb r3, [r4, #0] */
420 0xe3130080, /* tst r3, #0x80 */
421 0x0afffffc, /* beq busy */
422 0xe3a05050, /* mov r5, #0x50 */
423 0xe1c450b0, /* strh r5, [r4, #0] */
424 0xe3a050ff, /* mov r5, #0xFF */
425 0xe1c450b0, /* strh r5, [r4, #0] */
426 0xe3130012, /* tst r3, #0x12 */
427 0x1a000001, /* bne exit */
428 0xe2522001, /* subs r2, r2, #1 */
429 0x1affffed, /* bne write */
431 0xeafffffe, /* b exit */
434 /* flash write code */
435 if (target_alloc_working_area(target
, 4 * 19, &str9x_info
->write_algorithm
) != ERROR_OK
)
437 LOG_WARNING("no working area available, can't do block memory writes");
438 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
441 target_write_buffer(target
, str9x_info
->write_algorithm
->address
, 19 * 4, (u8
*)str9x_flash_write_code
);
444 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
447 if (buffer_size
<= 256)
449 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
450 if (str9x_info
->write_algorithm
)
451 target_free_working_area(target
, str9x_info
->write_algorithm
);
453 LOG_WARNING("no large enough working area available, can't do block memory writes");
454 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
458 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
459 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
460 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
462 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
463 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
464 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
465 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
469 u32 thisrun_count
= (count
> (buffer_size
/ 2)) ? (buffer_size
/ 2) : count
;
471 target_write_buffer(target
, source
->address
, thisrun_count
* 2, buffer
);
473 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
474 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
475 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
477 if ((retval
= target
->type
->run_algorithm(target
, 0, NULL
, 4, reg_params
, str9x_info
->write_algorithm
->address
, str9x_info
->write_algorithm
->address
+ (18 * 4), 10000, &armv4_5_info
)) != ERROR_OK
)
479 LOG_ERROR("error executing str9x flash write algorithm");
480 retval
= ERROR_FLASH_OPERATION_FAILED
;
484 if (buf_get_u32(reg_params
[3].value
, 0, 32) != 0x80)
486 retval
= ERROR_FLASH_OPERATION_FAILED
;
490 buffer
+= thisrun_count
* 2;
491 address
+= thisrun_count
* 2;
492 count
-= thisrun_count
;
495 target_free_working_area(target
, source
);
496 target_free_working_area(target
, str9x_info
->write_algorithm
);
498 destroy_reg_param(®_params
[0]);
499 destroy_reg_param(®_params
[1]);
500 destroy_reg_param(®_params
[2]);
501 destroy_reg_param(®_params
[3]);
506 static int str9x_write(struct flash_bank_s
*bank
,
507 u8
*buffer
, u32 offset
, u32 count
)
509 target_t
*target
= bank
->target
;
510 u32 words_remaining
= (count
/ 2);
511 u32 bytes_remaining
= (count
& 0x00000001);
512 u32 address
= bank
->base
+ offset
;
513 u32 bytes_written
= 0;
516 u32 check_address
= offset
;
520 if (bank
->target
->state
!= TARGET_HALTED
)
522 LOG_ERROR("Target not halted");
523 return ERROR_TARGET_NOT_HALTED
;
528 LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset
);
529 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
532 for (i
= 0; i
< bank
->num_sectors
; i
++)
534 u32 sec_start
= bank
->sectors
[i
].offset
;
535 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
537 /* check if destination falls within the current sector */
538 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
540 /* check if destination ends in the current sector */
541 if (offset
+ count
< sec_end
)
542 check_address
= offset
+ count
;
544 check_address
= sec_end
;
548 if (check_address
!= offset
+ count
)
549 return ERROR_FLASH_DST_OUT_OF_BANK
;
551 /* multiple half words (2-byte) to be programmed? */
552 if (words_remaining
> 0)
554 /* try using a block write */
555 if ((retval
= str9x_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
557 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
559 /* if block write failed (no sufficient working area),
560 * we use normal (slow) single dword accesses */
561 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
563 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
565 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
566 return ERROR_FLASH_OPERATION_FAILED
;
571 buffer
+= words_remaining
* 2;
572 address
+= words_remaining
* 2;
577 while (words_remaining
> 0)
579 bank_adr
= address
& ~0x03;
581 /* write data command */
582 target_write_u16(target
, bank_adr
, 0x40);
583 target
->type
->write_memory(target
, address
, 2, 1, buffer
+ bytes_written
);
585 /* get status command */
586 target_write_u16(target
, bank_adr
, 0x70);
589 for (timeout
=0; timeout
<1000; timeout
++)
591 target_read_u8(target
, bank_adr
, &status
);
598 LOG_ERROR("write timed out");
602 /* clear status reg and read array */
603 target_write_u16(target
, bank_adr
, 0x50);
604 target_write_u16(target
, bank_adr
, 0xFF);
607 return ERROR_FLASH_OPERATION_FAILED
;
608 else if (status
& 0x02)
609 return ERROR_FLASH_OPERATION_FAILED
;
618 u8 last_halfword
[2] = {0xff, 0xff};
621 while(bytes_remaining
> 0)
623 last_halfword
[i
++] = *(buffer
+ bytes_written
);
628 bank_adr
= address
& ~0x03;
630 /* write data comamnd */
631 target_write_u16(target
, bank_adr
, 0x40);
632 target
->type
->write_memory(target
, address
, 2, 1, last_halfword
);
634 /* query status command */
635 target_write_u16(target
, bank_adr
, 0x70);
638 for (timeout
=0; timeout
<1000; timeout
++)
640 target_read_u8(target
, bank_adr
, &status
);
647 LOG_ERROR("write timed out");
651 /* clear status reg and read array */
652 target_write_u16(target
, bank_adr
, 0x50);
653 target_write_u16(target
, bank_adr
, 0xFF);
656 return ERROR_FLASH_OPERATION_FAILED
;
657 else if (status
& 0x02)
658 return ERROR_FLASH_OPERATION_FAILED
;
664 static int str9x_probe(struct flash_bank_s
*bank
)
670 static int str9x_handle_part_id_command(struct command_context_s
*cmd_ctx
,
671 char *cmd
, char **args
, int argc
)
677 static int str9x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
679 snprintf(buf
, buf_size
, "str9x flash driver info" );
683 static int str9x_handle_flash_config_command(struct command_context_s
*cmd_ctx
,
684 char *cmd
, char **args
, int argc
)
686 str9x_flash_bank_t
*str9x_info
;
688 target_t
*target
= NULL
;
692 return ERROR_COMMAND_SYNTAX_ERROR
;
695 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
698 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
702 str9x_info
= bank
->driver_priv
;
704 target
= bank
->target
;
706 if (bank
->target
->state
!= TARGET_HALTED
)
708 LOG_ERROR("Target not halted");
709 return ERROR_TARGET_NOT_HALTED
;
712 /* config flash controller */
713 target_write_u32(target
, FLASH_BBSR
, strtoul(args
[1], NULL
, 0));
714 target_write_u32(target
, FLASH_NBBSR
, strtoul(args
[2], NULL
, 0));
715 target_write_u32(target
, FLASH_BBADR
, (strtoul(args
[3], NULL
, 0) >> 2));
716 target_write_u32(target
, FLASH_NBBADR
, (strtoul(args
[4], NULL
, 0) >> 2));
718 /* set bit 18 instruction TCM order as per flash programming manual */
719 arm966e_write_cp15(target
, 62, 0x40000);
721 /* enable flash bank 1 */
722 target_write_u32(target
, FLASH_CR
, 0x18);
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)