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
15 #include <helper/binarybuffer.h>
16 #include <target/algorithm.h>
17 #include <target/armv7m.h>
19 #define FLASH_BASE 0x40000000
20 #define FASZR (FLASH_BASE + 0x000)
21 #define DFCTRLR (FLASH_BASE + 0x030)
22 #define DFCTRLR_DFE (1UL << 0)
24 #define WDG_BASE 0x40011000
25 #define WDG_CTL (WDG_BASE + 0x008)
26 #define WDG_LCK (WDG_BASE + 0xC00)
38 struct fm4_flash_bank
{
39 enum fm4_variant variant
;
44 static int fm4_disable_hw_watchdog(struct target
*target
)
48 retval
= target_write_u32(target
, WDG_LCK
, 0x1ACCE551);
49 if (retval
!= ERROR_OK
)
52 retval
= target_write_u32(target
, WDG_LCK
, 0xE5331AAE);
53 if (retval
!= ERROR_OK
)
56 retval
= target_write_u32(target
, WDG_CTL
, 0);
57 if (retval
!= ERROR_OK
)
63 static int fm4_enter_flash_cpu_programming_mode(struct target
*target
)
68 /* FASZR ASZ = CPU programming mode */
69 retval
= target_write_u32(target
, FASZR
, 0x00000001);
70 if (retval
!= ERROR_OK
)
72 retval
= target_read_u32(target
, FASZR
, &u32_value
);
73 if (retval
!= ERROR_OK
)
79 static int fm4_enter_flash_cpu_rom_mode(struct target
*target
)
84 /* FASZR ASZ = CPU ROM mode */
85 retval
= target_write_u32(target
, FASZR
, 0x00000002);
86 if (retval
!= ERROR_OK
)
88 retval
= target_read_u32(target
, FASZR
, &u32_value
);
89 if (retval
!= ERROR_OK
)
95 static int fm4_flash_erase(struct flash_bank
*bank
, int first
, int last
)
97 struct target
*target
= bank
->target
;
98 struct working_area
*workarea
;
99 struct reg_param reg_params
[4];
100 struct armv7m_algorithm armv7m_algo
;
103 const uint8_t erase_sector_code
[] = {
104 #include "../../../contrib/loaders/flash/fm4/erase.inc"
107 if (target
->state
!= TARGET_HALTED
) {
108 LOG_WARNING("Cannot communicate... target not halted.");
109 return ERROR_TARGET_NOT_HALTED
;
112 LOG_DEBUG("Spansion FM4 erase sectors %d to %d", first
, last
);
114 retval
= fm4_disable_hw_watchdog(target
);
115 if (retval
!= ERROR_OK
)
118 retval
= fm4_enter_flash_cpu_programming_mode(target
);
119 if (retval
!= ERROR_OK
)
122 retval
= target_alloc_working_area(target
, sizeof(erase_sector_code
),
124 if (retval
!= ERROR_OK
) {
125 LOG_ERROR("No working area available.");
126 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
129 retval
= target_write_buffer(target
, workarea
->address
,
130 sizeof(erase_sector_code
), erase_sector_code
);
131 if (retval
!= ERROR_OK
)
134 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
135 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
137 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
138 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
139 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
140 init_reg_param(®_params
[3], "r3", 32, PARAM_IN
);
142 for (sector
= first
; sector
<= last
; sector
++) {
143 uint32_t addr
= bank
->base
+ bank
->sectors
[sector
].offset
;
146 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
147 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
148 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
150 retval
= target_run_algorithm(target
,
152 ARRAY_SIZE(reg_params
), reg_params
,
153 workarea
->address
, 0,
155 if (retval
!= ERROR_OK
) {
156 LOG_ERROR("Error executing flash sector erase "
157 "programming algorithm");
158 retval
= ERROR_FLASH_OPERATION_FAILED
;
162 result
= buf_get_u32(reg_params
[3].value
, 0, 32);
164 LOG_ERROR("Timeout error from flash sector erase programming algorithm");
165 retval
= ERROR_FLASH_OPERATION_FAILED
;
167 } else if (result
!= 0) {
168 LOG_ERROR("Unexpected error %d from flash sector erase programming algorithm", result
);
169 retval
= ERROR_FLASH_OPERATION_FAILED
;
174 bank
->sectors
[sector
].is_erased
= 1;
179 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
180 destroy_reg_param(®_params
[i
]);
183 target_free_working_area(target
, workarea
);
186 if (retval
!= ERROR_OK
)
187 fm4_enter_flash_cpu_rom_mode(target
);
189 retval
= fm4_enter_flash_cpu_rom_mode(target
);
194 static int fm4_flash_write(struct flash_bank
*bank
, const uint8_t *buffer
,
195 uint32_t offset
, uint32_t byte_count
)
197 struct target
*target
= bank
->target
;
198 struct working_area
*code_workarea
, *data_workarea
;
199 struct reg_param reg_params
[6];
200 struct armv7m_algorithm armv7m_algo
;
201 uint32_t halfword_count
= DIV_ROUND_UP(byte_count
, 2);
205 const uint8_t write_block_code
[] = {
206 #include "../../../contrib/loaders/flash/fm4/write.inc"
209 LOG_DEBUG("Spansion FM4 write at 0x%08" PRIx32
" (%" PRId32
" bytes)",
213 LOG_ERROR("offset 0x%" PRIx32
" breaks required 2-byte alignment",
215 return ERROR_FLASH_DST_BREAKS_ALIGNMENT
;
217 if (byte_count
& 0x1) {
218 LOG_WARNING("length %" PRId32
" is not 2-byte aligned, rounding up",
222 if (target
->state
!= TARGET_HALTED
) {
223 LOG_WARNING("Cannot communicate... target not halted.");
224 return ERROR_TARGET_NOT_HALTED
;
227 retval
= fm4_disable_hw_watchdog(target
);
228 if (retval
!= ERROR_OK
)
231 retval
= target_alloc_working_area(target
, sizeof(write_block_code
),
233 if (retval
!= ERROR_OK
) {
234 LOG_ERROR("No working area available for write code.");
235 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
237 retval
= target_write_buffer(target
, code_workarea
->address
,
238 sizeof(write_block_code
), write_block_code
);
239 if (retval
!= ERROR_OK
)
242 retval
= target_alloc_working_area(target
,
243 MIN(halfword_count
* 2, target_get_working_area_avail(target
)),
245 if (retval
!= ERROR_OK
) {
246 LOG_ERROR("No working area available for write data.");
247 retval
= ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
251 armv7m_algo
.common_magic
= ARMV7M_COMMON_MAGIC
;
252 armv7m_algo
.core_mode
= ARM_MODE_THREAD
;
254 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
255 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
256 init_reg_param(®_params
[2], "r2", 32, PARAM_OUT
);
257 init_reg_param(®_params
[3], "r3", 32, PARAM_OUT
);
258 init_reg_param(®_params
[4], "r4", 32, PARAM_OUT
);
259 init_reg_param(®_params
[5], "r5", 32, PARAM_IN
);
261 retval
= fm4_enter_flash_cpu_programming_mode(target
);
262 if (retval
!= ERROR_OK
)
265 while (byte_count
> 0) {
266 uint32_t halfwords
= MIN(halfword_count
, data_workarea
->size
/ 2);
267 uint32_t addr
= bank
->base
+ offset
;
269 LOG_DEBUG("copying %" PRId32
" bytes to SRAM 0x%08" PRIx32
,
270 MIN(halfwords
* 2, byte_count
), data_workarea
->address
);
272 retval
= target_write_buffer(target
, data_workarea
->address
,
273 MIN(halfwords
* 2, byte_count
), buffer
);
274 if (retval
!= ERROR_OK
) {
275 LOG_ERROR("Error writing data buffer");
276 retval
= ERROR_FLASH_OPERATION_FAILED
;
280 LOG_DEBUG("writing 0x%08" PRIx32
"-0x%08" PRIx32
" (%" PRId32
"x)",
281 addr
, addr
+ halfwords
* 2 - 1, halfwords
);
283 buf_set_u32(reg_params
[0].value
, 0, 32, (addr
& ~0xffff) | 0xAA8);
284 buf_set_u32(reg_params
[1].value
, 0, 32, (addr
& ~0xffff) | 0x554);
285 buf_set_u32(reg_params
[2].value
, 0, 32, addr
);
286 buf_set_u32(reg_params
[3].value
, 0, 32, data_workarea
->address
);
287 buf_set_u32(reg_params
[4].value
, 0, 32, halfwords
);
289 retval
= target_run_algorithm(target
,
291 ARRAY_SIZE(reg_params
), reg_params
,
292 code_workarea
->address
, 0,
293 5 * 60 * 1000, &armv7m_algo
);
294 if (retval
!= ERROR_OK
) {
295 LOG_ERROR("Error executing flash sector erase "
296 "programming algorithm");
297 retval
= ERROR_FLASH_OPERATION_FAILED
;
301 result
= buf_get_u32(reg_params
[5].value
, 0, 32);
303 LOG_ERROR("Timeout error from flash write "
304 "programming algorithm");
305 retval
= ERROR_FLASH_OPERATION_FAILED
;
307 } else if (result
!= 0) {
308 LOG_ERROR("Unexpected error %d from flash write "
309 "programming algorithm", result
);
310 retval
= ERROR_FLASH_OPERATION_FAILED
;
315 halfword_count
-= halfwords
;
316 offset
+= halfwords
* 2;
317 buffer
+= halfwords
* 2;
318 byte_count
-= MIN(halfwords
* 2, byte_count
);
324 retval
= fm4_enter_flash_cpu_rom_mode(target
);
327 for (i
= 0; i
< ARRAY_SIZE(reg_params
); i
++)
328 destroy_reg_param(®_params
[i
]);
330 target_free_working_area(target
, data_workarea
);
333 target_free_working_area(target
, code_workarea
);
338 static int mb9bf_probe(struct flash_bank
*bank
)
340 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
341 uint32_t flash_addr
= bank
->base
;
344 switch (fm4_bank
->variant
) {
346 bank
->num_sectors
= 12;
349 bank
->num_sectors
= 16;
352 bank
->num_sectors
= 20;
355 return ERROR_FLASH_OPER_UNSUPPORTED
;
358 LOG_DEBUG("%d sectors", bank
->num_sectors
);
359 bank
->sectors
= calloc(bank
->num_sectors
,
360 sizeof(struct flash_sector
));
361 for (i
= 0; i
< bank
->num_sectors
; i
++) {
363 bank
->sectors
[i
].size
= 8 * 1024;
365 bank
->sectors
[i
].size
= 32 * 1024;
367 bank
->sectors
[i
].size
= 64 * 1024;
368 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
369 bank
->sectors
[i
].is_erased
= -1;
370 bank
->sectors
[i
].is_protected
= -1;
372 bank
->size
+= bank
->sectors
[i
].size
;
373 flash_addr
+= bank
->sectors
[i
].size
;
379 static void s6e2cc_init_sector(struct flash_sector
*sector
, int sa
)
382 sector
->size
= 8 * 1024;
384 sector
->size
= 32 * 1024;
386 sector
->size
= 64 * 1024;
388 sector
->is_erased
= -1;
389 sector
->is_protected
= -1;
392 static int s6e2cc_probe(struct flash_bank
*bank
)
394 struct target
*target
= bank
->target
;
395 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
397 uint32_t flash_addr
= bank
->base
;
398 int i
, retval
, num_sectors
, num_extra_sectors
;
400 retval
= target_read_u32(target
, DFCTRLR
, &u32_value
);
401 if (retval
!= ERROR_OK
)
403 if (u32_value
& DFCTRLR_DFE
) {
404 LOG_WARNING("Dual Flash mode is not implemented.");
405 return ERROR_FLASH_OPER_UNSUPPORTED
;
408 switch (fm4_bank
->variant
) {
410 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 0;
413 num_sectors
= (fm4_bank
->macro_nr
== 0) ? 20 : 12;
419 return ERROR_FLASH_OPER_UNSUPPORTED
;
421 num_extra_sectors
= (fm4_bank
->macro_nr
== 0) ? 1 : 4;
422 bank
->num_sectors
= num_sectors
+ num_extra_sectors
;
424 LOG_DEBUG("%d sectors", bank
->num_sectors
);
425 bank
->sectors
= calloc(bank
->num_sectors
,
426 sizeof(struct flash_sector
));
427 for (i
= 0; i
< num_sectors
; i
++) {
429 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
430 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
432 bank
->size
+= bank
->sectors
[i
].size
;
433 flash_addr
+= bank
->sectors
[i
].size
;
436 flash_addr
= (fm4_bank
->macro_nr
== 0) ? 0x00406000 : 0x00408000;
437 for (; i
< bank
->num_sectors
; i
++) {
438 int sa
= 4 - num_extra_sectors
+ (i
- num_sectors
);
439 bank
->sectors
[i
].offset
= flash_addr
- bank
->base
;
440 s6e2cc_init_sector(&bank
->sectors
[i
], sa
);
443 * Don't increase bank->size for these sectors
444 * to avoid an overlap between Flash Macros #0 and #1.
446 flash_addr
+= bank
->sectors
[i
].size
;
452 static int fm4_probe(struct flash_bank
*bank
)
454 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
457 if (fm4_bank
->probed
)
460 if (bank
->target
->state
!= TARGET_HALTED
) {
461 LOG_WARNING("Cannot communicate... target not halted.");
462 return ERROR_TARGET_NOT_HALTED
;
465 switch (fm4_bank
->variant
) {
469 retval
= mb9bf_probe(bank
);
474 retval
= s6e2cc_probe(bank
);
477 return ERROR_FLASH_OPER_UNSUPPORTED
;
479 if (retval
!= ERROR_OK
)
482 fm4_bank
->probed
= true;
487 static int fm4_auto_probe(struct flash_bank
*bank
)
489 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
491 if (fm4_bank
->probed
)
494 return fm4_probe(bank
);
497 static int fm4_protect_check(struct flash_bank
*bank
)
502 static int fm4_get_info_command(struct flash_bank
*bank
, char *buf
, int buf_size
)
504 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
507 if (bank
->target
->state
!= TARGET_HALTED
) {
508 LOG_WARNING("Cannot communicate... target not halted.");
509 return ERROR_TARGET_NOT_HALTED
;
512 switch (fm4_bank
->variant
) {
536 switch (fm4_bank
->variant
) {
540 snprintf(buf
, buf_size
, "%s MainFlash Macro #%i",
541 name
, fm4_bank
->macro_nr
);
544 snprintf(buf
, buf_size
, "%s MainFlash", name
);
551 static bool fm4_name_match(const char *s
, const char *pattern
)
556 /* If the match string is shorter, ignore excess */
559 /* Use x as wildcard */
560 if (pattern
[i
] != 'x' && tolower(s
[i
]) != tolower(pattern
[i
]))
567 static int mb9bf_bank_setup(struct flash_bank
*bank
, const char *variant
)
569 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
571 if (fm4_name_match(variant
, "MB9BFx66")) {
572 fm4_bank
->variant
= mb9bfx66
;
573 } else if (fm4_name_match(variant
, "MB9BFx67")) {
574 fm4_bank
->variant
= mb9bfx67
;
575 } else if (fm4_name_match(variant
, "MB9BFx68")) {
576 fm4_bank
->variant
= mb9bfx68
;
578 LOG_WARNING("MB9BF variant %s not recognized.", variant
);
579 return ERROR_FLASH_OPER_UNSUPPORTED
;
585 static int s6e2cc_bank_setup(struct flash_bank
*bank
, const char *variant
)
587 struct fm4_flash_bank
*fm4_bank
= bank
->driver_priv
;
589 if (fm4_name_match(variant
, "S6E2Cx8")) {
590 fm4_bank
->variant
= s6e2cx8
;
591 } else if (fm4_name_match(variant
, "S6E2Cx9")) {
592 fm4_bank
->variant
= s6e2cx9
;
593 } else if (fm4_name_match(variant
, "S6E2CxA")) {
594 fm4_bank
->variant
= s6e2cxa
;
596 LOG_WARNING("S6E2CC variant %s not recognized.", variant
);
597 return ERROR_FLASH_OPER_UNSUPPORTED
;
603 FLASH_BANK_COMMAND_HANDLER(fm4_flash_bank_command
)
605 struct fm4_flash_bank
*fm4_bank
;
610 return ERROR_COMMAND_SYNTAX_ERROR
;
612 variant
= CMD_ARGV
[6];
614 fm4_bank
= malloc(sizeof(struct fm4_flash_bank
));
616 return ERROR_FLASH_OPERATION_FAILED
;
618 fm4_bank
->probed
= false;
619 fm4_bank
->macro_nr
= (bank
->base
== 0x00000000) ? 0 : 1;
621 bank
->driver_priv
= fm4_bank
;
623 if (fm4_name_match(variant
, "MB9BF"))
624 ret
= mb9bf_bank_setup(bank
, variant
);
625 else if (fm4_name_match(variant
, "S6E2Cx"))
626 ret
= s6e2cc_bank_setup(bank
, variant
);
628 LOG_WARNING("Family %s not recognized.", variant
);
629 ret
= ERROR_FLASH_OPER_UNSUPPORTED
;
636 static const struct command_registration fm4_exec_command_handlers
[] = {
637 COMMAND_REGISTRATION_DONE
640 static const struct command_registration fm4_command_handlers
[] = {
644 .help
= "fm4 flash command group",
646 .chain
= fm4_exec_command_handlers
,
648 COMMAND_REGISTRATION_DONE
651 struct flash_driver fm4_flash
= {
653 .commands
= fm4_command_handlers
,
654 .flash_bank_command
= fm4_flash_bank_command
,
655 .info
= fm4_get_info_command
,
657 .auto_probe
= fm4_auto_probe
,
658 .protect_check
= fm4_protect_check
,
659 .erase
= fm4_flash_erase
,
660 .erase_check
= default_flash_blank_check
,
661 .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)