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
, int first
, int last
)
103 struct target
*target
= bank
->target
;
104 struct working_area
*workarea
;
105 struct reg_param reg_params
[4];
106 struct armv7m_algorithm armv7m_algo
;
109 const uint8_t erase_sector_code
[] = {
110 #include "../../../contrib/loaders/flash/fm4/erase.inc"
113 if (target
->state
!= TARGET_HALTED
) {
114 LOG_WARNING("Cannot communicate... target not halted.");
115 return ERROR_TARGET_NOT_HALTED
;
118 LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first
, last
);
120 retval
= fm4_disable_hw_watchdog(target
);
121 if (retval
!= ERROR_OK
)
124 retval
= fm4_enter_flash_cpu_programming_mode(target
);
125 if (retval
!= ERROR_OK
)
128 retval
= target_alloc_working_area(target
, sizeof(erase_sector_code
),
130 if (retval
!= ERROR_OK
) {
131 LOG_ERROR("No working area available.");
132 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
135 retval
= target_write_buffer(target
, workarea
->address
,
136 sizeof(erase_sector_code
), erase_sector_code
);
137 if (retval
!= ERROR_OK
)
140 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
141 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
143 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
144 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
145 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
146 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
148 for (sector
= first
; sector
<= last
; sector
++) {
149 uint32_t addr
= bank
->base
+ bank
->sectors
[sector
].offset
;
152 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
153 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
154 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
156 retval
= target_run_algorithm(target
,
158 ARRAY_SIZE(reg_params
), reg_params
,
159 workarea
->address
, 0,
161 if (retval
!= ERROR_OK
) {
162 LOG_ERROR("Error executing flash sector erase "
163 "programming algorithm");
164 retval
= ERROR_FLASH_OPERATION_FAILED
;
168 result
= buf_get_u32(reg_params
[3].value
, 0, 32);
170 LOG_ERROR("Timeout error from flash sector erase programming algorithm");
171 retval
= ERROR_FLASH_OPERATION_FAILED
;
173 } else if (result
!= 0) {
174 LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result
);
175 retval
= ERROR_FLASH_OPERATION_FAILED
;
180 bank
->sectors
[sector
].is_erased
= 1;
185 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
186 destroy_reg_param(®_params
[i
]);
189 target_free_working_area(target
, workarea
);
192 if (retval
!= ERROR_OK
)
193 fm4_enter_flash_cpu_rom_mode(target
);
195 retval
= fm4_enter_flash_cpu_rom_mode(target
);
200 static int fm4_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
201 uint32_t offset
, uint32_t byte_count
)
203 struct target
*target
= bank
->target
;
204 struct working_area
*code_workarea
, *data_workarea
;
205 struct reg_param reg_params
[6];
206 struct armv7m_algorithm armv7m_algo
;
207 uint32_t halfword_count
= DIV_ROUND_UP(byte_count
, 2);
211 const uint8_t write_block_code
[] = {
212 #include "../../../contrib/loaders/flash/fm4/write.inc"
215 LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32
" (%" PRId32
" bytes)",
219 LOG_ERROR("offset 0x%" PRIx32
" breaks required 2-byte alignment",
221 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
223 if (byte_count
& 0x1) {
224 LOG_WARNING("length %" PRId32
" is not 2-byte aligned, rounding up",
228 if (target
->state
!= TARGET_HALTED
) {
229 LOG_WARNING("Cannot communicate... target not halted.");
230 return ERROR_TARGET_NOT_HALTED
;
233 retval
= fm4_disable_hw_watchdog(target
);
234 if (retval
!= ERROR_OK
)
237 retval
= target_alloc_working_area(target
, sizeof(write_block_code
),
239 if (retval
!= ERROR_OK
) {
240 LOG_ERROR("No working area available for write code.");
241 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
243 retval
= target_write_buffer(target
, code_workarea
->address
,
244 sizeof(write_block_code
), write_block_code
);
245 if (retval
!= ERROR_OK
)
248 retval
= target_alloc_working_area(target
,
249 MIN(halfword_count
* 2, target_get_working_area_avail(target
)),
251 if (retval
!= ERROR_OK
) {
252 LOG_ERROR("No working area available for write data.");
253 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
257 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
258 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
260 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
261 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
262 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
263 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
264 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
);
265 init_reg_param(®_params
[5], "r5", 32, PARAM_IN
);
267 retval
= fm4_enter_flash_cpu_programming_mode(target
);
268 if (retval
!= ERROR_OK
)
271 while (byte_count
> 0) {
272 uint32_t halfwords
= MIN(halfword_count
, data_workarea
->size
/ 2);
273 uint32_t addr
= bank
->base
+ offset
;
275 LOG_DEBUG("copying %" PRId32
" bytes to SRAM " TARGET_ADDR_FMT
,
276 MIN(halfwords
* 2, byte_count
), data_workarea
->address
);
278 retval
= target_write_buffer(target
, data_workarea
->address
,
279 MIN(halfwords
* 2, byte_count
), buffer
);
280 if (retval
!= ERROR_OK
) {
281 LOG_ERROR("Error writing data buffer");
282 retval
= ERROR_FLASH_OPERATION_FAILED
;
286 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRId32
"x)",
287 addr
, addr
+ halfwords
* 2 - 1, halfwords
);
289 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
290 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
291 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
292 buf_set_u32(reg_params
[3].value
, 0, 32, data_workarea
->address
);
293 buf_set_u32(reg_params
[4].value
, 0, 32, halfwords
);
295 retval
= target_run_algorithm(target
,
297 ARRAY_SIZE(reg_params
), reg_params
,
298 code_workarea
->address
, 0,
299 5 * 60 * 1000, &armv7m_algo
);
300 if (retval
!= ERROR_OK
) {
301 LOG_ERROR("Error executing flash sector erase "
302 "programming algorithm");
303 retval
= ERROR_FLASH_OPERATION_FAILED
;
307 result
= buf_get_u32(reg_params
[5].value
, 0, 32);
309 LOG_ERROR("Timeout error from flash write "
310 "programming algorithm");
311 retval
= ERROR_FLASH_OPERATION_FAILED
;
313 } else if (result
!= 0) {
314 LOG_ERROR("Unexpected error %d from flash write "
315 "programming algorithm", result
);
316 retval
= ERROR_FLASH_OPERATION_FAILED
;
321 halfword_count
-= halfwords
;
322 offset
+= halfwords
* 2;
323 buffer
+= halfwords
* 2;
324 byte_count
-= MIN(halfwords
* 2, byte_count
);
330 retval
= fm4_enter_flash_cpu_rom_mode(target
);
333 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
334 destroy_reg_param(®_params
[i
]);
336 target_free_working_area(target
, data_workarea
);
339 target_free_working_area(target
, code_workarea
);
344 static int mb9bf_probe(struct flash_bank
*bank
)
346 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
347 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("%d sectors", bank
->num_sectors
);
371 bank
->sectors
= calloc(bank
->num_sectors
,
372 sizeof(struct flash_sector
));
373 for (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
;
410 int i
, retval
, num_sectors
, num_extra_sectors
;
412 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
413 if (retval
!= ERROR_OK
)
415 if (u32_value
& DFCTRLR_DFE
) {
416 LOG_WARNING("Dual Flash mode is not implemented.");
417 return ERROR_FLASH_OPER_UNSUPPORTED
;
420 switch (fm4_bank
->variant
) {
422 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
425 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
431 return ERROR_FLASH_OPER_UNSUPPORTED
;
433 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
434 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
436 LOG_DEBUG("%d sectors", bank
->num_sectors
);
437 bank
->sectors
= calloc(bank
->num_sectors
,
438 sizeof(struct flash_sector
));
439 for (i
= 0; i
< num_sectors
; i
++) {
441 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
442 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
444 bank
->size
+= bank
->sectors
[i
].size
;
445 flash_addr
+= bank
->sectors
[i
].size
;
448 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
449 for (; i
< bank
->num_sectors
; i
++) {
450 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
451 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
452 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
455 * Don't increase bank->size for these sectors
456 * to avoid an overlap between Flash Macros #0 and #1.
458 flash_addr
+= bank
->sectors
[i
].size
;
464 static int s6e2dh_probe(struct flash_bank
*bank
)
466 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 (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
, char *buf
, int buf_size
)
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 snprintf(buf
, buf_size
, "%s MainFlash Macro #%i",
588 name
, fm4_bank
->macro_nr
);
591 snprintf(buf
, buf_size
, "%s MainFlash", name
);
598 static bool fm4_name_match(const char *s
, const char *pattern
)
603 /* If the match string is shorter, ignore excess */
606 /* Use x as wildcard */
607 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
614 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
616 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
618 if (fm4_name_match(variant
, "MB9BFx64")) {
619 fm4_bank
->variant
= mb9bfx64
;
620 } else if (fm4_name_match(variant
, "MB9BFx65")) {
621 fm4_bank
->variant
= mb9bfx65
;
622 } else if (fm4_name_match(variant
, "MB9BFx66")) {
623 fm4_bank
->variant
= mb9bfx66
;
624 } else if (fm4_name_match(variant
, "MB9BFx67")) {
625 fm4_bank
->variant
= mb9bfx67
;
626 } else if (fm4_name_match(variant
, "MB9BFx68")) {
627 fm4_bank
->variant
= mb9bfx68
;
629 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
630 return ERROR_FLASH_OPER_UNSUPPORTED
;
636 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
638 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
640 if (fm4_name_match(variant
, "S6E2Cx8")) {
641 fm4_bank
->variant
= s6e2cx8
;
642 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
643 fm4_bank
->variant
= s6e2cx9
;
644 } else if (fm4_name_match(variant
, "S6E2CxA")) {
645 fm4_bank
->variant
= s6e2cxa
;
647 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
648 return ERROR_FLASH_OPER_UNSUPPORTED
;
654 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
656 struct fm4_flash_bank
*fm4_bank
;
661 return ERROR_COMMAND_SYNTAX_ERROR
;
663 variant
= CMD_ARGV
[6];
665 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
667 return ERROR_FLASH_OPERATION_FAILED
;
669 fm4_bank
->probed
= false;
670 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
672 bank
->driver_priv
= fm4_bank
;
674 if (fm4_name_match(variant
, "MB9BF"))
675 ret
= mb9bf_bank_setup(bank
, variant
);
676 else if (fm4_name_match(variant
, "S6E2Cx"))
677 ret
= s6e2cc_bank_setup(bank
, variant
);
678 else if (fm4_name_match(variant
, "S6E2Dx")) {
679 fm4_bank
->variant
= s6e2dx
;
682 LOG_WARNING("Family %s not recognized.", variant
);
683 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
690 static const struct command_registration fm4_exec_command_handlers
[] = {
691 COMMAND_REGISTRATION_DONE
694 static const struct command_registration fm4_command_handlers
[] = {
698 .help
= "fm4 flash command group",
700 .chain
= fm4_exec_command_handlers
,
702 COMMAND_REGISTRATION_DONE
705 const struct flash_driver fm4_flash
= {
707 .commands
= fm4_command_handlers
,
708 .flash_bank_command
= fm4_flash_bank_command
,
709 .info
= fm4_get_info_command
,
711 .auto_probe
= fm4_auto_probe
,
712 .read
= default_flash_read
,
713 .erase
= fm4_flash_erase
,
714 .erase_check
= default_flash_blank_check
,
715 .write
= fm4_flash_write
,
716 .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)