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 destroy_reg_param(®_params
[0]);
478 destroy_reg_param(®_params
[1]);
479 destroy_reg_param(®_params
[2]);
480 destroy_reg_param(®_params
[3]);
481 destroy_reg_param(®_params
[4]);
486 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
488 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
489 target_t
*target
= str7x_info
->target
;
490 u32 dwords_remaining
= (count
/ 8);
491 u32 bytes_remaining
= (count
& 0x00000007);
492 u32 address
= bank
->base
+ offset
;
493 u32 bytes_written
= 0;
498 if (str7x_info
->target
->state
!= TARGET_HALTED
)
500 return ERROR_TARGET_NOT_HALTED
;
505 WARNING("offset 0x%x breaks required 8-byte alignment", offset
);
506 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
509 if (offset
+ count
> bank
->size
)
510 return ERROR_FLASH_DST_OUT_OF_BANK
;
512 /* clear FLASH_ER register */
513 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
515 /* multiple dwords (8-byte) to be programmed? */
516 if (dwords_remaining
> 0)
518 /* try using a block write */
519 if ((retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
)) != ERROR_OK
)
521 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
523 /* if block write failed (no sufficient working area),
524 * we use normal (slow) single dword accesses */
525 WARNING("couldn't use block writes, falling back to single memory accesses");
527 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
529 /* if an error occured, we examine the reason, and quit */
530 retval
= str7x_result(bank
);
532 ERROR("flash writing failed with error code: 0x%x", retval
);
533 return ERROR_FLASH_OPERATION_FAILED
;
538 buffer
+= dwords_remaining
* 8;
539 address
+= dwords_remaining
* 8;
540 dwords_remaining
= 0;
544 while (dwords_remaining
> 0)
548 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
551 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
554 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, buffer
+ bytes_written
);
558 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, buffer
+ bytes_written
);
561 /* start programming cycle */
562 cmd
= FLASH_DWPG
| FLASH_WMS
;
563 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
565 while (((retval
= str7x_status(bank
)) & (FLASH_BSYA1
| FLASH_BSYA2
)))
570 retval
= str7x_result(bank
);
572 if (retval
& FLASH_PGER
)
573 return ERROR_FLASH_OPERATION_FAILED
;
574 else if (retval
& FLASH_WPF
)
575 return ERROR_FLASH_OPERATION_FAILED
;
583 u8 last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
586 while(bytes_remaining
> 0)
588 last_dword
[i
++] = *(buffer
+ bytes_written
);
595 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
598 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
601 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, last_dword
);
605 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, last_dword
+ 4);
608 /* start programming cycle */
609 cmd
= FLASH_DWPG
| FLASH_WMS
;
610 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
612 while (((retval
= str7x_status(bank
)) & (FLASH_BSYA1
| FLASH_BSYA2
)))
617 retval
= str7x_result(bank
);
619 if (retval
& FLASH_PGER
)
620 return ERROR_FLASH_OPERATION_FAILED
;
621 else if (retval
& FLASH_WPF
)
622 return ERROR_FLASH_OPERATION_FAILED
;
628 int str7x_probe(struct flash_bank_s
*bank
)
633 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
638 int str7x_erase_check(struct flash_bank_s
*bank
)
640 return str7x_blank_check(bank
, 0, bank
->num_sectors
- 1);
643 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
645 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)