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 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
22 ***************************************************************************/
27 #include "replacements.h"
35 #include "algorithm.h"
36 #include "binarybuffer.h"
42 static u32 bank1start
= 0x00080000;
44 int str9x_register_commands(struct command_context_s
*cmd_ctx
);
45 int str9x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
46 int str9x_erase(struct flash_bank_s
*bank
, int first
, int last
);
47 int str9x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
48 int str9x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
49 int str9x_probe(struct flash_bank_s
*bank
);
50 int str9x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
51 int str9x_protect_check(struct flash_bank_s
*bank
);
52 int str9x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
54 int str9x_handle_flash_config_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
56 flash_driver_t str9x_flash
=
59 .register_commands
= str9x_register_commands
,
60 .flash_bank_command
= str9x_flash_bank_command
,
62 .protect
= str9x_protect
,
65 .auto_probe
= str9x_probe
,
66 .erase_check
= default_flash_blank_check
,
67 .protect_check
= str9x_protect_check
,
71 int str9x_register_commands(struct command_context_s
*cmd_ctx
)
73 command_t
*str9x_cmd
= register_command(cmd_ctx
, NULL
, "str9x", NULL
, COMMAND_ANY
, NULL
);
75 register_command(cmd_ctx
, str9x_cmd
, "flash_config", str9x_handle_flash_config_command
, COMMAND_EXEC
,
76 "configure str9 flash controller");
81 int str9x_build_block_list(struct flash_bank_s
*bank
)
83 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
87 int b0_sectors
= 0, b1_sectors
= 0;
90 /* set if we have large flash str9 */
91 str9x_info
->variant
= 0;
92 str9x_info
->bank1
= 0;
103 bank1start
= 0x00100000;
104 str9x_info
->variant
= 1;
108 bank1start
= 0x00200000;
109 str9x_info
->variant
= 1;
113 str9x_info
->variant
= 1;
114 str9x_info
->bank1
= 1;
116 bank1start
= bank
->base
;
119 str9x_info
->bank1
= 1;
121 bank1start
= bank
->base
;
124 LOG_ERROR("BUG: unknown bank->size encountered");
128 num_sectors
= b0_sectors
+ b1_sectors
;
130 bank
->num_sectors
= num_sectors
;
131 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
132 str9x_info
->sector_bits
= malloc(sizeof(u32
) * num_sectors
);
136 for (i
= 0; i
< b0_sectors
; i
++)
138 bank
->sectors
[num_sectors
].offset
= offset
;
139 bank
->sectors
[num_sectors
].size
= 0x10000;
140 offset
+= bank
->sectors
[i
].size
;
141 bank
->sectors
[num_sectors
].is_erased
= -1;
142 bank
->sectors
[num_sectors
].is_protected
= 1;
143 str9x_info
->sector_bits
[num_sectors
++] = (1<<i
);
146 for (i
= 0; i
< b1_sectors
; i
++)
148 bank
->sectors
[num_sectors
].offset
= offset
;
149 bank
->sectors
[num_sectors
].size
= str9x_info
->variant
== 0 ? 0x2000 : 0x4000;
150 offset
+= bank
->sectors
[i
].size
;
151 bank
->sectors
[num_sectors
].is_erased
= -1;
152 bank
->sectors
[num_sectors
].is_protected
= 1;
153 if (str9x_info
->variant
)
154 str9x_info
->sector_bits
[num_sectors
++] = (1<<i
);
156 str9x_info
->sector_bits
[num_sectors
++] = (1<<(i
+8));
162 /* flash bank str9x <base> <size> 0 0 <target#>
164 int str9x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
166 str9x_flash_bank_t
*str9x_info
;
170 LOG_WARNING("incomplete flash_bank str9x configuration");
171 return ERROR_FLASH_BANK_INVALID
;
174 str9x_info
= malloc(sizeof(str9x_flash_bank_t
));
175 bank
->driver_priv
= str9x_info
;
177 str9x_build_block_list(bank
);
179 str9x_info
->write_algorithm
= NULL
;
184 int str9x_protect_check(struct flash_bank_s
*bank
)
186 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
187 target_t
*target
= bank
->target
;
193 if (bank
->target
->state
!= TARGET_HALTED
)
195 return ERROR_TARGET_NOT_HALTED
;
198 /* read level one protection */
200 if (str9x_info
->variant
)
202 if (str9x_info
->bank1
)
204 adr
= bank1start
+ 0x18;
205 target_write_u16(target
, adr
, 0x90);
206 target_read_u16(target
, adr
, (u16
*)&status
);
210 adr
= bank1start
+ 0x14;
211 target_write_u16(target
, adr
, 0x90);
212 target_read_u32(target
, adr
, &status
);
217 adr
= bank1start
+ 0x10;
218 target_write_u16(target
, adr
, 0x90);
219 target_read_u16(target
, adr
, (u16
*)&status
);
222 /* read array command */
223 target_write_u16(target
, adr
, 0xFF);
225 for (i
= 0; i
< bank
->num_sectors
; i
++)
227 if (status
& str9x_info
->sector_bits
[i
])
228 bank
->sectors
[i
].is_protected
= 1;
230 bank
->sectors
[i
].is_protected
= 0;
236 int str9x_erase(struct flash_bank_s
*bank
, int first
, int last
)
238 target_t
*target
= bank
->target
;
244 if (bank
->target
->state
!= TARGET_HALTED
)
246 return ERROR_TARGET_NOT_HALTED
;
249 /* Check if we erase whole bank */
250 if ((first
== 0) && (last
== (bank
->num_sectors
- 1)))
252 /* Optimize to run erase bank command instead of sector */
257 /* Erase sector command */
261 for (i
= first
; i
<= last
; i
++)
263 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
266 target_write_u16(target
, adr
, erase_cmd
);
267 target_write_u16(target
, adr
, 0xD0);
270 target_write_u16(target
, adr
, 0x70);
273 target_read_u8(target
, adr
, &status
);
279 /* clear status, also clear read array */
280 target_write_u16(target
, adr
, 0x50);
282 /* read array command */
283 target_write_u16(target
, adr
, 0xFF);
287 LOG_ERROR("error erasing flash bank, status: 0x%x", status
);
288 return ERROR_FLASH_OPERATION_FAILED
;
291 /* If we ran erase bank command, we are finished */
292 if (erase_cmd
== 0x80)
296 for (i
= first
; i
<= last
; i
++)
297 bank
->sectors
[i
].is_erased
= 1;
302 int str9x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
304 target_t
*target
= bank
->target
;
309 if (bank
->target
->state
!= TARGET_HALTED
)
311 return ERROR_TARGET_NOT_HALTED
;
314 for (i
= first
; i
<= last
; i
++)
316 /* Level One Protection */
318 adr
= bank
->base
+ bank
->sectors
[i
].offset
;
320 target_write_u16(target
, adr
, 0x60);
322 target_write_u16(target
, adr
, 0x01);
324 target_write_u16(target
, adr
, 0xD0);
327 target_read_u8(target
, adr
, &status
);
329 /* clear status, also clear read array */
330 target_write_u16(target
, adr
, 0x50);
332 /* read array command */
333 target_write_u16(target
, adr
, 0xFF);
339 int str9x_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
341 str9x_flash_bank_t
*str9x_info
= bank
->driver_priv
;
342 target_t
*target
= bank
->target
;
343 u32 buffer_size
= 8192;
344 working_area_t
*source
;
345 u32 address
= bank
->base
+ offset
;
346 reg_param_t reg_params
[4];
347 armv4_5_algorithm_t armv4_5_info
;
348 int retval
= ERROR_OK
;
350 u32 str9x_flash_write_code
[] = {
352 0xe3c14003, /* bic r4, r1, #3 */
353 0xe3a03040, /* mov r3, #0x40 */
354 0xe1c430b0, /* strh r3, [r4, #0] */
355 0xe0d030b2, /* ldrh r3, [r0], #2 */
356 0xe0c130b2, /* strh r3, [r1], #2 */
357 0xe3a03070, /* mov r3, #0x70 */
358 0xe1c430b0, /* strh r3, [r4, #0] */
360 0xe5d43000, /* ldrb r3, [r4, #0] */
361 0xe3130080, /* tst r3, #0x80 */
362 0x0afffffc, /* beq busy */
363 0xe3a05050, /* mov r5, #0x50 */
364 0xe1c450b0, /* strh r5, [r4, #0] */
365 0xe3a050ff, /* mov r5, #0xFF */
366 0xe1c450b0, /* strh r5, [r4, #0] */
367 0xe3130012, /* tst r3, #0x12 */
368 0x1a000001, /* bne exit */
369 0xe2522001, /* subs r2, r2, #1 */
370 0x1affffed, /* bne write */
372 0xeafffffe, /* b exit */
375 /* flash write code */
376 if (target_alloc_working_area(target
, 4 * 19, &str9x_info
->write_algorithm
) != ERROR_OK
)
378 LOG_WARNING("no working area available, can't do block memory writes");
379 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
382 target_write_buffer(target
, str9x_info
->write_algorithm
->address
, 19 * 4, (u8
*)str9x_flash_write_code
);
385 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
388 if (buffer_size
<= 256)
390 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
391 if (str9x_info
->write_algorithm
)
392 target_free_working_area(target
, str9x_info
->write_algorithm
);
394 LOG_WARNING("no large enough working area available, can't do block memory writes");
395 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
399 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
400 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
401 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
403 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
404 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
405 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
406 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
410 u32 thisrun_count
= (count
> (buffer_size
/ 2)) ? (buffer_size
/ 2) : count
;
412 target_write_buffer(target
, source
->address
, thisrun_count
* 2, buffer
);
414 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
415 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
416 buf_set_u32(reg_params
[2].value
, 0, 32, thisrun_count
);
418 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
)
420 LOG_ERROR("error executing str9x flash write algorithm");
421 retval
= ERROR_FLASH_OPERATION_FAILED
;
425 if (buf_get_u32(reg_params
[3].value
, 0, 32) != 0x80)
427 retval
= ERROR_FLASH_OPERATION_FAILED
;
431 buffer
+= thisrun_count
* 2;
432 address
+= thisrun_count
* 2;
433 count
-= thisrun_count
;
436 target_free_working_area(target
, source
);
437 target_free_working_area(target
, str9x_info
->write_algorithm
);
439 destroy_reg_param(®_params
[0]);
440 destroy_reg_param(®_params
[1]);
441 destroy_reg_param(®_params
[2]);
442 destroy_reg_param(®_params
[3]);
447 int str9x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
449 target_t
*target
= bank
->target
;
450 u32 words_remaining
= (count
/ 2);
451 u32 bytes_remaining
= (count
& 0x00000001);
452 u32 address
= bank
->base
+ offset
;
453 u32 bytes_written
= 0;
456 u32 check_address
= offset
;
460 if (bank
->target
->state
!= TARGET_HALTED
)
462 return ERROR_TARGET_NOT_HALTED
;
467 LOG_WARNING("offset 0x%x breaks required 2-byte alignment", offset
);
468 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
471 for (i
= 0; i
< bank
->num_sectors
; i
++)
473 u32 sec_start
= bank
->sectors
[i
].offset
;
474 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
476 /* check if destination falls within the current sector */
477 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
479 /* check if destination ends in the current sector */
480 if (offset
+ count
< sec_end
)
481 check_address
= offset
+ count
;
483 check_address
= sec_end
;
487 if (check_address
!= offset
+ count
)
488 return ERROR_FLASH_DST_OUT_OF_BANK
;
490 /* multiple half words (2-byte) to be programmed? */
491 if (words_remaining
> 0)
493 /* try using a block write */
494 if ((retval
= str9x_write_block(bank
, buffer
, offset
, words_remaining
)) != ERROR_OK
)
496 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
498 /* if block write failed (no sufficient working area),
499 * we use normal (slow) single dword accesses */
500 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
502 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
504 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
505 return ERROR_FLASH_OPERATION_FAILED
;
510 buffer
+= words_remaining
* 2;
511 address
+= words_remaining
* 2;
516 while (words_remaining
> 0)
518 bank_adr
= address
& ~0x03;
520 /* write data command */
521 target_write_u16(target
, bank_adr
, 0x40);
522 target
->type
->write_memory(target
, address
, 2, 1, buffer
+ bytes_written
);
524 /* get status command */
525 target_write_u16(target
, bank_adr
, 0x70);
528 target_read_u8(target
, bank_adr
, &status
);
534 /* clear status reg and read array */
535 target_write_u16(target
, bank_adr
, 0x50);
536 target_write_u16(target
, bank_adr
, 0xFF);
539 return ERROR_FLASH_OPERATION_FAILED
;
540 else if (status
& 0x02)
541 return ERROR_FLASH_OPERATION_FAILED
;
550 u8 last_halfword
[2] = {0xff, 0xff};
553 while(bytes_remaining
> 0)
555 last_halfword
[i
++] = *(buffer
+ bytes_written
);
560 bank_adr
= address
& ~0x03;
562 /* write data comamnd */
563 target_write_u16(target
, bank_adr
, 0x40);
564 target
->type
->write_memory(target
, address
, 2, 1, last_halfword
);
566 /* query status command */
567 target_write_u16(target
, bank_adr
, 0x70);
570 target_read_u8(target
, bank_adr
, &status
);
576 /* clear status reg and read array */
577 target_write_u16(target
, bank_adr
, 0x50);
578 target_write_u16(target
, bank_adr
, 0xFF);
581 return ERROR_FLASH_OPERATION_FAILED
;
582 else if (status
& 0x02)
583 return ERROR_FLASH_OPERATION_FAILED
;
589 int str9x_probe(struct flash_bank_s
*bank
)
594 int str9x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
599 int str9x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
601 snprintf(buf
, buf_size
, "str9x flash driver info" );
605 int str9x_handle_flash_config_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
607 str9x_flash_bank_t
*str9x_info
;
609 target_t
*target
= NULL
;
613 return ERROR_COMMAND_SYNTAX_ERROR
;
616 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
619 command_print(cmd_ctx
, "flash bank '#%s' is out of bounds", args
[0]);
623 str9x_info
= bank
->driver_priv
;
625 target
= bank
->target
;
627 if (bank
->target
->state
!= TARGET_HALTED
)
629 return ERROR_TARGET_NOT_HALTED
;
632 /* config flash controller */
633 target_write_u32(target
, FLASH_BBSR
, strtoul(args
[1], NULL
, 0));
634 target_write_u32(target
, FLASH_NBBSR
, strtoul(args
[2], NULL
, 0));
635 target_write_u32(target
, FLASH_BBADR
, (strtoul(args
[3], NULL
, 0) >> 2));
636 target_write_u32(target
, FLASH_NBBADR
, (strtoul(args
[4], NULL
, 0) >> 2));
638 /* set bit 18 instruction TCM order as per flash programming manual */
639 arm966e_write_cp15(target
, 62, 0x40000);
641 /* enable flash bank 1 */
642 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)