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);
210 int retval
, retval2
= ERROR_OK
;
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 retval2
= 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
);
341 if (retval
!= ERROR_OK
)
346 static int mb9bf_probe(struct flash_bank
*bank
)
348 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
349 uint32_t flash_addr
= bank
->base
;
352 switch (fm4_bank
->variant
) {
354 bank
->num_sectors
= 8;
357 bank
->num_sectors
= 10;
360 bank
->num_sectors
= 12;
363 bank
->num_sectors
= 16;
366 bank
->num_sectors
= 20;
369 return ERROR_FLASH_OPER_UNSUPPORTED
;
372 LOG_DEBUG("%d sectors", bank
->num_sectors
);
373 bank
->sectors
= calloc(bank
->num_sectors
,
374 sizeof(struct flash_sector
));
375 for (i
= 0; i
< bank
->num_sectors
; i
++) {
377 bank
->sectors
[i
].size
= 8 * 1024;
379 bank
->sectors
[i
].size
= 32 * 1024;
381 bank
->sectors
[i
].size
= 64 * 1024;
382 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
383 bank
->sectors
[i
].is_erased
= -1;
384 bank
->sectors
[i
].is_protected
= -1;
386 bank
->size
+= bank
->sectors
[i
].size
;
387 flash_addr
+= bank
->sectors
[i
].size
;
393 static void s6e2cc_init_sector(struct flash_sector
*sector
, int sa
)
396 sector
->size
= 8 * 1024;
398 sector
->size
= 32 * 1024;
400 sector
->size
= 64 * 1024;
402 sector
->is_erased
= -1;
403 sector
->is_protected
= -1;
406 static int s6e2cc_probe(struct flash_bank
*bank
)
408 struct target
*target
= bank
->target
;
409 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
411 uint32_t flash_addr
= bank
->base
;
412 int i
, retval
, num_sectors
, num_extra_sectors
;
414 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
415 if (retval
!= ERROR_OK
)
417 if (u32_value
& DFCTRLR_DFE
) {
418 LOG_WARNING("Dual Flash mode is not implemented.");
419 return ERROR_FLASH_OPER_UNSUPPORTED
;
422 switch (fm4_bank
->variant
) {
424 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
427 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
433 return ERROR_FLASH_OPER_UNSUPPORTED
;
435 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
436 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
438 LOG_DEBUG("%d sectors", bank
->num_sectors
);
439 bank
->sectors
= calloc(bank
->num_sectors
,
440 sizeof(struct flash_sector
));
441 for (i
= 0; i
< num_sectors
; i
++) {
443 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
444 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
446 bank
->size
+= bank
->sectors
[i
].size
;
447 flash_addr
+= bank
->sectors
[i
].size
;
450 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
451 for (; i
< bank
->num_sectors
; i
++) {
452 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
453 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
454 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
457 * Don't increase bank->size for these sectors
458 * to avoid an overlap between Flash Macros #0 and #1.
460 flash_addr
+= bank
->sectors
[i
].size
;
466 static int s6e2dh_probe(struct flash_bank
*bank
)
468 uint32_t flash_addr
= bank
->base
;
471 bank
->num_sectors
= 10;
472 bank
->sectors
= calloc(bank
->num_sectors
,
473 sizeof(struct flash_sector
));
474 for (i
= 0; i
< bank
->num_sectors
; i
++) {
476 bank
->sectors
[i
].size
= 8 * 1024;
478 bank
->sectors
[i
].size
= 32 * 1024;
480 bank
->sectors
[i
].size
= 64 * 1024;
481 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
482 bank
->sectors
[i
].is_erased
= -1;
483 bank
->sectors
[i
].is_protected
= -1;
485 bank
->size
+= bank
->sectors
[i
].size
;
486 flash_addr
+= bank
->sectors
[i
].size
;
492 static int fm4_probe(struct flash_bank
*bank
)
494 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
497 if (fm4_bank
->probed
)
500 if (bank
->target
->state
!= TARGET_HALTED
) {
501 LOG_WARNING("Cannot communicate... target not halted.");
502 return ERROR_TARGET_NOT_HALTED
;
505 switch (fm4_bank
->variant
) {
511 retval
= mb9bf_probe(bank
);
516 retval
= s6e2cc_probe(bank
);
519 retval
= s6e2dh_probe(bank
);
522 return ERROR_FLASH_OPER_UNSUPPORTED
;
524 if (retval
!= ERROR_OK
)
527 fm4_bank
->probed
= true;
532 static int fm4_auto_probe(struct flash_bank
*bank
)
534 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
536 if (fm4_bank
->probed
)
539 return fm4_probe(bank
);
542 static int fm4_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
544 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
547 if (bank
->target
->state
!= TARGET_HALTED
) {
548 LOG_WARNING("Cannot communicate... target not halted.");
549 return ERROR_TARGET_NOT_HALTED
;
552 switch (fm4_bank
->variant
) {
585 switch (fm4_bank
->variant
) {
589 snprintf(buf
, buf_size
, "%s MainFlash Macro #%i",
590 name
, fm4_bank
->macro_nr
);
593 snprintf(buf
, buf_size
, "%s MainFlash", name
);
600 static bool fm4_name_match(const char *s
, const char *pattern
)
605 /* If the match string is shorter, ignore excess */
608 /* Use x as wildcard */
609 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
616 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
618 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
620 if (fm4_name_match(variant
, "MB9BFx64")) {
621 fm4_bank
->variant
= mb9bfx64
;
622 } else if (fm4_name_match(variant
, "MB9BFx65")) {
623 fm4_bank
->variant
= mb9bfx65
;
624 } else if (fm4_name_match(variant
, "MB9BFx66")) {
625 fm4_bank
->variant
= mb9bfx66
;
626 } else if (fm4_name_match(variant
, "MB9BFx67")) {
627 fm4_bank
->variant
= mb9bfx67
;
628 } else if (fm4_name_match(variant
, "MB9BFx68")) {
629 fm4_bank
->variant
= mb9bfx68
;
631 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
632 return ERROR_FLASH_OPER_UNSUPPORTED
;
638 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
640 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
642 if (fm4_name_match(variant
, "S6E2Cx8")) {
643 fm4_bank
->variant
= s6e2cx8
;
644 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
645 fm4_bank
->variant
= s6e2cx9
;
646 } else if (fm4_name_match(variant
, "S6E2CxA")) {
647 fm4_bank
->variant
= s6e2cxa
;
649 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
650 return ERROR_FLASH_OPER_UNSUPPORTED
;
656 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
658 struct fm4_flash_bank
*fm4_bank
;
663 return ERROR_COMMAND_SYNTAX_ERROR
;
665 variant
= CMD_ARGV
[6];
667 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
669 return ERROR_FLASH_OPERATION_FAILED
;
671 fm4_bank
->probed
= false;
672 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
674 bank
->driver_priv
= fm4_bank
;
676 if (fm4_name_match(variant
, "MB9BF"))
677 ret
= mb9bf_bank_setup(bank
, variant
);
678 else if (fm4_name_match(variant
, "S6E2Cx"))
679 ret
= s6e2cc_bank_setup(bank
, variant
);
680 else if (fm4_name_match(variant
, "S6E2Dx")) {
681 fm4_bank
->variant
= s6e2dx
;
684 LOG_WARNING("Family %s not recognized.", variant
);
685 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
692 static const struct command_registration fm4_exec_command_handlers
[] = {
693 COMMAND_REGISTRATION_DONE
696 static const struct command_registration fm4_command_handlers
[] = {
700 .help
= "fm4 flash command group",
702 .chain
= fm4_exec_command_handlers
,
704 COMMAND_REGISTRATION_DONE
707 const struct flash_driver fm4_flash
= {
709 .commands
= fm4_command_handlers
,
710 .flash_bank_command
= fm4_flash_bank_command
,
711 .info
= fm4_get_info_command
,
713 .auto_probe
= fm4_auto_probe
,
714 .read
= default_flash_read
,
715 .erase
= fm4_flash_erase
,
716 .erase_check
= default_flash_blank_check
,
717 .write
= fm4_flash_write
,
718 .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)