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 ***************************************************************************/
24 #include "replacements.h"
31 #include "algorithm.h"
32 #include "binarybuffer.h"
38 str7x_mem_layout_t mem_layout
[] = {
39 {0x00000000, 0x02000, 0x01},
40 {0x00002000, 0x02000, 0x01},
41 {0x00004000, 0x02000, 0x01},
42 {0x00006000, 0x02000, 0x01},
43 {0x00008000, 0x08000, 0x01},
44 {0x00010000, 0x10000, 0x01},
45 {0x00020000, 0x10000, 0x01},
46 {0x00030000, 0x10000, 0x01},
47 {0x000C0000, 0x02000, 0x100},
48 {0x000C2000, 0x02000, 0x100},
52 int str7x_register_commands(struct command_context_s
*cmd_ctx
);
53 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
54 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
);
55 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
56 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
57 int str7x_probe(struct flash_bank_s
*bank
);
58 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
59 int str7x_protect_check(struct flash_bank_s
*bank
);
60 int str7x_erase_check(struct flash_bank_s
*bank
);
61 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
63 flash_driver_t str7x_flash
=
66 .register_commands
= str7x_register_commands
,
67 .flash_bank_command
= str7x_flash_bank_command
,
69 .protect
= str7x_protect
,
72 .erase_check
= str7x_erase_check
,
73 .protect_check
= str7x_protect_check
,
77 int str7x_register_commands(struct command_context_s
*cmd_ctx
)
83 int str7x_get_flash_adr(struct flash_bank_s
*bank
, u32 reg
)
85 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
86 return (str7x_info
->flash_base
|reg
);
89 int str7x_build_block_list(struct flash_bank_s
*bank
)
91 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
111 ERROR("BUG: unknown bank->size encountered");
115 if( str7x_info
->bank1
== 1 )
120 bank
->num_sectors
= num_sectors
;
121 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
123 for (i
= 0; i
< num_sectors
; i
++)
125 bank
->sectors
[i
].offset
= mem_layout
[i
].sector_start
;
126 bank
->sectors
[i
].size
= mem_layout
[i
].sector_size
;
127 bank
->sectors
[i
].is_erased
= -1;
128 bank
->sectors
[i
].is_protected
= 1;
134 /* flash bank str7x <base> <size> 0 0 <str71_variant> <target#>
136 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
138 str7x_flash_bank_t
*str7x_info
;
142 WARNING("incomplete flash_bank str7x configuration");
143 return ERROR_FLASH_BANK_INVALID
;
146 str7x_info
= malloc(sizeof(str7x_flash_bank_t
));
147 bank
->driver_priv
= str7x_info
;
149 if (strcmp(args
[5], "STR71x") == 0)
151 str7x_info
->bank1
= 1;
152 str7x_info
->flash_base
= 0x40000000;
154 else if (strcmp(args
[5], "STR73x") == 0)
156 str7x_info
->bank1
= 0;
157 str7x_info
->flash_base
= 0x80000000;
161 ERROR("unknown STR7x variant");
163 return ERROR_FLASH_BANK_INVALID
;
166 str7x_info
->target
= get_target_by_num(strtoul(args
[6], NULL
, 0));
167 if (!str7x_info
->target
)
169 ERROR("no target '%s' configured", args
[6]);
173 str7x_build_block_list(bank
);
175 str7x_info
->write_algorithm
= NULL
;
180 u32
str7x_status(struct flash_bank_s
*bank
)
182 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
183 target_t
*target
= str7x_info
->target
;
186 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), &retval
);
191 u32
str7x_result(struct flash_bank_s
*bank
)
193 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
194 target_t
*target
= str7x_info
->target
;
197 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), &retval
);
202 int str7x_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
204 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
205 target_t
*target
= str7x_info
->target
;
210 if ((first
< 0) || (last
> bank
->num_sectors
))
211 return ERROR_FLASH_SECTOR_INVALID
;
213 if (str7x_info
->target
->state
!= TARGET_HALTED
)
215 return ERROR_TARGET_NOT_HALTED
;
218 buffer
= malloc(256);
220 for (i
= first
; i
<= last
; i
++)
222 bank
->sectors
[i
].is_erased
= 1;
224 target
->type
->read_memory(target
, bank
->base
+ bank
->sectors
[i
].offset
, 4, 256/4, buffer
);
226 for (nBytes
= 0; nBytes
< 256; nBytes
++)
228 if (buffer
[nBytes
] != 0xFF)
230 bank
->sectors
[i
].is_erased
= 0;
241 int str7x_protect_check(struct flash_bank_s
*bank
)
243 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
244 target_t
*target
= str7x_info
->target
;
249 if (str7x_info
->target
->state
!= TARGET_HALTED
)
251 return ERROR_TARGET_NOT_HALTED
;
254 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVWPAR
), &retval
);
256 for (i
= 0; i
< bank
->num_sectors
; i
++)
258 if (retval
& (mem_layout
[i
].reg_offset
<< i
))
259 bank
->sectors
[i
].is_protected
= 0;
261 bank
->sectors
[i
].is_protected
= 1;
267 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
)
269 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
270 target_t
*target
= str7x_info
->target
;
277 if (str7x_info
->target
->state
!= TARGET_HALTED
)
279 return ERROR_TARGET_NOT_HALTED
;
284 for (i
= first
; i
<= last
; i
++)
285 erase_blocks
|= (mem_layout
[i
].reg_offset
<< i
);
287 /* clear FLASH_ER register */
288 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
291 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
294 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
296 cmd
= FLASH_SER
|FLASH_WMS
;
297 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
299 while (((retval
= str7x_status(bank
)) & (FLASH_BSYA1
|FLASH_BSYA2
))){
303 retval
= str7x_result(bank
);
305 if (retval
& FLASH_ERER
)
306 return ERROR_FLASH_SECTOR_NOT_ERASED
;
307 else if (retval
& FLASH_WPF
)
308 return ERROR_FLASH_OPERATION_FAILED
;
310 for (i
= first
; i
<= last
; i
++)
311 bank
->sectors
[i
].is_erased
= 1;
316 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
318 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
319 target_t
*target
= str7x_info
->target
;
325 if (str7x_info
->target
->state
!= TARGET_HALTED
)
327 return ERROR_TARGET_NOT_HALTED
;
330 protect_blocks
= 0xFFFFFFFF;
334 for (i
= first
; i
<= last
; i
++)
335 protect_blocks
&= ~(mem_layout
[i
].reg_offset
<< i
);
338 /* clear FLASH_ER register */
339 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
342 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
344 cmd
= str7x_get_flash_adr(bank
, FLASH_NVWPAR
);
345 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), cmd
);
347 cmd
= protect_blocks
;
348 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), cmd
);
350 cmd
= FLASH_SPR
|FLASH_WMS
;
351 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
353 while (((retval
= str7x_status(bank
)) & (FLASH_BSYA1
|FLASH_BSYA2
))){
357 retval
= str7x_result(bank
);
359 DEBUG("retval: 0x%8.8x", retval
);
361 if (retval
& FLASH_ERER
)
362 return ERROR_FLASH_SECTOR_NOT_ERASED
;
363 else if (retval
& FLASH_WPF
)
364 return ERROR_FLASH_OPERATION_FAILED
;
369 int str7x_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
371 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
372 target_t
*target
= str7x_info
->target
;
373 u32 buffer_size
= 8192;
374 working_area_t
*source
;
375 u32 address
= bank
->base
+ offset
;
376 reg_param_t reg_params
[5];
377 armv4_5_algorithm_t armv4_5_info
;
380 u32 str7x_flash_write_code
[] = {
382 0xe3a04201, /* mov r4, #0x10000000 */
383 0xe5824000, /* str r4, [r2, #0x0] */
384 0xe5821010, /* str r1, [r2, #0x10] */
385 0xe4904004, /* ldr r4, [r0], #4 */
386 0xe5824008, /* str r4, [r2, #0x8] */
387 0xe4904004, /* ldr r4, [r0], #4 */
388 0xe582400c, /* str r4, [r2, #0xc] */
389 0xe3a04209, /* mov r4, #0x90000000 */
390 0xe5824000, /* str r4, [r2, #0x0] */
392 0xe5924000, /* ldr r4, [r2, #0x0] */
393 0xe3140016, /* tst r4, #0x16 */
394 0x1afffffc, /* bne busy */
395 0xe5924014, /* ldr r4, [r2, #0x14] */
396 0xe31400ff, /* tst r4, #0xff */
397 0x03140c01, /* tsteq r4, #0x100 */
398 0x1a000002, /* bne exit */
399 0xe2811008, /* add r1, r1, #0x8 */
400 0xe2533001, /* subs r3, r3, #1 */
401 0x1affffec, /* bne write */
403 0xeafffffe, /* b exit */
406 u8 str7x_flash_write_code_buf
[80];
409 /* flash write code */
410 if (!str7x_info
->write_algorithm
)
412 if (target_alloc_working_area(target
, 4 * 20, &str7x_info
->write_algorithm
) != ERROR_OK
)
414 WARNING("no working area available, can't do block memory writes");
415 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
418 /* convert flash writing code into a buffer in target endianness */
419 for (i
= 0; i
< 20; i
++)
420 target_buffer_set_u32(target
, str7x_flash_write_code_buf
+ i
*4, str7x_flash_write_code
[i
]);
422 target_write_buffer(target
, str7x_info
->write_algorithm
->address
, 20 * 4, str7x_flash_write_code_buf
);
426 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
429 if (buffer_size
<= 256)
431 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
432 if (str7x_info
->write_algorithm
)
433 target_free_working_area(target
, str7x_info
->write_algorithm
);
435 WARNING("no large enough working area available, can't do block memory writes");
436 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
440 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
441 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
442 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
444 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
445 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
446 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
447 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
448 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
452 u32 thisrun_count
= (count
> (buffer_size
/ 8)) ? (buffer_size
/ 8) : count
;
454 target_write_buffer(target
, source
->address
, thisrun_count
* 8, buffer
);
456 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
457 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
458 buf_set_u32(reg_params
[2].value
, 0, 32, str7x_get_flash_adr(bank
, FLASH_CR0
));
459 buf_set_u32(reg_params
[3].value
, 0, 32, thisrun_count
);
461 if ((retval
= target
->type
->run_algorithm(target
, 0, NULL
, 5, reg_params
, str7x_info
->write_algorithm
->address
, str7x_info
->write_algorithm
->address
+ (19 * 4), 10000, &armv4_5_info
)) != ERROR_OK
)
463 ERROR("error executing str7x flash write algorithm");
464 return ERROR_FLASH_OPERATION_FAILED
;
467 if (buf_get_u32(reg_params
[4].value
, 0, 32) != 0x00)
469 return ERROR_FLASH_OPERATION_FAILED
;
472 buffer
+= thisrun_count
* 8;
473 address
+= thisrun_count
* 8;
474 count
-= thisrun_count
;
477 target_free_working_area(target
, source
);
479 destroy_reg_param(®_params
[0]);
480 destroy_reg_param(®_params
[1]);
481 destroy_reg_param(®_params
[2]);
482 destroy_reg_param(®_params
[3]);
483 destroy_reg_param(®_params
[4]);
488 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
490 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
491 target_t
*target
= str7x_info
->target
;
492 u32 dwords_remaining
= (count
/ 8);
493 u32 bytes_remaining
= (count
& 0x00000007);
494 u32 address
= bank
->base
+ offset
;
495 u32 bytes_written
= 0;
500 if (str7x_info
->target
->state
!= TARGET_HALTED
)
502 return ERROR_TARGET_NOT_HALTED
;
507 WARNING("offset 0x%x breaks required 8-byte alignment", offset
);
508 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
511 if (offset
+ count
> bank
->size
)
512 return ERROR_FLASH_DST_OUT_OF_BANK
;
514 /* clear FLASH_ER register */
515 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
517 /* multiple dwords (8-byte) to be programmed? */
518 if (dwords_remaining
> 0)
520 /* try using a block write */
521 if ((retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
)) != ERROR_OK
)
523 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
525 /* if block write failed (no sufficient working area),
526 * we use normal (slow) single dword accesses */
527 WARNING("couldn't use block writes, falling back to single memory accesses");
529 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
531 /* if an error occured, we examine the reason, and quit */
532 retval
= str7x_result(bank
);
534 ERROR("flash writing failed with error code: 0x%x", retval
);
535 return ERROR_FLASH_OPERATION_FAILED
;
540 buffer
+= dwords_remaining
* 8;
541 address
+= dwords_remaining
* 8;
542 dwords_remaining
= 0;
546 while (dwords_remaining
> 0)
550 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
553 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
556 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, buffer
+ bytes_written
);
560 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, buffer
+ bytes_written
);
563 /* start programming cycle */
564 cmd
= FLASH_DWPG
| FLASH_WMS
;
565 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
567 while (((retval
= str7x_status(bank
)) & (FLASH_BSYA1
| FLASH_BSYA2
)))
572 retval
= str7x_result(bank
);
574 if (retval
& FLASH_PGER
)
575 return ERROR_FLASH_OPERATION_FAILED
;
576 else if (retval
& FLASH_WPF
)
577 return ERROR_FLASH_OPERATION_FAILED
;
585 u8 last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
588 while(bytes_remaining
> 0)
590 last_dword
[i
++] = *(buffer
+ bytes_written
);
597 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
600 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
603 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, last_dword
);
607 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, last_dword
+ 4);
610 /* start programming cycle */
611 cmd
= FLASH_DWPG
| FLASH_WMS
;
612 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
614 while (((retval
= str7x_status(bank
)) & (FLASH_BSYA1
| FLASH_BSYA2
)))
619 retval
= str7x_result(bank
);
621 if (retval
& FLASH_PGER
)
622 return ERROR_FLASH_OPERATION_FAILED
;
623 else if (retval
& FLASH_WPF
)
624 return ERROR_FLASH_OPERATION_FAILED
;
630 int str7x_probe(struct flash_bank_s
*bank
)
635 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
640 int str7x_erase_check(struct flash_bank_s
*bank
)
642 return str7x_blank_check(bank
, 0, bank
->num_sectors
- 1);
645 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
647 snprintf(buf
, buf_size
, "str7x flash driver info" );
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)