4 * Copyright (c) 2015 Andreas Färber
6 * Based on S6E2CC_MN709-00007 for S6E2CC/C5/C4/C3/C2/C1 series
7 * Based on MB9B560R_MN709-00005 for MB9BFx66/x67/x68 series
8 * Based on MB9B560L_MN709-00006 for MB9BFx64/x65/x66 series
16 #include <helper/binarybuffer.h>
17 #include <target/algorithm.h>
18 #include <target/armv7m.h>
20 #define FLASH_BASE 0x40000000
21 #define FASZR (FLASH_BASE + 0x000)
22 #define DFCTRLR (FLASH_BASE + 0x030)
23 #define DFCTRLR_DFE (1UL << 0)
25 #define WDG_BASE 0x40011000
26 #define WDG_CTL (WDG_BASE + 0x008)
27 #define WDG_LCK (WDG_BASE + 0xC00)
41 struct fm4_flash_bank
{
42 enum fm4_variant variant
;
47 static int fm4_disable_hw_watchdog(struct target
*target
)
51 retval
= target_write_u32(target
, WDG_LCK
, 0x1ACCE551);
52 if (retval
!= ERROR_OK
)
55 retval
= target_write_u32(target
, WDG_LCK
, 0xE5331AAE);
56 if (retval
!= ERROR_OK
)
59 retval
= target_write_u32(target
, WDG_CTL
, 0);
60 if (retval
!= ERROR_OK
)
66 static int fm4_enter_flash_cpu_programming_mode(struct target
*target
)
71 /* FASZR ASZ = CPU programming mode */
72 retval
= target_write_u32(target
, FASZR
, 0x00000001);
73 if (retval
!= ERROR_OK
)
75 retval
= target_read_u32(target
, FASZR
, &u32_value
);
76 if (retval
!= ERROR_OK
)
82 static int fm4_enter_flash_cpu_rom_mode(struct target
*target
)
87 /* FASZR ASZ = CPU ROM mode */
88 retval
= target_write_u32(target
, FASZR
, 0x00000002);
89 if (retval
!= ERROR_OK
)
91 retval
= target_read_u32(target
, FASZR
, &u32_value
);
92 if (retval
!= ERROR_OK
)
98 static int fm4_flash_erase(struct flash_bank
*bank
, int first
, int last
)
100 struct target
*target
= bank
->target
;
101 struct working_area
*workarea
;
102 struct reg_param reg_params
[4];
103 struct armv7m_algorithm armv7m_algo
;
106 const uint8_t erase_sector_code
[] = {
107 #include "../../../contrib/loaders/flash/fm4/erase.inc"
110 if (target
->state
!= TARGET_HALTED
) {
111 LOG_WARNING("Cannot communicate... target not halted.");
112 return ERROR_TARGET_NOT_HALTED
;
115 LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first
, last
);
117 retval
= fm4_disable_hw_watchdog(target
);
118 if (retval
!= ERROR_OK
)
121 retval
= fm4_enter_flash_cpu_programming_mode(target
);
122 if (retval
!= ERROR_OK
)
125 retval
= target_alloc_working_area(target
, sizeof(erase_sector_code
),
127 if (retval
!= ERROR_OK
) {
128 LOG_ERROR("No working area available.");
129 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
132 retval
= target_write_buffer(target
, workarea
->address
,
133 sizeof(erase_sector_code
), erase_sector_code
);
134 if (retval
!= ERROR_OK
)
137 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
138 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
140 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
141 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
142 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
143 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
145 for (sector
= first
; sector
<= last
; sector
++) {
146 uint32_t addr
= bank
->base
+ bank
->sectors
[sector
].offset
;
149 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
150 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
151 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
153 retval
= target_run_algorithm(target
,
155 ARRAY_SIZE(reg_params
), reg_params
,
156 workarea
->address
, 0,
158 if (retval
!= ERROR_OK
) {
159 LOG_ERROR("Error executing flash sector erase "
160 "programming algorithm");
161 retval
= ERROR_FLASH_OPERATION_FAILED
;
165 result
= buf_get_u32(reg_params
[3].value
, 0, 32);
167 LOG_ERROR("Timeout error from flash sector erase programming algorithm");
168 retval
= ERROR_FLASH_OPERATION_FAILED
;
170 } else if (result
!= 0) {
171 LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result
);
172 retval
= ERROR_FLASH_OPERATION_FAILED
;
177 bank
->sectors
[sector
].is_erased
= 1;
182 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
183 destroy_reg_param(®_params
[i
]);
186 target_free_working_area(target
, workarea
);
189 if (retval
!= ERROR_OK
)
190 fm4_enter_flash_cpu_rom_mode(target
);
192 retval
= fm4_enter_flash_cpu_rom_mode(target
);
197 static int fm4_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
198 uint32_t offset
, uint32_t byte_count
)
200 struct target
*target
= bank
->target
;
201 struct working_area
*code_workarea
, *data_workarea
;
202 struct reg_param reg_params
[6];
203 struct armv7m_algorithm armv7m_algo
;
204 uint32_t halfword_count
= DIV_ROUND_UP(byte_count
, 2);
208 const uint8_t write_block_code
[] = {
209 #include "../../../contrib/loaders/flash/fm4/write.inc"
212 LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32
" (%" PRId32
" bytes)",
216 LOG_ERROR("offset 0x%" PRIx32
" breaks required 2-byte alignment",
218 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
220 if (byte_count
& 0x1) {
221 LOG_WARNING("length %" PRId32
" is not 2-byte aligned, rounding up",
225 if (target
->state
!= TARGET_HALTED
) {
226 LOG_WARNING("Cannot communicate... target not halted.");
227 return ERROR_TARGET_NOT_HALTED
;
230 retval
= fm4_disable_hw_watchdog(target
);
231 if (retval
!= ERROR_OK
)
234 retval
= target_alloc_working_area(target
, sizeof(write_block_code
),
236 if (retval
!= ERROR_OK
) {
237 LOG_ERROR("No working area available for write code.");
238 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
240 retval
= target_write_buffer(target
, code_workarea
->address
,
241 sizeof(write_block_code
), write_block_code
);
242 if (retval
!= ERROR_OK
)
245 retval
= target_alloc_working_area(target
,
246 MIN(halfword_count
* 2, target_get_working_area_avail(target
)),
248 if (retval
!= ERROR_OK
) {
249 LOG_ERROR("No working area available for write data.");
250 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
254 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
255 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
257 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
258 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
259 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
260 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
261 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
);
262 init_reg_param(®_params
[5], "r5", 32, PARAM_IN
);
264 retval
= fm4_enter_flash_cpu_programming_mode(target
);
265 if (retval
!= ERROR_OK
)
268 while (byte_count
> 0) {
269 uint32_t halfwords
= MIN(halfword_count
, data_workarea
->size
/ 2);
270 uint32_t addr
= bank
->base
+ offset
;
272 LOG_DEBUG("copying %" PRId32
" bytes to SRAM 0x%08" PRIx32
,
273 MIN(halfwords
* 2, byte_count
), data_workarea
->address
);
275 retval
= target_write_buffer(target
, data_workarea
->address
,
276 MIN(halfwords
* 2, byte_count
), buffer
);
277 if (retval
!= ERROR_OK
) {
278 LOG_ERROR("Error writing data buffer");
279 retval
= ERROR_FLASH_OPERATION_FAILED
;
283 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRId32
"x)",
284 addr
, addr
+ halfwords
* 2 - 1, halfwords
);
286 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
287 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
288 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
289 buf_set_u32(reg_params
[3].value
, 0, 32, data_workarea
->address
);
290 buf_set_u32(reg_params
[4].value
, 0, 32, halfwords
);
292 retval
= target_run_algorithm(target
,
294 ARRAY_SIZE(reg_params
), reg_params
,
295 code_workarea
->address
, 0,
296 5 * 60 * 1000, &armv7m_algo
);
297 if (retval
!= ERROR_OK
) {
298 LOG_ERROR("Error executing flash sector erase "
299 "programming algorithm");
300 retval
= ERROR_FLASH_OPERATION_FAILED
;
304 result
= buf_get_u32(reg_params
[5].value
, 0, 32);
306 LOG_ERROR("Timeout error from flash write "
307 "programming algorithm");
308 retval
= ERROR_FLASH_OPERATION_FAILED
;
310 } else if (result
!= 0) {
311 LOG_ERROR("Unexpected error %d from flash write "
312 "programming algorithm", result
);
313 retval
= ERROR_FLASH_OPERATION_FAILED
;
318 halfword_count
-= halfwords
;
319 offset
+= halfwords
* 2;
320 buffer
+= halfwords
* 2;
321 byte_count
-= MIN(halfwords
* 2, byte_count
);
327 retval
= fm4_enter_flash_cpu_rom_mode(target
);
330 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
331 destroy_reg_param(®_params
[i
]);
333 target_free_working_area(target
, data_workarea
);
336 target_free_working_area(target
, code_workarea
);
341 static int mb9bf_probe(struct flash_bank
*bank
)
343 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
344 uint32_t flash_addr
= bank
->base
;
347 switch (fm4_bank
->variant
) {
349 bank
->num_sectors
= 8;
352 bank
->num_sectors
= 10;
355 bank
->num_sectors
= 12;
358 bank
->num_sectors
= 16;
361 bank
->num_sectors
= 20;
364 return ERROR_FLASH_OPER_UNSUPPORTED
;
367 LOG_DEBUG("%d sectors", bank
->num_sectors
);
368 bank
->sectors
= calloc(bank
->num_sectors
,
369 sizeof(struct flash_sector
));
370 for (i
= 0; i
< bank
->num_sectors
; i
++) {
372 bank
->sectors
[i
].size
= 8 * 1024;
374 bank
->sectors
[i
].size
= 32 * 1024;
376 bank
->sectors
[i
].size
= 64 * 1024;
377 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
378 bank
->sectors
[i
].is_erased
= -1;
379 bank
->sectors
[i
].is_protected
= -1;
381 bank
->size
+= bank
->sectors
[i
].size
;
382 flash_addr
+= bank
->sectors
[i
].size
;
388 static void s6e2cc_init_sector(struct flash_sector
*sector
, int sa
)
391 sector
->size
= 8 * 1024;
393 sector
->size
= 32 * 1024;
395 sector
->size
= 64 * 1024;
397 sector
->is_erased
= -1;
398 sector
->is_protected
= -1;
401 static int s6e2cc_probe(struct flash_bank
*bank
)
403 struct target
*target
= bank
->target
;
404 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
406 uint32_t flash_addr
= bank
->base
;
407 int i
, retval
, num_sectors
, num_extra_sectors
;
409 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
410 if (retval
!= ERROR_OK
)
412 if (u32_value
& DFCTRLR_DFE
) {
413 LOG_WARNING("Dual Flash mode is not implemented.");
414 return ERROR_FLASH_OPER_UNSUPPORTED
;
417 switch (fm4_bank
->variant
) {
419 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
422 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
428 return ERROR_FLASH_OPER_UNSUPPORTED
;
430 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
431 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
433 LOG_DEBUG("%d sectors", bank
->num_sectors
);
434 bank
->sectors
= calloc(bank
->num_sectors
,
435 sizeof(struct flash_sector
));
436 for (i
= 0; i
< num_sectors
; i
++) {
438 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
439 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
441 bank
->size
+= bank
->sectors
[i
].size
;
442 flash_addr
+= bank
->sectors
[i
].size
;
445 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
446 for (; i
< bank
->num_sectors
; i
++) {
447 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
448 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
449 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
452 * Don't increase bank->size for these sectors
453 * to avoid an overlap between Flash Macros #0 and #1.
455 flash_addr
+= bank
->sectors
[i
].size
;
461 static int fm4_probe(struct flash_bank
*bank
)
463 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
466 if (fm4_bank
->probed
)
469 if (bank
->target
->state
!= TARGET_HALTED
) {
470 LOG_WARNING("Cannot communicate... target not halted.");
471 return ERROR_TARGET_NOT_HALTED
;
474 switch (fm4_bank
->variant
) {
480 retval
= mb9bf_probe(bank
);
485 retval
= s6e2cc_probe(bank
);
488 return ERROR_FLASH_OPER_UNSUPPORTED
;
490 if (retval
!= ERROR_OK
)
493 fm4_bank
->probed
= true;
498 static int fm4_auto_probe(struct flash_bank
*bank
)
500 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
502 if (fm4_bank
->probed
)
505 return fm4_probe(bank
);
508 static int fm4_protect_check(struct flash_bank
*bank
)
513 static int fm4_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
515 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
518 if (bank
->target
->state
!= TARGET_HALTED
) {
519 LOG_WARNING("Cannot communicate... target not halted.");
520 return ERROR_TARGET_NOT_HALTED
;
523 switch (fm4_bank
->variant
) {
553 switch (fm4_bank
->variant
) {
557 snprintf(buf
, buf_size
, "%s MainFlash Macro #%i",
558 name
, fm4_bank
->macro_nr
);
561 snprintf(buf
, buf_size
, "%s MainFlash", name
);
568 static bool fm4_name_match(const char *s
, const char *pattern
)
573 /* If the match string is shorter, ignore excess */
576 /* Use x as wildcard */
577 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
584 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
586 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
588 if (fm4_name_match(variant
, "MB9BFx64")) {
589 fm4_bank
->variant
= mb9bfx64
;
590 } else if (fm4_name_match(variant
, "MB9BFx65")) {
591 fm4_bank
->variant
= mb9bfx65
;
592 } else if (fm4_name_match(variant
, "MB9BFx66")) {
593 fm4_bank
->variant
= mb9bfx66
;
594 } else if (fm4_name_match(variant
, "MB9BFx67")) {
595 fm4_bank
->variant
= mb9bfx67
;
596 } else if (fm4_name_match(variant
, "MB9BFx68")) {
597 fm4_bank
->variant
= mb9bfx68
;
599 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
600 return ERROR_FLASH_OPER_UNSUPPORTED
;
606 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
608 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
610 if (fm4_name_match(variant
, "S6E2Cx8")) {
611 fm4_bank
->variant
= s6e2cx8
;
612 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
613 fm4_bank
->variant
= s6e2cx9
;
614 } else if (fm4_name_match(variant
, "S6E2CxA")) {
615 fm4_bank
->variant
= s6e2cxa
;
617 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
618 return ERROR_FLASH_OPER_UNSUPPORTED
;
624 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
626 struct fm4_flash_bank
*fm4_bank
;
631 return ERROR_COMMAND_SYNTAX_ERROR
;
633 variant
= CMD_ARGV
[6];
635 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
637 return ERROR_FLASH_OPERATION_FAILED
;
639 fm4_bank
->probed
= false;
640 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
642 bank
->driver_priv
= fm4_bank
;
644 if (fm4_name_match(variant
, "MB9BF"))
645 ret
= mb9bf_bank_setup(bank
, variant
);
646 else if (fm4_name_match(variant
, "S6E2Cx"))
647 ret
= s6e2cc_bank_setup(bank
, variant
);
649 LOG_WARNING("Family %s not recognized.", variant
);
650 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
657 static const struct command_registration fm4_exec_command_handlers
[] = {
658 COMMAND_REGISTRATION_DONE
661 static const struct command_registration fm4_command_handlers
[] = {
665 .help
= "fm4 flash command group",
667 .chain
= fm4_exec_command_handlers
,
669 COMMAND_REGISTRATION_DONE
672 struct flash_driver fm4_flash
= {
674 .commands
= fm4_command_handlers
,
675 .flash_bank_command
= fm4_flash_bank_command
,
676 .info
= fm4_get_info_command
,
678 .auto_probe
= fm4_auto_probe
,
679 .protect_check
= fm4_protect_check
,
680 .erase
= fm4_flash_erase
,
681 .erase_check
= default_flash_blank_check
,
682 .write
= fm4_flash_write
,
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)