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_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
);
61 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
);
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 .auto_probe
= str7x_probe
,
73 .erase_check
= default_flash_blank_check
,
74 .protect_check
= str7x_protect_check
,
78 int str7x_register_commands(struct command_context_s
*cmd_ctx
)
80 command_t
*str7x_cmd
= register_command(cmd_ctx
, NULL
, "str7x", NULL
, COMMAND_ANY
, NULL
);
82 register_command(cmd_ctx
, str7x_cmd
, "disable_jtag", str7x_handle_disable_jtag_command
, COMMAND_EXEC
,
83 "disable jtag access");
88 int str7x_get_flash_adr(struct flash_bank_s
*bank
, u32 reg
)
90 return (bank
->base
| reg
);
93 int str7x_build_block_list(struct flash_bank_s
*bank
)
95 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
98 int num_sectors
= 0, b0_sectors
= 0, b1_sectors
= 0;
115 LOG_ERROR("BUG: unknown bank->size encountered");
119 if( str7x_info
->bank1
== 1 )
124 num_sectors
= b0_sectors
+ b1_sectors
;
126 bank
->num_sectors
= num_sectors
;
127 bank
->sectors
= malloc(sizeof(flash_sector_t
) * num_sectors
);
128 str7x_info
->sector_bits
= malloc(sizeof(u32
) * num_sectors
);
129 str7x_info
->sector_bank
= malloc(sizeof(u32
) * num_sectors
);
133 for (i
= 0; i
< b0_sectors
; i
++)
135 bank
->sectors
[num_sectors
].offset
= mem_layout
[i
].sector_start
;
136 bank
->sectors
[num_sectors
].size
= mem_layout
[i
].sector_size
;
137 bank
->sectors
[num_sectors
].is_erased
= -1;
138 bank
->sectors
[num_sectors
].is_protected
= 1;
139 str7x_info
->sector_bank
[num_sectors
] = 0;
140 str7x_info
->sector_bits
[num_sectors
++] = mem_layout
[i
].sector_bit
;
145 for (i
= 8; i
< 10; i
++)
147 bank
->sectors
[num_sectors
].offset
= mem_layout
[i
].sector_start
;
148 bank
->sectors
[num_sectors
].size
= mem_layout
[i
].sector_size
;
149 bank
->sectors
[num_sectors
].is_erased
= -1;
150 bank
->sectors
[num_sectors
].is_protected
= 1;
151 str7x_info
->sector_bank
[num_sectors
] = 1;
152 str7x_info
->sector_bits
[num_sectors
++] = mem_layout
[i
].sector_bit
;
159 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
161 int str7x_flash_bank_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
, struct flash_bank_s
*bank
)
163 str7x_flash_bank_t
*str7x_info
;
167 LOG_WARNING("incomplete flash_bank str7x configuration");
168 return ERROR_FLASH_BANK_INVALID
;
171 str7x_info
= malloc(sizeof(str7x_flash_bank_t
));
172 bank
->driver_priv
= str7x_info
;
174 /* set default bits for str71x flash */
175 str7x_info
->bank1
= 1;
176 str7x_info
->busy_bits
= (FLASH_LOCK
|FLASH_BSYA1
|FLASH_BSYA0
);
177 str7x_info
->disable_bit
= (1<<1);
179 if (strcmp(args
[6], "STR71x") == 0)
181 if (bank
->base
!= 0x40000000)
183 LOG_WARNING("overriding flash base address for STR71x device with 0x40000000");
184 bank
->base
= 0x40000000;
187 else if (strcmp(args
[6], "STR73x") == 0)
189 str7x_info
->bank1
= 0;
190 str7x_info
->busy_bits
= (FLASH_LOCK
|FLASH_BSYA0
);
192 if (bank
->base
!= 0x80000000)
194 LOG_WARNING("overriding flash base address for STR73x device with 0x80000000");
195 bank
->base
= 0x80000000;
198 else if (strcmp(args
[6], "STR75x") == 0)
200 str7x_info
->disable_bit
= (1<<0);
202 if (bank
->base
!= 0x20000000)
204 LOG_WARNING("overriding flash base address for STR75x device with 0x20000000");
205 bank
->base
= 0x20000000;
210 LOG_ERROR("unknown STR7x variant: '%s'", args
[6]);
212 return ERROR_FLASH_BANK_INVALID
;
215 str7x_build_block_list(bank
);
217 str7x_info
->write_algorithm
= NULL
;
222 u32
str7x_status(struct flash_bank_s
*bank
)
224 target_t
*target
= bank
->target
;
227 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), &retval
);
232 u32
str7x_result(struct flash_bank_s
*bank
)
234 target_t
*target
= bank
->target
;
237 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), &retval
);
243 int str7x_protect_check(struct flash_bank_s
*bank
)
245 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
246 target_t
*target
= bank
->target
;
251 if (bank
->target
->state
!= TARGET_HALTED
)
253 return ERROR_TARGET_NOT_HALTED
;
256 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVWPAR
), &retval
);
258 for (i
= 0; i
< bank
->num_sectors
; i
++)
260 if (retval
& str7x_info
->sector_bits
[i
])
261 bank
->sectors
[i
].is_protected
= 0;
263 bank
->sectors
[i
].is_protected
= 1;
269 int str7x_erase(struct flash_bank_s
*bank
, int first
, int last
)
271 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
272 target_t
*target
= bank
->target
;
277 u32 b0_sectors
= 0, b1_sectors
= 0;
279 if (bank
->target
->state
!= TARGET_HALTED
)
281 return ERROR_TARGET_NOT_HALTED
;
284 for (i
= first
; i
<= last
; i
++)
286 if (str7x_info
->sector_bank
[i
] == 0)
287 b0_sectors
|= str7x_info
->sector_bits
[i
];
288 else if (str7x_info
->sector_bank
[i
] == 1)
289 b1_sectors
|= str7x_info
->sector_bits
[i
];
291 LOG_ERROR("BUG: str7x_info->sector_bank[i] neither 0 nor 1 (%i)", str7x_info
->sector_bank
[i
]);
296 LOG_DEBUG("b0_sectors: 0x%x", b0_sectors
);
298 /* clear FLASH_ER register */
299 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
302 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
305 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
307 cmd
= FLASH_SER
|FLASH_WMS
;
308 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
310 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
314 retval
= str7x_result(bank
);
318 LOG_ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval
);
319 return ERROR_FLASH_OPERATION_FAILED
;
325 LOG_DEBUG("b1_sectors: 0x%x", b1_sectors
);
327 /* clear FLASH_ER register */
328 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
331 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
334 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
336 cmd
= FLASH_SER
|FLASH_WMS
;
337 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
339 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
343 retval
= str7x_result(bank
);
347 LOG_ERROR("error erasing flash bank, FLASH_ER: 0x%x", retval
);
348 return ERROR_FLASH_OPERATION_FAILED
;
352 for (i
= first
; i
<= last
; i
++)
353 bank
->sectors
[i
].is_erased
= 1;
358 int str7x_protect(struct flash_bank_s
*bank
, int set
, int first
, int last
)
360 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
361 target_t
*target
= bank
->target
;
367 if (bank
->target
->state
!= TARGET_HALTED
)
369 return ERROR_TARGET_NOT_HALTED
;
372 protect_blocks
= 0xFFFFFFFF;
376 for (i
= first
; i
<= last
; i
++)
377 protect_blocks
&= ~(str7x_info
->sector_bits
[i
]);
380 /* clear FLASH_ER register */
381 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
384 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
386 cmd
= str7x_get_flash_adr(bank
, FLASH_NVWPAR
);
387 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), cmd
);
389 cmd
= protect_blocks
;
390 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), cmd
);
392 cmd
= FLASH_SPR
|FLASH_WMS
;
393 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
395 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
)){
399 retval
= str7x_result(bank
);
401 LOG_DEBUG("retval: 0x%8.8x", retval
);
403 if (retval
& FLASH_ERER
)
404 return ERROR_FLASH_SECTOR_NOT_ERASED
;
405 else if (retval
& FLASH_WPF
)
406 return ERROR_FLASH_OPERATION_FAILED
;
411 int str7x_write_block(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
413 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
414 target_t
*target
= bank
->target
;
415 u32 buffer_size
= 8192;
416 working_area_t
*source
;
417 u32 address
= bank
->base
+ offset
;
418 reg_param_t reg_params
[6];
419 armv4_5_algorithm_t armv4_5_info
;
420 int retval
= ERROR_OK
;
422 u32 str7x_flash_write_code
[] = {
424 0xe3a04201, /* mov r4, #0x10000000 */
425 0xe5824000, /* str r4, [r2, #0x0] */
426 0xe5821010, /* str r1, [r2, #0x10] */
427 0xe4904004, /* ldr r4, [r0], #4 */
428 0xe5824008, /* str r4, [r2, #0x8] */
429 0xe4904004, /* ldr r4, [r0], #4 */
430 0xe582400c, /* str r4, [r2, #0xc] */
431 0xe3a04209, /* mov r4, #0x90000000 */
432 0xe5824000, /* str r4, [r2, #0x0] */
434 0xe5924000, /* ldr r4, [r2, #0x0] */
435 0xe1140005, /* tst r4, r5 */
436 0x1afffffc, /* bne busy */
437 0xe5924014, /* ldr r4, [r2, #0x14] */
438 0xe31400ff, /* tst r4, #0xff */
439 0x03140c01, /* tsteq r4, #0x100 */
440 0x1a000002, /* bne exit */
441 0xe2811008, /* add r1, r1, #0x8 */
442 0xe2533001, /* subs r3, r3, #1 */
443 0x1affffec, /* bne write */
445 0xeafffffe, /* b exit */
448 /* flash write code */
449 if (target_alloc_working_area(target
, 4 * 20, &str7x_info
->write_algorithm
) != ERROR_OK
)
451 LOG_WARNING("no working area available, can't do block memory writes");
452 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
455 target_write_buffer(target
, str7x_info
->write_algorithm
->address
, 20 * 4, (u8
*)str7x_flash_write_code
);
458 while (target_alloc_working_area(target
, buffer_size
, &source
) != ERROR_OK
)
461 if (buffer_size
<= 256)
463 /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */
464 if (str7x_info
->write_algorithm
)
465 target_free_working_area(target
, str7x_info
->write_algorithm
);
467 LOG_WARNING("no large enough working area available, can't do block memory writes");
468 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
472 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
473 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
474 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
476 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
477 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
478 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
479 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
480 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
481 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
485 u32 thisrun_count
= (count
> (buffer_size
/ 8)) ? (buffer_size
/ 8) : count
;
487 target_write_buffer(target
, source
->address
, thisrun_count
* 8, buffer
);
489 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
490 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
491 buf_set_u32(reg_params
[2].value
, 0, 32, str7x_get_flash_adr(bank
, FLASH_CR0
));
492 buf_set_u32(reg_params
[3].value
, 0, 32, thisrun_count
);
493 buf_set_u32(reg_params
[5].value
, 0, 32, str7x_info
->busy_bits
);
495 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
)
497 LOG_ERROR("error executing str7x flash write algorithm");
501 if (buf_get_u32(reg_params
[4].value
, 0, 32) != 0x00)
503 retval
= ERROR_FLASH_OPERATION_FAILED
;
507 buffer
+= thisrun_count
* 8;
508 address
+= thisrun_count
* 8;
509 count
-= thisrun_count
;
512 target_free_working_area(target
, source
);
513 target_free_working_area(target
, str7x_info
->write_algorithm
);
515 destroy_reg_param(®_params
[0]);
516 destroy_reg_param(®_params
[1]);
517 destroy_reg_param(®_params
[2]);
518 destroy_reg_param(®_params
[3]);
519 destroy_reg_param(®_params
[4]);
520 destroy_reg_param(®_params
[5]);
525 int str7x_write(struct flash_bank_s
*bank
, u8
*buffer
, u32 offset
, u32 count
)
527 target_t
*target
= bank
->target
;
528 str7x_flash_bank_t
*str7x_info
= bank
->driver_priv
;
529 u32 dwords_remaining
= (count
/ 8);
530 u32 bytes_remaining
= (count
& 0x00000007);
531 u32 address
= bank
->base
+ offset
;
532 u32 bytes_written
= 0;
535 u32 check_address
= offset
;
538 if (bank
->target
->state
!= TARGET_HALTED
)
540 return ERROR_TARGET_NOT_HALTED
;
545 LOG_WARNING("offset 0x%x breaks required 8-byte alignment", offset
);
546 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
549 for (i
= 0; i
< bank
->num_sectors
; i
++)
551 u32 sec_start
= bank
->sectors
[i
].offset
;
552 u32 sec_end
= sec_start
+ bank
->sectors
[i
].size
;
554 /* check if destination falls within the current sector */
555 if ((check_address
>= sec_start
) && (check_address
< sec_end
))
557 /* check if destination ends in the current sector */
558 if (offset
+ count
< sec_end
)
559 check_address
= offset
+ count
;
561 check_address
= sec_end
;
565 if (check_address
!= offset
+ count
)
566 return ERROR_FLASH_DST_OUT_OF_BANK
;
568 /* clear FLASH_ER register */
569 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
571 /* multiple dwords (8-byte) to be programmed? */
572 if (dwords_remaining
> 0)
574 /* try using a block write */
575 if ((retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
)) != ERROR_OK
)
577 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
)
579 /* if block write failed (no sufficient working area),
580 * we use normal (slow) single dword accesses */
581 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
583 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
585 /* if an error occured, we examine the reason, and quit */
586 retval
= str7x_result(bank
);
588 LOG_ERROR("flash writing failed with error code: 0x%x", retval
);
589 return ERROR_FLASH_OPERATION_FAILED
;
594 buffer
+= dwords_remaining
* 8;
595 address
+= dwords_remaining
* 8;
596 dwords_remaining
= 0;
600 while (dwords_remaining
> 0)
604 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
607 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
610 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, buffer
+ bytes_written
);
614 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, buffer
+ bytes_written
);
617 /* start programming cycle */
618 cmd
= FLASH_DWPG
| FLASH_WMS
;
619 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
621 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
626 retval
= str7x_result(bank
);
628 if (retval
& FLASH_PGER
)
629 return ERROR_FLASH_OPERATION_FAILED
;
630 else if (retval
& FLASH_WPF
)
631 return ERROR_FLASH_OPERATION_FAILED
;
639 u8 last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
642 while(bytes_remaining
> 0)
644 last_dword
[i
++] = *(buffer
+ bytes_written
);
651 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
654 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
657 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 4, 1, last_dword
);
661 target
->type
->write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
), 4, 1, last_dword
+ 4);
664 /* start programming cycle */
665 cmd
= FLASH_DWPG
| FLASH_WMS
;
666 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
668 while (((retval
= str7x_status(bank
)) & str7x_info
->busy_bits
))
673 retval
= str7x_result(bank
);
675 if (retval
& FLASH_PGER
)
676 return ERROR_FLASH_OPERATION_FAILED
;
677 else if (retval
& FLASH_WPF
)
678 return ERROR_FLASH_OPERATION_FAILED
;
684 int str7x_probe(struct flash_bank_s
*bank
)
689 int str7x_handle_part_id_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
694 int str7x_info(struct flash_bank_s
*bank
, char *buf
, int buf_size
)
696 snprintf(buf
, buf_size
, "str7x flash driver info" );
700 int str7x_handle_disable_jtag_command(struct command_context_s
*cmd_ctx
, char *cmd
, char **args
, int argc
)
703 target_t
*target
= NULL
;
704 str7x_flash_bank_t
*str7x_info
= NULL
;
708 u16 ProtectionLevel
= 0;
713 command_print(cmd_ctx
, "str7x disable_jtag <bank>");
717 bank
= get_flash_bank_by_num(strtoul(args
[0], NULL
, 0));
720 command_print(cmd_ctx
, "str7x disable_jtag <bank> ok");
724 str7x_info
= bank
->driver_priv
;
726 target
= bank
->target
;
728 if (target
->state
!= TARGET_HALTED
)
730 return ERROR_TARGET_NOT_HALTED
;
733 /* first we get protection status */
734 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR0
), &retval
);
736 if (!(retval
& str7x_info
->disable_bit
))
741 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR1
), &retval
);
742 ProtectionRegs
= ~(retval
>> 16);
744 while (((ProtectionRegs
) != 0) && (ProtectionLevel
< 16))
746 ProtectionRegs
>>= 1;
750 if (ProtectionLevel
== 0)
752 flash_cmd
= FLASH_SPR
;
753 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
754 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFB8);
755 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 0xFFFFFFFD);
756 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
757 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
761 flash_cmd
= FLASH_SPR
;
762 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
763 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFBC);
764 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), ~(1<<(15+ProtectionLevel
)));
765 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
766 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)