4 * Copyright (c) 2015 Andreas Färber
6 * Based on S6E2DH_MN709-00013 for S6E2DH/DF/D5/D3 series
7 * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
8 * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
9 * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
17 #include <helper/binarybuffer.h>
18 #include <target/algorithm.h>
19 #include <target/armv7m.h>
21 #define FLASH_BASE 0x40000000
22 #define FASZR (FLASH_BASE + 0x000)
23 #define DFCTRLR (FLASH_BASE + 0x030)
24 #define DFCTRLR_DFE (1UL << 0)
26 #define WDG_BASE 0x40011000
27 #define WDG_CTL (WDG_BASE + 0x008)
28 #define WDG_LCK (WDG_BASE + 0xC00)
44 struct fm4_flash_bank
{
45 enum fm4_variant variant
;
50 static int fm4_disable_hw_watchdog(struct target
*target
)
54 retval
= target_write_u32(target
, WDG_LCK
, 0x1ACCE551);
55 if (retval
!= ERROR_OK
)
58 retval
= target_write_u32(target
, WDG_LCK
, 0xE5331AAE);
59 if (retval
!= ERROR_OK
)
62 retval
= target_write_u32(target
, WDG_CTL
, 0);
63 if (retval
!= ERROR_OK
)
69 static int fm4_enter_flash_cpu_programming_mode(struct target
*target
)
74 /* FASZR ASZ = CPU programming mode */
75 retval
= target_write_u32(target
, FASZR
, 0x00000001);
76 if (retval
!= ERROR_OK
)
78 retval
= target_read_u32(target
, FASZR
, &u32_value
);
79 if (retval
!= ERROR_OK
)
85 static int fm4_enter_flash_cpu_rom_mode(struct target
*target
)
90 /* FASZR ASZ = CPU ROM mode */
91 retval
= target_write_u32(target
, FASZR
, 0x00000002);
92 if (retval
!= ERROR_OK
)
94 retval
= target_read_u32(target
, FASZR
, &u32_value
);
95 if (retval
!= ERROR_OK
)
101 static int fm4_flash_erase(struct flash_bank
*bank
, unsigned int first
,
104 struct target
*target
= bank
->target
;
105 struct working_area
*workarea
;
106 struct reg_param reg_params
[4];
107 struct armv7m_algorithm armv7m_algo
;
110 const uint8_t erase_sector_code
[] = {
111 #include "../../../contrib/loaders/flash/fm4/erase.inc"
114 if (target
->state
!= TARGET_HALTED
) {
115 LOG_WARNING("Cannot communicate... target not halted.");
116 return ERROR_TARGET_NOT_HALTED
;
119 LOG_DEBUG("Spansion FM4 erase sectors %u to %u", first
, last
);
121 retval
= fm4_disable_hw_watchdog(target
);
122 if (retval
!= ERROR_OK
)
125 retval
= fm4_enter_flash_cpu_programming_mode(target
);
126 if (retval
!= ERROR_OK
)
129 retval
= target_alloc_working_area(target
, sizeof(erase_sector_code
),
131 if (retval
!= ERROR_OK
) {
132 LOG_ERROR("No working area available.");
133 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
136 retval
= target_write_buffer(target
, workarea
->address
,
137 sizeof(erase_sector_code
), erase_sector_code
);
138 if (retval
!= ERROR_OK
)
141 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
142 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
144 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
145 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
146 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
147 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
149 for (unsigned int sector
= first
; sector
<= last
; sector
++) {
150 uint32_t addr
= bank
->base
+ bank
->sectors
[sector
].offset
;
153 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
154 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
155 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
157 retval
= target_run_algorithm(target
,
159 ARRAY_SIZE(reg_params
), reg_params
,
160 workarea
->address
, 0,
162 if (retval
!= ERROR_OK
) {
163 LOG_ERROR("Error executing flash sector erase "
164 "programming algorithm");
165 retval
= ERROR_FLASH_OPERATION_FAILED
;
169 result
= buf_get_u32(reg_params
[3].value
, 0, 32);
171 LOG_ERROR("Timeout error from flash sector erase programming algorithm");
172 retval
= ERROR_FLASH_OPERATION_FAILED
;
174 } else if (result
!= 0) {
175 LOG_ERROR("Unexpected error %" PRIu32
" from flash sector erase programming algorithm", result
);
176 retval
= ERROR_FLASH_OPERATION_FAILED
;
184 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
185 destroy_reg_param(®_params
[i
]);
188 target_free_working_area(target
, workarea
);
191 if (retval
!= ERROR_OK
)
192 fm4_enter_flash_cpu_rom_mode(target
);
194 retval
= fm4_enter_flash_cpu_rom_mode(target
);
199 static int fm4_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
200 uint32_t offset
, uint32_t byte_count
)
202 struct target
*target
= bank
->target
;
203 struct working_area
*code_workarea
, *data_workarea
;
204 struct reg_param reg_params
[6];
205 struct armv7m_algorithm armv7m_algo
;
206 uint32_t halfword_count
= DIV_ROUND_UP(byte_count
, 2);
209 int retval
, retval2
= ERROR_OK
;
210 const uint8_t write_block_code
[] = {
211 #include "../../../contrib/loaders/flash/fm4/write.inc"
214 LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32
" (%" PRIu32
" bytes)",
218 LOG_ERROR("offset 0x%" PRIx32
" breaks required 2-byte alignment",
220 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
222 if (byte_count
& 0x1) {
223 LOG_WARNING("length %" PRIu32
" is not 2-byte aligned, rounding up",
227 if (target
->state
!= TARGET_HALTED
) {
228 LOG_WARNING("Cannot communicate... target not halted.");
229 return ERROR_TARGET_NOT_HALTED
;
232 retval
= fm4_disable_hw_watchdog(target
);
233 if (retval
!= ERROR_OK
)
236 retval
= target_alloc_working_area(target
, sizeof(write_block_code
),
238 if (retval
!= ERROR_OK
) {
239 LOG_ERROR("No working area available for write code.");
240 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
242 retval
= target_write_buffer(target
, code_workarea
->address
,
243 sizeof(write_block_code
), write_block_code
);
244 if (retval
!= ERROR_OK
)
247 retval
= target_alloc_working_area(target
,
248 MIN(halfword_count
* 2, target_get_working_area_avail(target
)),
250 if (retval
!= ERROR_OK
) {
251 LOG_ERROR("No working area available for write data.");
252 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
256 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
257 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
259 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
260 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
261 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
262 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
263 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
);
264 init_reg_param(®_params
[5], "r5", 32, PARAM_IN
);
266 retval
= fm4_enter_flash_cpu_programming_mode(target
);
267 if (retval
!= ERROR_OK
)
270 while (byte_count
> 0) {
271 uint32_t halfwords
= MIN(halfword_count
, data_workarea
->size
/ 2);
272 uint32_t addr
= bank
->base
+ offset
;
274 LOG_DEBUG("copying %" PRIu32
" bytes to SRAM " TARGET_ADDR_FMT
,
275 MIN(halfwords
* 2, byte_count
), data_workarea
->address
);
277 retval
= target_write_buffer(target
, data_workarea
->address
,
278 MIN(halfwords
* 2, byte_count
), buffer
);
279 if (retval
!= ERROR_OK
) {
280 LOG_ERROR("Error writing data buffer");
281 retval
= ERROR_FLASH_OPERATION_FAILED
;
285 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRIu32
"x)",
286 addr
, addr
+ halfwords
* 2 - 1, halfwords
);
288 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
289 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
290 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
291 buf_set_u32(reg_params
[3].value
, 0, 32, data_workarea
->address
);
292 buf_set_u32(reg_params
[4].value
, 0, 32, halfwords
);
294 retval
= target_run_algorithm(target
,
296 ARRAY_SIZE(reg_params
), reg_params
,
297 code_workarea
->address
, 0,
298 5 * 60 * 1000, &armv7m_algo
);
299 if (retval
!= ERROR_OK
) {
300 LOG_ERROR("Error executing flash sector erase "
301 "programming algorithm");
302 retval
= ERROR_FLASH_OPERATION_FAILED
;
306 result
= buf_get_u32(reg_params
[5].value
, 0, 32);
308 LOG_ERROR("Timeout error from flash write "
309 "programming algorithm");
310 retval
= ERROR_FLASH_OPERATION_FAILED
;
312 } else if (result
!= 0) {
313 LOG_ERROR("Unexpected error %" PRIu32
" from flash write "
314 "programming algorithm", result
);
315 retval
= ERROR_FLASH_OPERATION_FAILED
;
320 halfword_count
-= halfwords
;
321 offset
+= halfwords
* 2;
322 buffer
+= halfwords
* 2;
323 byte_count
-= MIN(halfwords
* 2, byte_count
);
329 retval2
= fm4_enter_flash_cpu_rom_mode(target
);
332 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
333 destroy_reg_param(®_params
[i
]);
335 target_free_working_area(target
, data_workarea
);
338 target_free_working_area(target
, code_workarea
);
340 if (retval
!= ERROR_OK
)
345 static int mb9bf_probe(struct flash_bank
*bank
)
347 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
348 uint32_t flash_addr
= bank
->base
;
350 switch (fm4_bank
->variant
) {
352 bank
->num_sectors
= 8;
355 bank
->num_sectors
= 10;
358 bank
->num_sectors
= 12;
361 bank
->num_sectors
= 16;
364 bank
->num_sectors
= 20;
367 return ERROR_FLASH_OPER_UNSUPPORTED
;
370 LOG_DEBUG("%u sectors", bank
->num_sectors
);
371 bank
->sectors
= calloc(bank
->num_sectors
,
372 sizeof(struct flash_sector
));
373 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
375 bank
->sectors
[i
].size
= 8 * 1024;
377 bank
->sectors
[i
].size
= 32 * 1024;
379 bank
->sectors
[i
].size
= 64 * 1024;
380 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
381 bank
->sectors
[i
].is_erased
= -1;
382 bank
->sectors
[i
].is_protected
= -1;
384 bank
->size
+= bank
->sectors
[i
].size
;
385 flash_addr
+= bank
->sectors
[i
].size
;
391 static void s6e2cc_init_sector(struct flash_sector
*sector
, int sa
)
394 sector
->size
= 8 * 1024;
396 sector
->size
= 32 * 1024;
398 sector
->size
= 64 * 1024;
400 sector
->is_erased
= -1;
401 sector
->is_protected
= -1;
404 static int s6e2cc_probe(struct flash_bank
*bank
)
406 struct target
*target
= bank
->target
;
407 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
409 uint32_t flash_addr
= bank
->base
;
411 unsigned int i
, num_extra_sectors
, num_sectors
;
413 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
414 if (retval
!= ERROR_OK
)
416 if (u32_value
& DFCTRLR_DFE
) {
417 LOG_WARNING("Dual Flash mode is not implemented.");
418 return ERROR_FLASH_OPER_UNSUPPORTED
;
421 switch (fm4_bank
->variant
) {
423 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
426 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
432 return ERROR_FLASH_OPER_UNSUPPORTED
;
434 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
435 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
437 LOG_DEBUG("%u sectors", bank
->num_sectors
);
438 bank
->sectors
= calloc(bank
->num_sectors
,
439 sizeof(struct flash_sector
));
440 for (i
= 0; i
< num_sectors
; i
++) {
442 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
443 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
445 bank
->size
+= bank
->sectors
[i
].size
;
446 flash_addr
+= bank
->sectors
[i
].size
;
449 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
450 for (; i
< bank
->num_sectors
; i
++) {
451 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
452 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
453 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
456 * Don't increase bank->size for these sectors
457 * to avoid an overlap between Flash Macros #0 and #1.
459 flash_addr
+= bank
->sectors
[i
].size
;
465 static int s6e2dh_probe(struct flash_bank
*bank
)
467 uint32_t flash_addr
= bank
->base
;
469 bank
->num_sectors
= 10;
470 bank
->sectors
= calloc(bank
->num_sectors
,
471 sizeof(struct flash_sector
));
472 for (unsigned int i
= 0; i
< bank
->num_sectors
; i
++) {
474 bank
->sectors
[i
].size
= 8 * 1024;
476 bank
->sectors
[i
].size
= 32 * 1024;
478 bank
->sectors
[i
].size
= 64 * 1024;
479 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
480 bank
->sectors
[i
].is_erased
= -1;
481 bank
->sectors
[i
].is_protected
= -1;
483 bank
->size
+= bank
->sectors
[i
].size
;
484 flash_addr
+= bank
->sectors
[i
].size
;
490 static int fm4_probe(struct flash_bank
*bank
)
492 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
495 if (fm4_bank
->probed
)
498 if (bank
->target
->state
!= TARGET_HALTED
) {
499 LOG_WARNING("Cannot communicate... target not halted.");
500 return ERROR_TARGET_NOT_HALTED
;
503 switch (fm4_bank
->variant
) {
509 retval
= mb9bf_probe(bank
);
514 retval
= s6e2cc_probe(bank
);
517 retval
= s6e2dh_probe(bank
);
520 return ERROR_FLASH_OPER_UNSUPPORTED
;
522 if (retval
!= ERROR_OK
)
525 fm4_bank
->probed
= true;
530 static int fm4_auto_probe(struct flash_bank
*bank
)
532 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
534 if (fm4_bank
->probed
)
537 return fm4_probe(bank
);
540 static int fm4_get_info_command(struct flash_bank
*bank
, struct command_invocation
*cmd
)
542 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
545 if (bank
->target
->state
!= TARGET_HALTED
) {
546 LOG_WARNING("Cannot communicate... target not halted.");
547 return ERROR_TARGET_NOT_HALTED
;
550 switch (fm4_bank
->variant
) {
583 switch (fm4_bank
->variant
) {
587 command_print_sameline(cmd
, "%s MainFlash Macro #%i", name
, fm4_bank
->macro_nr
);
590 command_print_sameline(cmd
, "%s MainFlash", name
);
597 static bool fm4_name_match(const char *s
, const char *pattern
)
602 /* If the match string is shorter, ignore excess */
605 /* Use x as wildcard */
606 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
613 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
615 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
617 if (fm4_name_match(variant
, "MB9BFx64")) {
618 fm4_bank
->variant
= MB9BFX64
;
619 } else if (fm4_name_match(variant
, "MB9BFx65")) {
620 fm4_bank
->variant
= MB9BFX65
;
621 } else if (fm4_name_match(variant
, "MB9BFx66")) {
622 fm4_bank
->variant
= MB9BFX66
;
623 } else if (fm4_name_match(variant
, "MB9BFx67")) {
624 fm4_bank
->variant
= MB9BFX67
;
625 } else if (fm4_name_match(variant
, "MB9BFx68")) {
626 fm4_bank
->variant
= MB9BFX68
;
628 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
629 return ERROR_FLASH_OPER_UNSUPPORTED
;
635 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
637 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
639 if (fm4_name_match(variant
, "S6E2Cx8")) {
640 fm4_bank
->variant
= S6E2CX8
;
641 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
642 fm4_bank
->variant
= S6E2CX9
;
643 } else if (fm4_name_match(variant
, "S6E2CxA")) {
644 fm4_bank
->variant
= S6E2CXA
;
646 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
647 return ERROR_FLASH_OPER_UNSUPPORTED
;
653 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
655 struct fm4_flash_bank
*fm4_bank
;
660 return ERROR_COMMAND_SYNTAX_ERROR
;
662 variant
= CMD_ARGV
[6];
664 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
666 return ERROR_FLASH_OPERATION_FAILED
;
668 fm4_bank
->probed
= false;
669 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
671 bank
->driver_priv
= fm4_bank
;
673 if (fm4_name_match(variant
, "MB9BF"))
674 ret
= mb9bf_bank_setup(bank
, variant
);
675 else if (fm4_name_match(variant
, "S6E2Cx"))
676 ret
= s6e2cc_bank_setup(bank
, variant
);
677 else if (fm4_name_match(variant
, "S6E2Dx")) {
678 fm4_bank
->variant
= S6E2DX
;
681 LOG_WARNING("Family %s not recognized.", variant
);
682 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
689 static const struct command_registration fm4_exec_command_handlers
[] = {
690 COMMAND_REGISTRATION_DONE
693 static const struct command_registration fm4_command_handlers
[] = {
697 .help
= "fm4 flash command group",
699 .chain
= fm4_exec_command_handlers
,
701 COMMAND_REGISTRATION_DONE
704 const struct flash_driver fm4_flash
= {
706 .commands
= fm4_command_handlers
,
707 .flash_bank_command
= fm4_flash_bank_command
,
708 .info
= fm4_get_info_command
,
710 .auto_probe
= fm4_auto_probe
,
711 .read
= default_flash_read
,
712 .erase
= fm4_flash_erase
,
713 .erase_check
= default_flash_blank_check
,
714 .write
= fm4_flash_write
,
715 .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)