1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
7 * Copyright (C) 2008 by Spencer Oliver *
8 * spen@spen-soft.co.uk *
10 * Copyright (C) 2010 Øyvind Harboe *
11 * oyvind.harboe@zylin.com *
12 ***************************************************************************/
19 #include <target/arm.h>
20 #include <helper/binarybuffer.h>
21 #include <target/algorithm.h>
25 #define FLASH_CR0 0x00000000
26 #define FLASH_CR1 0x00000004
27 #define FLASH_DR0 0x00000008
28 #define FLASH_DR1 0x0000000C
29 #define FLASH_AR 0x00000010
30 #define FLASH_ER 0x00000014
31 #define FLASH_NVWPAR 0x0000DFB0
32 #define FLASH_NVAPR0 0x0000DFB8
33 #define FLASH_NVAPR1 0x0000DFBC
35 /* FLASH_CR0 register bits */
37 #define FLASH_WMS 0x80000000
38 #define FLASH_SUSP 0x40000000
39 #define FLASH_WPG 0x20000000
40 #define FLASH_DWPG 0x10000000
41 #define FLASH_SER 0x08000000
42 #define FLASH_SPR 0x01000000
43 #define FLASH_BER 0x04000000
44 #define FLASH_MER 0x02000000
45 #define FLASH_LOCK 0x00000010
46 #define FLASH_BSYA1 0x00000004
47 #define FLASH_BSYA0 0x00000002
49 /* FLASH_CR1 register bits */
51 #define FLASH_B1S 0x02000000
52 #define FLASH_B0S 0x01000000
53 #define FLASH_B1F1 0x00020000
54 #define FLASH_B1F0 0x00010000
55 #define FLASH_B0F7 0x00000080
56 #define FLASH_B0F6 0x00000040
57 #define FLASH_B0F5 0x00000020
58 #define FLASH_B0F4 0x00000010
59 #define FLASH_B0F3 0x00000008
60 #define FLASH_B0F2 0x00000004
61 #define FLASH_B0F1 0x00000002
62 #define FLASH_B0F0 0x00000001
64 /* FLASH_ER register bits */
66 #define FLASH_WPF 0x00000100
67 #define FLASH_RESER 0x00000080
68 #define FLASH_SEQER 0x00000040
69 #define FLASH_10ER 0x00000008
70 #define FLASH_PGER 0x00000004
71 #define FLASH_ERER 0x00000002
72 #define FLASH_ERR 0x00000001
75 struct str7x_flash_bank
{
76 uint32_t *sector_bits
;
79 uint32_t register_base
;
82 struct str7x_mem_layout
{
83 uint32_t sector_start
;
88 enum str7x_status_codes
{
89 STR7X_CMD_SUCCESS
= 0,
90 STR7X_INVALID_COMMAND
= 1,
91 STR7X_SRC_ADDR_ERROR
= 2,
92 STR7X_DST_ADDR_ERROR
= 3,
93 STR7X_SRC_ADDR_NOT_MAPPED
= 4,
94 STR7X_DST_ADDR_NOT_MAPPED
= 5,
95 STR7X_COUNT_ERROR
= 6,
96 STR7X_INVALID_SECTOR
= 7,
97 STR7X_SECTOR_NOT_BLANK
= 8,
98 STR7X_SECTOR_NOT_PREPARED
= 9,
99 STR7X_COMPARE_ERROR
= 10,
103 static const struct str7x_mem_layout mem_layout_str7bank0
[] = {
104 {0x00000000, 0x02000, 0x01},
105 {0x00002000, 0x02000, 0x02},
106 {0x00004000, 0x02000, 0x04},
107 {0x00006000, 0x02000, 0x08},
108 {0x00008000, 0x08000, 0x10},
109 {0x00010000, 0x10000, 0x20},
110 {0x00020000, 0x10000, 0x40},
111 {0x00030000, 0x10000, 0x80}
114 static const struct str7x_mem_layout mem_layout_str7bank1
[] = {
115 {0x00000000, 0x02000, 0x10000},
116 {0x00002000, 0x02000, 0x20000}
119 static int str7x_get_flash_adr(struct flash_bank
*bank
, uint32_t reg
)
121 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
122 return str7x_info
->register_base
| reg
;
125 static int str7x_build_block_list(struct flash_bank
*bank
)
127 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
130 unsigned int num_sectors
;
131 int b0_sectors
= 0, b1_sectors
= 0;
133 switch (bank
->size
) {
147 LOG_ERROR("BUG: unknown bank->size encountered");
151 num_sectors
= b0_sectors
+ b1_sectors
;
153 bank
->num_sectors
= num_sectors
;
154 bank
->sectors
= malloc(sizeof(struct flash_sector
) * num_sectors
);
155 str7x_info
->sector_bits
= malloc(sizeof(uint32_t) * num_sectors
);
159 for (i
= 0; i
< b0_sectors
; i
++) {
160 bank
->sectors
[num_sectors
].offset
= mem_layout_str7bank0
[i
].sector_start
;
161 bank
->sectors
[num_sectors
].size
= mem_layout_str7bank0
[i
].sector_size
;
162 bank
->sectors
[num_sectors
].is_erased
= -1;
163 /* the reset_init handler marks all the sectors unprotected,
164 * matching hardware after reset; keep the driver in sync
166 bank
->sectors
[num_sectors
].is_protected
= 0;
167 str7x_info
->sector_bits
[num_sectors
++] = mem_layout_str7bank0
[i
].sector_bit
;
170 for (i
= 0; i
< b1_sectors
; i
++) {
171 bank
->sectors
[num_sectors
].offset
= mem_layout_str7bank1
[i
].sector_start
;
172 bank
->sectors
[num_sectors
].size
= mem_layout_str7bank1
[i
].sector_size
;
173 bank
->sectors
[num_sectors
].is_erased
= -1;
174 /* the reset_init handler marks all the sectors unprotected,
175 * matching hardware after reset; keep the driver in sync
177 bank
->sectors
[num_sectors
].is_protected
= 0;
178 str7x_info
->sector_bits
[num_sectors
++] = mem_layout_str7bank1
[i
].sector_bit
;
184 /* flash bank str7x <base> <size> 0 0 <target#> <str71_variant>
186 FLASH_BANK_COMMAND_HANDLER(str7x_flash_bank_command
)
188 struct str7x_flash_bank
*str7x_info
;
191 return ERROR_COMMAND_SYNTAX_ERROR
;
193 str7x_info
= malloc(sizeof(struct str7x_flash_bank
));
194 bank
->driver_priv
= str7x_info
;
196 /* set default bits for str71x flash */
197 str7x_info
->busy_bits
= (FLASH_LOCK
| FLASH_BSYA1
| FLASH_BSYA0
);
198 str7x_info
->disable_bit
= (1 << 1);
200 if (strcmp(CMD_ARGV
[6], "STR71x") == 0)
201 str7x_info
->register_base
= 0x40100000;
202 else if (strcmp(CMD_ARGV
[6], "STR73x") == 0) {
203 str7x_info
->register_base
= 0x80100000;
204 str7x_info
->busy_bits
= (FLASH_LOCK
| FLASH_BSYA0
);
205 } else if (strcmp(CMD_ARGV
[6], "STR75x") == 0) {
206 str7x_info
->register_base
= 0x20100000;
207 str7x_info
->disable_bit
= (1 << 0);
209 LOG_ERROR("unknown STR7x variant: '%s'", CMD_ARGV
[6]);
211 return ERROR_FLASH_BANK_INVALID
;
214 str7x_build_block_list(bank
);
219 /* wait for flash to become idle or report errors.
221 FIX!!! what's the maximum timeout??? The documentation doesn't
222 state any maximum time.... by inspection it seems > 1000ms is to be
225 10000ms is long enough that it should cover anything, yet not
226 quite be equivalent to an infinite loop.
229 static int str7x_waitbusy(struct flash_bank
*bank
)
233 struct target
*target
= bank
->target
;
234 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
236 for (i
= 0 ; i
< 10000; i
++) {
238 err
= target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), &retval
);
242 if ((retval
& str7x_info
->busy_bits
) == 0)
247 LOG_ERROR("Timed out waiting for str7x flash");
252 static int str7x_result(struct flash_bank
*bank
)
254 struct target
*target
= bank
->target
;
255 uint32_t flash_flags
;
258 retval
= target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), &flash_flags
);
259 if (retval
!= ERROR_OK
)
262 if (flash_flags
& FLASH_WPF
) {
263 LOG_ERROR("str7x hw write protection set");
266 if (flash_flags
& FLASH_RESER
) {
267 LOG_ERROR("str7x suspended program erase not resumed");
270 if (flash_flags
& FLASH_10ER
) {
271 LOG_ERROR("str7x trying to set bit to 1 when it is already 0");
274 if (flash_flags
& FLASH_PGER
) {
275 LOG_ERROR("str7x program error");
278 if (flash_flags
& FLASH_ERER
) {
279 LOG_ERROR("str7x erase error");
282 if (retval
== ERROR_OK
) {
283 if (flash_flags
& FLASH_ERR
) {
284 /* this should always be set if one of the others are set... */
285 LOG_ERROR("str7x write operation failed / bad setup");
293 static int str7x_protect_check(struct flash_bank
*bank
)
295 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
296 struct target
*target
= bank
->target
;
298 uint32_t flash_flags
;
300 if (bank
->target
->state
!= TARGET_HALTED
) {
301 LOG_ERROR("Target not halted");
302 return ERROR_TARGET_NOT_HALTED
;
306 retval
= target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVWPAR
), &flash_flags
);
307 if (retval
!= ERROR_OK
)
310 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
311 if (flash_flags
& str7x_info
->sector_bits
[i
])
312 bank
->sectors
[i
].is_protected
= 0;
314 bank
->sectors
[i
].is_protected
= 1;
320 static int str7x_erase(struct flash_bank
*bank
, unsigned int first
,
323 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
324 struct target
*target
= bank
->target
;
327 uint32_t sectors
= 0;
330 if (bank
->target
->state
!= TARGET_HALTED
) {
331 LOG_ERROR("Target not halted");
332 return ERROR_TARGET_NOT_HALTED
;
335 for (unsigned int i
= first
; i
<= last
; i
++)
336 sectors
|= str7x_info
->sector_bits
[i
];
338 LOG_DEBUG("sectors: 0x%" PRIx32
"", sectors
);
340 /* clear FLASH_ER register */
341 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
346 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
351 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR1
), cmd
);
355 cmd
= FLASH_SER
| FLASH_WMS
;
356 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
360 err
= str7x_waitbusy(bank
);
364 err
= str7x_result(bank
);
371 static int str7x_protect(struct flash_bank
*bank
, int set
, unsigned int first
,
374 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
375 struct target
*target
= bank
->target
;
377 uint32_t protect_blocks
;
379 if (bank
->target
->state
!= TARGET_HALTED
) {
380 LOG_ERROR("Target not halted");
381 return ERROR_TARGET_NOT_HALTED
;
384 protect_blocks
= 0xFFFFFFFF;
387 for (unsigned int i
= first
; i
<= last
; i
++)
388 protect_blocks
&= ~(str7x_info
->sector_bits
[i
]);
391 /* clear FLASH_ER register */
393 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
398 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
402 cmd
= str7x_get_flash_adr(bank
, FLASH_NVWPAR
);
403 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), cmd
);
407 cmd
= protect_blocks
;
408 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), cmd
);
412 cmd
= FLASH_SPR
| FLASH_WMS
;
413 err
= target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
417 err
= str7x_waitbusy(bank
);
421 err
= str7x_result(bank
);
428 static int str7x_write_block(struct flash_bank
*bank
, const uint8_t *buffer
,
429 uint32_t offset
, uint32_t count
)
431 struct str7x_flash_bank
*str7x_info
= bank
->driver_priv
;
432 struct target
*target
= bank
->target
;
433 uint32_t buffer_size
= 32768;
434 struct working_area
*write_algorithm
;
435 struct working_area
*source
;
436 uint32_t address
= bank
->base
+ offset
;
437 struct reg_param reg_params
[6];
438 struct arm_algorithm arm_algo
;
439 int retval
= ERROR_OK
;
441 /* see contrib/loaders/flash/str7x.s for src */
443 static const uint32_t str7x_flash_write_code
[] = {
445 0xe3a04201, /* mov r4, #0x10000000 */
446 0xe5824000, /* str r4, [r2, #0x0] */
447 0xe5821010, /* str r1, [r2, #0x10] */
448 0xe4904004, /* ldr r4, [r0], #4 */
449 0xe5824008, /* str r4, [r2, #0x8] */
450 0xe4904004, /* ldr r4, [r0], #4 */
451 0xe582400c, /* str r4, [r2, #0xc] */
452 0xe3a04209, /* mov r4, #0x90000000 */
453 0xe5824000, /* str r4, [r2, #0x0] */
455 0xe5924000, /* ldr r4, [r2, #0x0] */
456 0xe1140005, /* tst r4, r5 */
457 0x1afffffc, /* bne busy */
458 0xe5924014, /* ldr r4, [r2, #0x14] */
459 0xe31400ff, /* tst r4, #0xff */
460 0x03140c01, /* tsteq r4, #0x100 */
461 0x1a000002, /* bne exit */
462 0xe2811008, /* add r1, r1, #0x8 */
463 0xe2533001, /* subs r3, r3, #1 */
464 0x1affffec, /* bne write */
466 0xeafffffe, /* b exit */
469 /* flash write code */
470 if (target_alloc_working_area_try(target
, sizeof(str7x_flash_write_code
),
471 &write_algorithm
) != ERROR_OK
) {
472 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
475 uint8_t code
[sizeof(str7x_flash_write_code
)];
476 target_buffer_set_u32_array(target
, code
, ARRAY_SIZE(str7x_flash_write_code
),
477 str7x_flash_write_code
);
478 target_write_buffer(target
, write_algorithm
->address
, sizeof(code
), code
);
481 while (target_alloc_working_area_try(target
, buffer_size
, &source
) != ERROR_OK
) {
483 if (buffer_size
<= 256) {
484 /* we already allocated the writing code, but failed to get a
485 * buffer, free the algorithm */
486 target_free_working_area(target
, write_algorithm
);
488 LOG_WARNING("no large enough working area available, can't do block memory writes");
489 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
493 arm_algo
.common_magic
= ARM_COMMON_MAGIC
;
494 arm_algo
.core_mode
= ARM_MODE_SVC
;
495 arm_algo
.core_state
= ARM_STATE_ARM
;
497 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
498 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
499 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
500 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
501 init_reg_param(®_params
[4], "r4", 32, PARAM_IN
);
502 init_reg_param(®_params
[5], "r5", 32, PARAM_OUT
);
505 uint32_t thisrun_count
= (count
> (buffer_size
/ 8)) ? (buffer_size
/ 8) : count
;
507 target_write_buffer(target
, source
->address
, thisrun_count
* 8, buffer
);
509 buf_set_u32(reg_params
[0].value
, 0, 32, source
->address
);
510 buf_set_u32(reg_params
[1].value
, 0, 32, address
);
511 buf_set_u32(reg_params
[2].value
, 0, 32, str7x_get_flash_adr(bank
, FLASH_CR0
));
512 buf_set_u32(reg_params
[3].value
, 0, 32, thisrun_count
);
513 buf_set_u32(reg_params
[5].value
, 0, 32, str7x_info
->busy_bits
);
515 retval
= target_run_algorithm(target
, 0, NULL
, 6, reg_params
,
516 write_algorithm
->address
,
517 write_algorithm
->address
+ (sizeof(str7x_flash_write_code
) - 4),
519 if (retval
!= ERROR_OK
)
522 if (buf_get_u32(reg_params
[4].value
, 0, 32) != 0x00) {
523 retval
= str7x_result(bank
);
527 buffer
+= thisrun_count
* 8;
528 address
+= thisrun_count
* 8;
529 count
-= thisrun_count
;
532 target_free_working_area(target
, source
);
533 target_free_working_area(target
, write_algorithm
);
535 destroy_reg_param(®_params
[0]);
536 destroy_reg_param(®_params
[1]);
537 destroy_reg_param(®_params
[2]);
538 destroy_reg_param(®_params
[3]);
539 destroy_reg_param(®_params
[4]);
540 destroy_reg_param(®_params
[5]);
545 static int str7x_write(struct flash_bank
*bank
, const uint8_t *buffer
,
546 uint32_t offset
, uint32_t count
)
548 struct target
*target
= bank
->target
;
549 uint32_t dwords_remaining
= (count
/ 8);
550 uint32_t bytes_remaining
= (count
& 0x00000007);
551 uint32_t address
= bank
->base
+ offset
;
552 uint32_t bytes_written
= 0;
555 uint32_t check_address
= offset
;
557 if (bank
->target
->state
!= TARGET_HALTED
) {
558 LOG_ERROR("Target not halted");
559 return ERROR_TARGET_NOT_HALTED
;
563 LOG_WARNING("offset 0x%" PRIx32
" breaks required 8-byte alignment", offset
);
564 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
567 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
568 uint32_t sec_start
= bank
->sectors
[i
].offset
;
569 uint32_t sec_end
= sec_start
+ bank
->sectors
[i
].size
;
571 /* check if destination falls within the current sector */
572 if ((check_address
>= sec_start
) && (check_address
< sec_end
)) {
573 /* check if destination ends in the current sector */
574 if (offset
+ count
< sec_end
)
575 check_address
= offset
+ count
;
577 check_address
= sec_end
;
581 if (check_address
!= offset
+ count
)
582 return ERROR_FLASH_DST_OUT_OF_BANK
;
584 /* clear FLASH_ER register */
585 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_ER
), 0x0);
587 /* multiple dwords (8-byte) to be programmed? */
588 if (dwords_remaining
> 0) {
589 /* try using a block write */
590 retval
= str7x_write_block(bank
, buffer
, offset
, dwords_remaining
);
591 if (retval
!= ERROR_OK
) {
592 if (retval
== ERROR_TARGET_RESOURCE_NOT_AVAILABLE
) {
593 /* if block write failed (no sufficient working area),
594 * we use normal (slow) single dword accesses */
595 LOG_WARNING("couldn't use block writes, falling back to single memory accesses");
600 buffer
+= dwords_remaining
* 8;
601 address
+= dwords_remaining
* 8;
602 dwords_remaining
= 0;
606 while (dwords_remaining
> 0) {
609 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
612 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
615 target_write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
),
616 4, 1, buffer
+ bytes_written
);
620 target_write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
),
621 4, 1, buffer
+ bytes_written
);
624 /* start programming cycle */
625 cmd
= FLASH_DWPG
| FLASH_WMS
;
626 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
629 err
= str7x_waitbusy(bank
);
633 err
= str7x_result(bank
);
641 if (bytes_remaining
) {
642 uint8_t last_dword
[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
644 /* copy the last remaining bytes into the write buffer */
645 memcpy(last_dword
, buffer
+bytes_written
, bytes_remaining
);
649 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
652 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), address
);
655 target_write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR0
),
659 target_write_memory(target
, str7x_get_flash_adr(bank
, FLASH_DR1
),
660 4, 1, last_dword
+ 4);
662 /* start programming cycle */
663 cmd
= FLASH_DWPG
| FLASH_WMS
;
664 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), cmd
);
667 err
= str7x_waitbusy(bank
);
671 err
= str7x_result(bank
);
679 static int str7x_probe(struct flash_bank
*bank
)
685 COMMAND_HANDLER(str7x_handle_part_id_command
)
691 static int get_str7x_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
693 /* Setting the write protection on a sector is a permanent change but it
694 * can be disabled temporarily. FLASH_NVWPAR reflects the permanent
695 * protection state of the sectors, not the temporary.
697 command_print_sameline(cmd
, "STR7x flash protection info is only valid after a power cycle, "
698 "clearing the protection is only temporary and may not be reflected in the current "
703 COMMAND_HANDLER(str7x_handle_disable_jtag_command
)
705 struct target
*target
= NULL
;
706 struct str7x_flash_bank
*str7x_info
= NULL
;
709 uint16_t protection_level
= 0;
710 uint16_t protection_regs
;
713 return ERROR_COMMAND_SYNTAX_ERROR
;
715 struct flash_bank
*bank
;
716 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &bank
);
717 if (retval
!= ERROR_OK
)
720 str7x_info
= bank
->driver_priv
;
722 target
= bank
->target
;
724 if (target
->state
!= TARGET_HALTED
) {
725 LOG_ERROR("Target not halted");
726 return ERROR_TARGET_NOT_HALTED
;
729 /* first we get protection status */
731 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR0
), ®
);
733 if (!(reg
& str7x_info
->disable_bit
))
734 protection_level
= 1;
736 target_read_u32(target
, str7x_get_flash_adr(bank
, FLASH_NVAPR1
), ®
);
737 protection_regs
= ~(reg
>> 16);
739 while (((protection_regs
) != 0) && (protection_level
< 16)) {
740 protection_regs
>>= 1;
744 if (protection_level
== 0) {
745 flash_cmd
= FLASH_SPR
;
746 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
747 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_AR
), 0x4010DFB8);
748 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
), 0xFFFFFFFD);
749 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
750 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
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
), 0x4010DFBC);
755 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_DR0
),
756 ~(1 << (15 + protection_level
)));
757 flash_cmd
= FLASH_SPR
| FLASH_WMS
;
758 target_write_u32(target
, str7x_get_flash_adr(bank
, FLASH_CR0
), flash_cmd
);
764 static const struct command_registration str7x_exec_command_handlers
[] = {
766 .name
= "disable_jtag",
768 .handler
= str7x_handle_disable_jtag_command
,
769 .mode
= COMMAND_EXEC
,
770 .help
= "disable jtag access",
772 COMMAND_REGISTRATION_DONE
775 static const struct command_registration str7x_command_handlers
[] = {
779 .help
= "str7x flash command group",
781 .chain
= str7x_exec_command_handlers
,
783 COMMAND_REGISTRATION_DONE
786 const struct flash_driver str7x_flash
= {
788 .commands
= str7x_command_handlers
,
789 .flash_bank_command
= str7x_flash_bank_command
,
790 .erase
= str7x_erase
,
791 .protect
= str7x_protect
,
792 .write
= str7x_write
,
793 .read
= default_flash_read
,
794 .probe
= str7x_probe
,
795 .auto_probe
= str7x_probe
,
796 .erase_check
= default_flash_blank_check
,
797 .protect_check
= str7x_protect_check
,
798 .info
= get_str7x_info
,
799 .free_driver_priv
= default_flash_free_driver_priv
,
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)