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
;
198 if (bank
->target
->state
!= TARGET_HALTED
)
200 LOG_ERROR("Target not halted");
201 return ERROR_TARGET_NOT_HALTED
;
204 /* read level one protection */
206 if (str9x_info
->variant
)
208 if (str9x_info
->bank1
)
210 adr
= bank1start
+ 0x18;
211 if ((retval
=target_write_u16(target
, adr
, 0x90))!=ERROR_OK
)
215 if ((retval
=target_read_u16(target
, adr
, (u16
*)&status
))!=ERROR_OK
)
222 adr
= bank1start
+ 0x14;
223 if ((retval
=target_write_u16(target
, adr
, 0x90))!=ERROR_OK
)
227 if ((retval
=target_read_u32(target
, adr
, &status
))!=ERROR_OK
)
235 adr
= bank1start
+ 0x10;
236 if ((retval
=target_write_u16(target
, adr
, 0x90))!=ERROR_OK
)
240 if ((retval
=target_read_u16(target
, adr
, (u16
*)&status
))!=ERROR_OK
)
246 /* read array command */
247 if ((retval
=target_write_u16(target
, adr
, 0xFF))!=ERROR_OK
)
252 for (i
= 0; i
< bank
->num_sectors
; i
++)
254 if (status
& str9x_info
->sector_bits
[i
])
255 bank
->sectors
[i
].is_protected
= 1;
257 bank
->sectors
[i
].is_protected
= 0;
263 static int str9x_erase(struct flash_bank_s
*bank
, int first
, int last
)
265 target_t
*target
= bank
->target
;
271 if (bank
->target
->state
!= TARGET_HALTED
)
273 LOG_ERROR("Target not halted");
274 return ERROR_TARGET_NOT_HALTED
;
277 /* Check if we erase whole bank */
278 if ((first
== 0) && (last
== (bank
->num_sectors
- 1)))
280 /* Optimize to run erase bank command instead of sector */
285 /* Erase sector command */
289 for (i
= first
; i
<= last
; i
++)
292 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
295 if ((retval
=target_write_u16(target
, adr
, erase_cmd
))!=ERROR_OK
)
299 if ((retval
=target_write_u16(target
, adr
, 0xD0))!=ERROR_OK
)
305 if ((retval
=target_write_u16(target
, adr
, 0x70))!=ERROR_OK
)
311 for (timeout
=0; timeout
<1000; timeout
++) {
312 if ((retval
=target_read_u8(target
, adr
, &status
))!=ERROR_OK
)
322 LOG_ERROR("erase timed out");
326 /* clear status, also clear read array */
327 if ((retval
=target_write_u16(target
, adr
, 0x50))!=ERROR_OK
)
332 /* read array command */
333 if ((retval
=target_write_u16(target
, adr
, 0xFF))!=ERROR_OK
)
340 LOG_ERROR("error erasing flash bank, status: 0x%x", status
);
341 return ERROR_FLASH_OPERATION_FAILED
;
344 /* If we ran erase bank command, we are finished */
345 if (erase_cmd
== 0x80)
349 for (i
= first
; i
<= last
; i
++)
350 bank
->sectors
[i
].is_erased
= 1;
355 static int str9x_protect(struct flash_bank_s
*bank
,
356 int set
, int first
, int last
)
358 target_t
*target
= bank
->target
;
363 if (bank
->target
->state
!= TARGET_HALTED
)
365 LOG_ERROR("Target not halted");
366 return ERROR_TARGET_NOT_HALTED
;
369 for (i
= first
; i
<= last
; i
++)
371 /* Level One Protection */
373 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
375 target_write_u16(target
, adr
, 0x60);
377 target_write_u16(target
, adr
, 0x01);
379 target_write_u16(target
, adr
, 0xD0);
382 target_read_u8(target
, adr
, &status
);
384 /* clear status, also clear read array */
385 target_write_u16(target
, adr
, 0x50);
387 /* read array command */
388 target_write_u16(target
, adr
, 0xFF);
394 static int str9x_write_block(struct flash_bank_s
*bank
,
395 u8
*buffer
, u32 offset
, u32 count
)
397 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
398 target_t
*target
= bank
->target
;
399 u32 buffer_size
= 8192;
400 working_area_t
*source
;
401 u32 address
= bank
->base
+ offset
;
402 reg_param_t reg_params
[4];
403 armv4_5_algorithm_t armv4_5_info
;
404 int retval
= ERROR_OK
;
406 u32 str9x_flash_write_code
[] = {
408 0xe3c14003, /* bic r4, r1, #3 */
409 0xe3a03040, /* mov r3, #0x40 */
410 0xe1c430b0, /* strh r3, [r4, #0] */
411 0xe0d030b2, /* ldrh r3, [r0], #2 */
412 0xe0c130b2, /* strh r3, [r1], #2 */
413 0xe3a03070, /* mov r3, #0x70 */
414 0xe1c430b0, /* strh r3, [r4, #0] */
416 0xe5d43000, /* ldrb r3, [r4, #0] */
417 0xe3130080, /* tst r3, #0x80 */
418 0x0afffffc, /* beq busy */
419 0xe3a05050, /* mov r5, #0x50 */
420 0xe1c450b0, /* strh r5, [r4, #0] */
421 0xe3a050ff, /* mov r5, #0xFF */
422 0xe1c450b0, /* strh r5, [r4, #0] */
423 0xe3130012, /* tst r3, #0x12 */
424 0x1a000001, /* bne exit */
425 0xe2522001, /* subs r2, r2, #1 */
426 0x1affffed, /* bne write */
428 0xeafffffe, /* b exit */
431 /* flash write code */
432 if (target_alloc_working_area(target
, 4 * 19, &str9x_info
->write_algorithm
) != ERROR_OK
)
434 LOG_WARNING("no working area available, can't do block memory writes");
435 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
438 target_write_buffer(target
, str9x_info
->write_algorithm
->address
, 19 * 4, (u8
*)str9x_flash_write_code
);
441 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
444 if (buffer_size
<= 256)
446 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
447 if (str9x_info
->write_algorithm
)
448 target_free_working_area(target
, str9x_info
->write_algorithm
);
450 LOG_WARNING("no large enough working area available, can't do block memory writes");
451 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
455 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
456 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
457 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
459 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
460 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
461 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
462 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
466 u32 thisrun_count
= (count
> (buffer_size
/ 2)) ? (buffer_size
/ 2) : count
;
468 target_write_buffer(target
, source
->address
, thisrun_count
* 2, buffer
);
470 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
471 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
472 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
474 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
)
476 LOG_ERROR("error executing str9x flash write algorithm");
477 retval
= ERROR_FLASH_OPERATION_FAILED
;
481 if (buf_get_u32(reg_params
[3].value
, 0, 32) != 0x80)
483 retval
= ERROR_FLASH_OPERATION_FAILED
;
487 buffer
+= thisrun_count
* 2;
488 address
+= thisrun_count
* 2;
489 count
-= thisrun_count
;
492 target_free_working_area(target
, source
);
493 target_free_working_area(target
, str9x_info
->write_algorithm
);
495 destroy_reg_param(®_params
[0]);
496 destroy_reg_param(®_params
[1]);
497 destroy_reg_param(®_params
[2]);
498 destroy_reg_param(®_params
[3]);
503 static int str9x_write(struct flash_bank_s
*bank
,
504 u8
*buffer
, u32 offset
, u32 count
)
506 target_t
*target
= bank
->target
;
507 u32 words_remaining
= (count
/ 2);
508 u32 bytes_remaining
= (count
& 0x00000001);
509 u32 address
= bank
->base
+ offset
;
510 u32 bytes_written
= 0;
513 u32 check_address
= offset
;
517 if (bank
->target
->state
!= TARGET_HALTED
)
519 LOG_ERROR("Target not halted");
520 return ERROR_TARGET_NOT_HALTED
;
525 LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset
);
526 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
529 for (i
= 0; i
< bank
->num_sectors
; i
++)
531 u32 sec_start
= bank
->sectors
[i
].offset
;
532 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
534 /* check if destination falls within the current sector */
535 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
537 /* check if destination ends in the current sector */
538 if (offset
+ count
< sec_end
)
539 check_address
= offset
+ count
;
541 check_address
= sec_end
;
545 if (check_address
!= offset
+ count
)
546 return ERROR_FLASH_DST_OUT_OF_BANK
;
548 /* multiple half words (2-byte) to be programmed? */
549 if (words_remaining
> 0)
551 /* try using a block write */
552 if ((retval
= str9x_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
554 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
556 /* if block write failed (no sufficient working area),
557 * we use normal (slow) single dword accesses */
558 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
560 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
562 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
563 return ERROR_FLASH_OPERATION_FAILED
;
568 buffer
+= words_remaining
* 2;
569 address
+= words_remaining
* 2;
574 while (words_remaining
> 0)
576 bank_adr
= address
& ~0x03;
578 /* write data command */
579 target_write_u16(target
, bank_adr
, 0x40);
580 target
->type
->write_memory(target
, address
, 2, 1, buffer
+ bytes_written
);
582 /* get status command */
583 target_write_u16(target
, bank_adr
, 0x70);
586 for (timeout
=0; timeout
<1000; timeout
++)
588 target_read_u8(target
, bank_adr
, &status
);
595 LOG_ERROR("write timed out");
599 /* clear status reg and read array */
600 target_write_u16(target
, bank_adr
, 0x50);
601 target_write_u16(target
, bank_adr
, 0xFF);
604 return ERROR_FLASH_OPERATION_FAILED
;
605 else if (status
& 0x02)
606 return ERROR_FLASH_OPERATION_FAILED
;
615 u8 last_halfword
[2] = {0xff, 0xff};
618 while(bytes_remaining
> 0)
620 last_halfword
[i
++] = *(buffer
+ bytes_written
);
625 bank_adr
= address
& ~0x03;
627 /* write data comamnd */
628 target_write_u16(target
, bank_adr
, 0x40);
629 target
->type
->write_memory(target
, address
, 2, 1, last_halfword
);
631 /* query status command */
632 target_write_u16(target
, bank_adr
, 0x70);
635 for (timeout
=0; timeout
<1000; timeout
++)
637 target_read_u8(target
, bank_adr
, &status
);
644 LOG_ERROR("write timed out");
648 /* clear status reg and read array */
649 target_write_u16(target
, bank_adr
, 0x50);
650 target_write_u16(target
, bank_adr
, 0xFF);
653 return ERROR_FLASH_OPERATION_FAILED
;
654 else if (status
& 0x02)
655 return ERROR_FLASH_OPERATION_FAILED
;
661 static int str9x_probe(struct flash_bank_s
*bank
)
667 static int str9x_handle_part_id_command(struct command_context_s
*cmd_ctx
,
668 char *cmd
, char **args
, int argc
)
674 static int str9x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
676 snprintf(buf
, buf_size
, "str9x flash driver info" );
680 static int str9x_handle_flash_config_command(struct command_context_s
*cmd_ctx
,
681 char *cmd
, char **args
, int argc
)
683 str9x_flash_bank_t
*str9x_info
;
685 target_t
*target
= NULL
;
689 return ERROR_COMMAND_SYNTAX_ERROR
;
692 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
695 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
699 str9x_info
= bank
->driver_priv
;
701 target
= bank
->target
;
703 if (bank
->target
->state
!= TARGET_HALTED
)
705 LOG_ERROR("Target not halted");
706 return ERROR_TARGET_NOT_HALTED
;
709 /* config flash controller */
710 target_write_u32(target
, FLASH_BBSR
, strtoul(args
[1], NULL
, 0));
711 target_write_u32(target
, FLASH_NBBSR
, strtoul(args
[2], NULL
, 0));
712 target_write_u32(target
, FLASH_BBADR
, (strtoul(args
[3], NULL
, 0) >> 2));
713 target_write_u32(target
, FLASH_NBBADR
, (strtoul(args
[4], NULL
, 0) >> 2));
715 /* set bit 18 instruction TCM order as per flash programming manual */
716 arm966e_write_cp15(target
, 62, 0x40000);
718 /* enable flash bank 1 */
719 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)