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, 0x02},
41 {0x00004000, 0x02000, 0x04},
42 {0x00006000, 0x02000, 0x08},
43 {0x00008000, 0x08000, 0x10},
44 {0x00010000, 0x10000, 0x20},
45 {0x00020000, 0x10000, 0x40},
46 {0x00030000, 0x10000, 0x80},
47 {0x000C0000, 0x02000, 0x10000},
48 {0x000C2000, 0x02000, 0x20000},
51 int str7x_register_commands(struct command_context_s
*cmd_ctx
);
52 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
);
53 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
);
54 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
);
55 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
);
56 int str7x_probe(struct flash_bank_s
*bank
);
57 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
58 int str7x_protect_check(struct flash_bank_s
*bank
);
59 int str7x_erase_check(struct flash_bank_s
*bank
);
60 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
62 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
64 flash_driver_t str7x_flash
=
67 .register_commands
= str7x_register_commands
,
68 .flash_bank_command
= str7x_flash_bank_command
,
70 .protect
= str7x_protect
,
73 .auto_probe
= str7x_probe
,
74 .erase_check
= str7x_erase_check
,
75 .protect_check
= str7x_protect_check
,
79 int str7x_register_commands(struct command_context_s
*cmd_ctx
)
81 command_t
*str7x_cmd
= register_command(cmd_ctx
, NULL
, "str7x", NULL
, COMMAND_ANY
, NULL
);
83 register_command(cmd_ctx
, str7x_cmd
, "disable_jtag", str7x_handle_disable_jtag_command
, COMMAND_EXEC
,
84 "disable jtag access");
89 int str7x_get_flash_adr(struct flash_bank_s
*bank
, u32 reg
)
91 return (bank
->base
| reg
);
94 int str7x_build_block_list(struct flash_bank_s
*bank
)
96 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
99 int num_sectors
= 0, b0_sectors
= 0, b1_sectors
= 0;
116 ERROR("BUG: unknown bank->size encountered");
120 if( str7x_info
->bank1
== 1 )
125 num_sectors
= b0_sectors
+ b1_sectors
;
127 bank
->num_sectors
= num_sectors
;
128 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
129 str7x_info
->sector_bits
= malloc(sizeof(u32
) * num_sectors
);
130 str7x_info
->sector_bank
= malloc(sizeof(u32
) * num_sectors
);
134 for (i
= 0; i
< b0_sectors
; i
++)
136 bank
->sectors
[num_sectors
].offset
= mem_layout
[i
].sector_start
;
137 bank
->sectors
[num_sectors
].size
= mem_layout
[i
].sector_size
;
138 bank
->sectors
[num_sectors
].is_erased
= -1;
139 bank
->sectors
[num_sectors
].is_protected
= 1;
140 str7x_info
->sector_bank
[num_sectors
] = 0;
141 str7x_info
->sector_bits
[num_sectors
++] = mem_layout
[i
].sector_bit
;
146 for (i
= 8; i
< 10; i
++)
148 bank
->sectors
[num_sectors
].offset
= mem_layout
[i
].sector_start
;
149 bank
->sectors
[num_sectors
].size
= mem_layout
[i
].sector_size
;
150 bank
->sectors
[num_sectors
].is_erased
= -1;
151 bank
->sectors
[num_sectors
].is_protected
= 1;
152 str7x_info
->sector_bank
[num_sectors
] = 1;
153 str7x_info
->sector_bits
[num_sectors
++] = mem_layout
[i
].sector_bit
;
160 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
162 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
164 str7x_flash_bank_t
*str7x_info
;
168 WARNING("incomplete flash_bank str7x configuration");
169 return ERROR_FLASH_BANK_INVALID
;
172 str7x_info
= malloc(sizeof(str7x_flash_bank_t
));
173 bank
->driver_priv
= str7x_info
;
175 /* set default bits for str71x flash */
176 str7x_info
->bank1
= 1;
177 str7x_info
->busy_bits
= (FLASH_LOCK
|FLASH_BSYA1
|FLASH_BSYA0
);
178 str7x_info
->disable_bit
= (1<<1);
180 if (strcmp(args
[6], "STR71x") == 0)
182 if (bank
->base
!= 0x40000000)
184 WARNING("overriding flash base address for STR71x device with 0x40000000");
185 bank
->base
= 0x40000000;
188 else if (strcmp(args
[6], "STR73x") == 0)
190 str7x_info
->bank1
= 0;
191 str7x_info
->busy_bits
= (FLASH_LOCK
|FLASH_BSYA0
);
193 if (bank
->base
!= 0x80000000)
195 WARNING("overriding flash base address for STR73x device with 0x80000000");
196 bank
->base
= 0x80000000;
199 else if (strcmp(args
[6], "STR75x") == 0)
201 str7x_info
->disable_bit
= (1<<0);
203 if (bank
->base
!= 0x20000000)
205 WARNING("overriding flash base address for STR75x device with 0x20000000");
206 bank
->base
= 0x20000000;
211 ERROR("unknown STR7x variant: '%s'", args
[6]);
213 return ERROR_FLASH_BANK_INVALID
;
216 str7x_build_block_list(bank
);
218 str7x_info
->write_algorithm
= NULL
;
223 u32
str7x_status(struct flash_bank_s
*bank
)
225 target_t
*target
= bank
->target
;
228 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), &retval
);
233 u32
str7x_result(struct flash_bank_s
*bank
)
235 target_t
*target
= bank
->target
;
238 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), &retval
);
243 int str7x_blank_check(struct flash_bank_s
*bank
, int first
, int last
)
245 target_t
*target
= bank
->target
;
250 if ((first
< 0) || (last
> bank
->num_sectors
))
251 return ERROR_FLASH_SECTOR_INVALID
;
253 if (bank
->target
->state
!= TARGET_HALTED
)
255 return ERROR_TARGET_NOT_HALTED
;
258 buffer
= malloc(256);
260 for (i
= first
; i
<= last
; i
++)
262 bank
->sectors
[i
].is_erased
= 1;
264 target
->type
->read_memory(target
, bank
->base
+ bank
->sectors
[i
].offset
, 4, 256/4, buffer
);
266 for (nBytes
= 0; nBytes
< 256; nBytes
++)
268 if (buffer
[nBytes
] != 0xFF)
270 bank
->sectors
[i
].is_erased
= 0;
281 int str7x_protect_check(struct flash_bank_s
*bank
)
283 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
284 target_t
*target
= bank
->target
;
289 if (bank
->target
->state
!= TARGET_HALTED
)
291 return ERROR_TARGET_NOT_HALTED
;
294 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVWPAR
), &retval
);
296 for (i
= 0; i
< bank
->num_sectors
; i
++)
298 if (retval
& str7x_info
->sector_bits
[i
])
299 bank
->sectors
[i
].is_protected
= 0;
301 bank
->sectors
[i
].is_protected
= 1;
307 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
)
309 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
310 target_t
*target
= bank
->target
;
315 u32 b0_sectors
= 0, b1_sectors
= 0;
317 for (i
= first
; i
<= last
; i
++)
319 if (str7x_info
->sector_bank
[i
] == 0)
320 b0_sectors
|= str7x_info
->sector_bits
[i
];
321 else if (str7x_info
->sector_bank
[i
] == 1)
322 b1_sectors
|= str7x_info
->sector_bits
[i
];
324 ERROR("BUG: str7x_info->sector_bank[i] neither 0 nor 1 (%i)", str7x_info
->sector_bank
[i
]);
329 DEBUG("b0_sectors: 0x%x", b0_sectors
);
331 /* clear FLASH_ER register */
332 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
335 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
338 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
340 cmd
= FLASH_SER
|FLASH_WMS
;
341 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
343 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
347 retval
= str7x_result(bank
);
351 ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval
);
352 return ERROR_FLASH_OPERATION_FAILED
;
358 DEBUG("b1_sectors: 0x%x", b1_sectors
);
360 /* clear FLASH_ER register */
361 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
364 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
367 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
369 cmd
= FLASH_SER
|FLASH_WMS
;
370 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
372 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
376 retval
= str7x_result(bank
);
380 ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval
);
381 return ERROR_FLASH_OPERATION_FAILED
;
385 for (i
= first
; i
<= last
; i
++)
386 bank
->sectors
[i
].is_erased
= 1;
391 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
393 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
394 target_t
*target
= bank
->target
;
400 if (bank
->target
->state
!= TARGET_HALTED
)
402 return ERROR_TARGET_NOT_HALTED
;
405 protect_blocks
= 0xFFFFFFFF;
409 for (i
= first
; i
<= last
; i
++)
410 protect_blocks
&= ~(str7x_info
->sector_bits
[i
]);
413 /* clear FLASH_ER register */
414 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
417 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
419 cmd
= str7x_get_flash_adr(bank
, FLASH_NVWPAR
);
420 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), cmd
);
422 cmd
= protect_blocks
;
423 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), cmd
);
425 cmd
= FLASH_SPR
|FLASH_WMS
;
426 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
428 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
432 retval
= str7x_result(bank
);
434 DEBUG("retval: 0x%8.8x", retval
);
436 if (retval
& FLASH_ERER
)
437 return ERROR_FLASH_SECTOR_NOT_ERASED
;
438 else if (retval
& FLASH_WPF
)
439 return ERROR_FLASH_OPERATION_FAILED
;
444 int str7x_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
446 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
447 target_t
*target
= bank
->target
;
448 u32 buffer_size
= 8192;
449 working_area_t
*source
;
450 u32 address
= bank
->base
+ offset
;
451 reg_param_t reg_params
[6];
452 armv4_5_algorithm_t armv4_5_info
;
453 int retval
= ERROR_OK
;
455 u32 str7x_flash_write_code
[] = {
457 0xe3a04201, /* mov r4, #0x10000000 */
458 0xe5824000, /* str r4, [r2, #0x0] */
459 0xe5821010, /* str r1, [r2, #0x10] */
460 0xe4904004, /* ldr r4, [r0], #4 */
461 0xe5824008, /* str r4, [r2, #0x8] */
462 0xe4904004, /* ldr r4, [r0], #4 */
463 0xe582400c, /* str r4, [r2, #0xc] */
464 0xe3a04209, /* mov r4, #0x90000000 */
465 0xe5824000, /* str r4, [r2, #0x0] */
467 0xe5924000, /* ldr r4, [r2, #0x0] */
468 0xe1140005, /* tst r4, r5 */
469 0x1afffffc, /* bne busy */
470 0xe5924014, /* ldr r4, [r2, #0x14] */
471 0xe31400ff, /* tst r4, #0xff */
472 0x03140c01, /* tsteq r4, #0x100 */
473 0x1a000002, /* bne exit */
474 0xe2811008, /* add r1, r1, #0x8 */
475 0xe2533001, /* subs r3, r3, #1 */
476 0x1affffec, /* bne write */
478 0xeafffffe, /* b exit */
481 /* flash write code */
482 if (target_alloc_working_area(target
, 4 * 20, &str7x_info
->write_algorithm
) != ERROR_OK
)
484 WARNING("no working area available, can't do block memory writes");
485 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
488 target_write_buffer(target
, str7x_info
->write_algorithm
->address
, 20 * 4, (u8
*)str7x_flash_write_code
);
491 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
494 if (buffer_size
<= 256)
496 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
497 if (str7x_info
->write_algorithm
)
498 target_free_working_area(target
, str7x_info
->write_algorithm
);
500 WARNING("no large enough working area available, can't do block memory writes");
501 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
505 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
506 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
507 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
509 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
510 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
511 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
512 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
513 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
514 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
518 u32 thisrun_count
= (count
> (buffer_size
/ 8)) ? (buffer_size
/ 8) : count
;
520 target_write_buffer(target
, source
->address
, thisrun_count
* 8, buffer
);
522 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
523 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
524 buf_set_u32(reg_params
[2].value
, 0, 32, str7x_get_flash_adr(bank
, FLASH_CR0
));
525 buf_set_u32(reg_params
[3].value
, 0, 32, thisrun_count
);
526 buf_set_u32(reg_params
[5].value
, 0, 32, str7x_info
->busy_bits
);
528 if ((retval
= target
->type
->run_algorithm(target
, 0, NULL
, 6, reg_params
, str7x_info
->write_algorithm
->address
, str7x_info
->write_algorithm
->address
+ (19 * 4), 10000, &armv4_5_info
)) != ERROR_OK
)
530 ERROR("error executing str7x flash write algorithm");
534 if (buf_get_u32(reg_params
[4].value
, 0, 32) != 0x00)
536 retval
= ERROR_FLASH_OPERATION_FAILED
;
540 buffer
+= thisrun_count
* 8;
541 address
+= thisrun_count
* 8;
542 count
-= thisrun_count
;
545 target_free_working_area(target
, source
);
546 target_free_working_area(target
, str7x_info
->write_algorithm
);
548 destroy_reg_param(®_params
[0]);
549 destroy_reg_param(®_params
[1]);
550 destroy_reg_param(®_params
[2]);
551 destroy_reg_param(®_params
[3]);
552 destroy_reg_param(®_params
[4]);
553 destroy_reg_param(®_params
[5]);
558 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
560 target_t
*target
= bank
->target
;
561 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
562 u32 dwords_remaining
= (count
/ 8);
563 u32 bytes_remaining
= (count
& 0x00000007);
564 u32 address
= bank
->base
+ offset
;
565 u32 bytes_written
= 0;
568 u32 check_address
= offset
;
573 WARNING("offset 0x%x breaks required 8-byte alignment", offset
);
574 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
577 for (i
= 0; i
< bank
->num_sectors
; i
++)
579 u32 sec_start
= bank
->sectors
[i
].offset
;
580 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
582 /* check if destination falls within the current sector */
583 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
585 /* check if destination ends in the current sector */
586 if (offset
+ count
< sec_end
)
587 check_address
= offset
+ count
;
589 check_address
= sec_end
;
593 if (check_address
!= offset
+ count
)
594 return ERROR_FLASH_DST_OUT_OF_BANK
;
596 /* clear FLASH_ER register */
597 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
599 /* multiple dwords (8-byte) to be programmed? */
600 if (dwords_remaining
> 0)
602 /* try using a block write */
603 if ((retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
)) != ERROR_OK
)
605 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
607 /* if block write failed (no sufficient working area),
608 * we use normal (slow) single dword accesses */
609 WARNING("couldn't use block writes, falling back to single memory accesses");
611 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
613 /* if an error occured, we examine the reason, and quit */
614 retval
= str7x_result(bank
);
616 ERROR("flash writing failed with error code: 0x%x", retval
);
617 return ERROR_FLASH_OPERATION_FAILED
;
622 buffer
+= dwords_remaining
* 8;
623 address
+= dwords_remaining
* 8;
624 dwords_remaining
= 0;
628 while (dwords_remaining
> 0)
632 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
635 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
638 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, buffer
+ bytes_written
);
642 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, buffer
+ bytes_written
);
645 /* start programming cycle */
646 cmd
= FLASH_DWPG
| FLASH_WMS
;
647 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
649 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
654 retval
= str7x_result(bank
);
656 if (retval
& FLASH_PGER
)
657 return ERROR_FLASH_OPERATION_FAILED
;
658 else if (retval
& FLASH_WPF
)
659 return ERROR_FLASH_OPERATION_FAILED
;
667 u8 last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
670 while(bytes_remaining
> 0)
672 last_dword
[i
++] = *(buffer
+ bytes_written
);
679 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
682 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
685 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, last_dword
);
689 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, last_dword
+ 4);
692 /* start programming cycle */
693 cmd
= FLASH_DWPG
| FLASH_WMS
;
694 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
696 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
701 retval
= str7x_result(bank
);
703 if (retval
& FLASH_PGER
)
704 return ERROR_FLASH_OPERATION_FAILED
;
705 else if (retval
& FLASH_WPF
)
706 return ERROR_FLASH_OPERATION_FAILED
;
712 int str7x_probe(struct flash_bank_s
*bank
)
717 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
722 int str7x_erase_check(struct flash_bank_s
*bank
)
724 return str7x_blank_check(bank
, 0, bank
->num_sectors
- 1);
727 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
729 snprintf(buf
, buf_size
, "str7x flash driver info" );
733 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
736 target_t
*target
= NULL
;
737 str7x_flash_bank_t
*str7x_info
= NULL
;
741 u16 ProtectionLevel
= 0;
746 command_print(cmd_ctx
, "str7x disable_jtag <bank>");
750 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
753 command_print(cmd_ctx
, "str7x disable_jtag <bank> ok");
757 str7x_info
= bank
->driver_priv
;
759 target
= bank
->target
;
761 if (target
->state
!= TARGET_HALTED
)
763 return ERROR_TARGET_NOT_HALTED
;
766 /* first we get protection status */
767 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR0
), &retval
);
769 if (!(retval
& str7x_info
->disable_bit
))
774 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR1
), &retval
);
775 ProtectionRegs
= ~(retval
>> 16);
777 while (((ProtectionRegs
) != 0) && (ProtectionLevel
< 16))
779 ProtectionRegs
>>= 1;
783 if (ProtectionLevel
== 0)
785 flash_cmd
= FLASH_SPR
;
786 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
787 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFB8);
788 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 0xFFFFFFFD);
789 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
790 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
794 flash_cmd
= FLASH_SPR
;
795 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
796 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFBC);
797 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), ~(1<<(15+ProtectionLevel
)));
798 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
799 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
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)