fm3: add Fujitsu MB9Ax family support
[openocd.git] / src / flash / nor / fm3.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Marc Willam, Holger Wech *
3 * openOCD.fseu(AT)de.fujitsu.com *
4 * Copyright (C) 2011 Ronny Strutz *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
20 ***************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "imp.h"
27 #include <helper/binarybuffer.h>
28 #include <target/algorithm.h>
29 #include <target/armv7m.h>
30
31 #define FLASH_DQ6 0x00000040 /* Data toggle flag bit (TOGG) position */
32 #define FLASH_DQ5 0x00000020 /* Time limit exceeding flag bit (TLOV) position */
33
34 enum fm3_variant {
35 mb9bfxx1, /* Flash Type '1' */
36 mb9bfxx2,
37 mb9bfxx3,
38 mb9bfxx4,
39 mb9bfxx5,
40 mb9bfxx6,
41 mb9bfxx7,
42 mb9bfxx8,
43
44 mb9afxx1, /* Flash Type '2' */
45 mb9afxx2,
46 mb9afxx3,
47 mb9afxx4,
48 mb9afxx5,
49 mb9afxx6,
50 mb9afxx7,
51 mb9afxx8,
52 };
53
54 enum fm3_flash_type {
55 fm3_no_flash_type = 0,
56 fm3_flash_type1 = 1,
57 fm3_flash_type2 = 2
58 };
59
60 struct fm3_flash_bank {
61 enum fm3_variant variant;
62 enum fm3_flash_type flashtype;
63 int probed;
64 };
65
66 FLASH_BANK_COMMAND_HANDLER(fm3_flash_bank_command)
67 {
68 struct fm3_flash_bank *fm3_info;
69
70 if (CMD_ARGC < 6)
71 return ERROR_COMMAND_SYNTAX_ERROR;
72
73 fm3_info = malloc(sizeof(struct fm3_flash_bank));
74 bank->driver_priv = fm3_info;
75
76 /* Flash type '1' */
77 if (strcmp(CMD_ARGV[5], "mb9bfxx1.cpu") == 0) {
78 fm3_info->variant = mb9bfxx1;
79 fm3_info->flashtype = fm3_flash_type1;
80 } else if (strcmp(CMD_ARGV[5], "mb9bfxx2.cpu") == 0) {
81 fm3_info->variant = mb9bfxx2;
82 fm3_info->flashtype = fm3_flash_type1;
83 } else if (strcmp(CMD_ARGV[5], "mb9bfxx3.cpu") == 0) {
84 fm3_info->variant = mb9bfxx3;
85 fm3_info->flashtype = fm3_flash_type1;
86 } else if (strcmp(CMD_ARGV[5], "mb9bfxx4.cpu") == 0) {
87 fm3_info->variant = mb9bfxx4;
88 fm3_info->flashtype = fm3_flash_type1;
89 } else if (strcmp(CMD_ARGV[5], "mb9bfxx5.cpu") == 0) {
90 fm3_info->variant = mb9bfxx5;
91 fm3_info->flashtype = fm3_flash_type1;
92 } else if (strcmp(CMD_ARGV[5], "mb9bfxx6.cpu") == 0) {
93 fm3_info->variant = mb9bfxx6;
94 fm3_info->flashtype = fm3_flash_type1;
95 } else if (strcmp(CMD_ARGV[5], "mb9bfxx7.cpu") == 0) {
96 fm3_info->variant = mb9bfxx7;
97 fm3_info->flashtype = fm3_flash_type1;
98 } else if (strcmp(CMD_ARGV[5], "mb9bfxx8.cpu") == 0) {
99 fm3_info->variant = mb9bfxx8;
100 fm3_info->flashtype = fm3_flash_type1;
101 } else if (strcmp(CMD_ARGV[5], "mb9afxx1.cpu") == 0) { /* Flash type '2' */
102 fm3_info->variant = mb9afxx1;
103 fm3_info->flashtype = fm3_flash_type2;
104 } else if (strcmp(CMD_ARGV[5], "mb9afxx2.cpu") == 0) {
105 fm3_info->variant = mb9afxx2;
106 fm3_info->flashtype = fm3_flash_type2;
107 } else if (strcmp(CMD_ARGV[5], "mb9afxx3.cpu") == 0) {
108 fm3_info->variant = mb9afxx3;
109 fm3_info->flashtype = fm3_flash_type2;
110 } else if (strcmp(CMD_ARGV[5], "mb9afxx4.cpu") == 0) {
111 fm3_info->variant = mb9afxx4;
112 fm3_info->flashtype = fm3_flash_type2;
113 } else if (strcmp(CMD_ARGV[5], "mb9afxx5.cpu") == 0) {
114 fm3_info->variant = mb9afxx5;
115 fm3_info->flashtype = fm3_flash_type2;
116 } else if (strcmp(CMD_ARGV[5], "mb9afxx6.cpu") == 0) {
117 fm3_info->variant = mb9afxx6;
118 fm3_info->flashtype = fm3_flash_type2;
119 } else if (strcmp(CMD_ARGV[5], "mb9afxx7.cpu") == 0) {
120 fm3_info->variant = mb9afxx7;
121 fm3_info->flashtype = fm3_flash_type2;
122 } else if (strcmp(CMD_ARGV[5], "mb9afxx8.cpu") == 0) {
123 fm3_info->variant = mb9afxx8;
124 fm3_info->flashtype = fm3_flash_type2;
125 }
126
127 /* unknown Flash type */
128 else {
129 LOG_ERROR("unknown fm3 variant: %s", CMD_ARGV[5]);
130 free(fm3_info);
131 return ERROR_FLASH_BANK_INVALID;
132 }
133
134 fm3_info->probed = 0;
135
136 return ERROR_OK;
137 }
138
139 /* Data polling algorithm */
140 static int fm3_busy_wait(struct target *target, uint32_t offset, int timeout_ms)
141 {
142 int retval = ERROR_OK;
143 uint16_t state1, state2;
144 int ms = 0;
145
146 /* While(1) loop exit via "break" and "return" on error */
147 while (1) {
148 /* dummy-read - see flash manual */
149 retval = target_read_u16(target, offset, &state1);
150 if (retval != ERROR_OK)
151 return retval;
152
153 /* Data polling 1 */
154 retval = target_read_u16(target, offset, &state1);
155 if (retval != ERROR_OK)
156 return retval;
157
158 /* Data polling 2 */
159 retval = target_read_u16(target, offset, &state2);
160 if (retval != ERROR_OK)
161 return retval;
162
163 /* Flash command finished via polled data equal? */
164 if ((state1 & FLASH_DQ6) == (state2 & FLASH_DQ6))
165 break;
166 /* Timeout Flag? */
167 else if (state1 & FLASH_DQ5) {
168 /* Retry data polling */
169
170 /* Data polling 1 */
171 retval = target_read_u16(target, offset, &state1);
172 if (retval != ERROR_OK)
173 return retval;
174
175 /* Data polling 2 */
176 retval = target_read_u16(target, offset, &state2);
177 if (retval != ERROR_OK)
178 return retval;
179
180 /* Flash command finished via polled data equal? */
181 if ((state1 & FLASH_DQ6) != (state2 & FLASH_DQ6))
182 return ERROR_FLASH_OPERATION_FAILED;
183
184 /* finish anyway */
185 break;
186 }
187 usleep(1000);
188 ++ms;
189
190 /* Polling time exceeded? */
191 if (ms > timeout_ms) {
192 LOG_ERROR("Polling data reading timed out!");
193 return ERROR_FLASH_OPERATION_FAILED;
194 }
195 }
196
197 if (retval == ERROR_OK)
198 LOG_DEBUG("fm3_busy_wait(%x) needs about %d ms", offset, ms);
199
200 return retval;
201 }
202
203 static int fm3_erase(struct flash_bank *bank, int first, int last)
204 {
205 struct fm3_flash_bank *fm3_info = bank->driver_priv;
206 struct target *target = bank->target;
207 int retval = ERROR_OK;
208 uint32_t u32DummyRead;
209 int sector, odd;
210 uint32_t u32FlashType;
211 uint32_t u32FlashSeqAddress1;
212 uint32_t u32FlashSeqAddress2;
213
214 u32FlashType = (uint32_t) fm3_info->flashtype;
215
216 if (u32FlashType == fm3_flash_type1) {
217 u32FlashSeqAddress1 = 0x00001550;
218 u32FlashSeqAddress2 = 0x00000AA8;
219 } else if (u32FlashType == fm3_flash_type2) {
220 u32FlashSeqAddress1 = 0x00000AA8;
221 u32FlashSeqAddress2 = 0x00000554;
222 } else {
223 LOG_ERROR("Flash/Device type unknown!");
224 return ERROR_FLASH_OPERATION_FAILED;
225 }
226
227 if (target->state != TARGET_HALTED) {
228 LOG_ERROR("Target not halted");
229 return ERROR_TARGET_NOT_HALTED;
230 }
231
232 LOG_INFO("Fujitsu MB9[A/B]FXXX: Sector Erase ... (%d to %d)", first, last);
233
234 /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash acccess) */
235 retval = target_write_u32(target, 0x40000000, 0x0001);
236 if (retval != ERROR_OK)
237 return retval;
238
239 /* dummy read of FASZR */
240 retval = target_read_u32(target, 0x40000000, &u32DummyRead);
241 if (retval != ERROR_OK)
242 return retval;
243
244 for (sector = first ; sector <= last ; sector++) {
245 uint32_t offset = bank->sectors[sector].offset;
246
247 for (odd = 0; odd < 2 ; odd++) {
248 if (odd)
249 offset += 4;
250
251 /* Flash unlock sequence */
252 retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
253 if (retval != ERROR_OK)
254 return retval;
255
256 retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
257 if (retval != ERROR_OK)
258 return retval;
259
260 retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080);
261 if (retval != ERROR_OK)
262 return retval;
263
264 retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
265 if (retval != ERROR_OK)
266 return retval;
267
268 retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
269 if (retval != ERROR_OK)
270 return retval;
271
272 /* Sector erase command (0x0030) */
273 retval = target_write_u16(target, offset, 0x0030);
274 if (retval != ERROR_OK)
275 return retval;
276
277 retval = fm3_busy_wait(target, offset, 500);
278 if (retval != ERROR_OK)
279 return retval;
280 }
281 bank->sectors[sector].is_erased = 1;
282 }
283
284 /* FASZR = 0x02, Enables CPU Run Mode (32-bit Flash acccess) */
285 retval = target_write_u32(target, 0x40000000, 0x0002);
286 if (retval != ERROR_OK)
287 return retval;
288
289 retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
290
291 return retval;
292 }
293
294 static int fm3_write_block(struct flash_bank *bank, uint8_t *buffer,
295 uint32_t offset, uint32_t count)
296 {
297 struct fm3_flash_bank *fm3_info = bank->driver_priv;
298 struct target *target = bank->target;
299 uint32_t buffer_size = 2048; /* Default minimum value */
300 struct working_area *write_algorithm;
301 struct working_area *source;
302 uint32_t address = bank->base + offset;
303 struct reg_param reg_params[6];
304 struct armv7m_algorithm armv7m_info;
305 int retval = ERROR_OK;
306 uint32_t u32FlashType;
307 uint32_t u32FlashSeqAddress1;
308 uint32_t u32FlashSeqAddress2;
309
310 /* Increase buffer_size if needed */
311 if (buffer_size < (target->working_area_size / 2))
312 buffer_size = (target->working_area_size / 2);
313
314 u32FlashType = (uint32_t) fm3_info->flashtype;
315
316 if (u32FlashType == fm3_flash_type1) {
317 u32FlashSeqAddress1 = 0x00001550;
318 u32FlashSeqAddress2 = 0x00000AA8;
319 } else if (u32FlashType == fm3_flash_type2) {
320 u32FlashSeqAddress1 = 0x00000AA8;
321 u32FlashSeqAddress2 = 0x00000554;
322 } else {
323 LOG_ERROR("Flash/Device type unknown!");
324 return ERROR_FLASH_OPERATION_FAILED;
325 }
326
327 /* RAMCODE used for fm3 Flash programming: */
328 /* R0 keeps source start address (u32Source) */
329 /* R1 keeps target start address (u32Target) */
330 /* R2 keeps number of halfwords to write (u32Count) */
331 /* R3 keeps Flash Sequence address 1 (u32FlashSeq1) */
332 /* R4 keeps Flash Sequence address 2 (u32FlashSeq2) */
333 /* R5 returns result value (u32FlashResult) */
334
335 const uint8_t fm3_flash_write_code[] = {
336 /* fm3_FLASH_IF->FASZ &= 0xFFFD; */
337 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
338 0x2D, 0x68, /* LDR R5, [R5] */
339 0x4F, 0xF6, 0xFD, 0x76, /* MOVW R6, #0xFFFD */
340 0x35, 0x40, /* ANDS R5, R5, R6 */
341 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
342 0x35, 0x60, /* STR R5, [R6] */
343 /* fm3_FLASH_IF->FASZ |= 1; */
344 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
345 0x2D, 0x68, /* LDR R5, [R3] */
346 0x55, 0xF0, 0x01, 0x05, /* ORRS.W R5, R5, #1 */
347 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
348 0x35, 0x60, /* STR R5, [R6] */
349 /* u32DummyRead = fm3_FLASH_IF->FASZ; */
350 0x28, 0x4D, /* LDR.N R5, ??u32DummyRead */
351 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
352 0x36, 0x68, /* LDR R6, [R6] */
353 0x2E, 0x60, /* STR R6, [R5] */
354 /* u32FlashResult = FLASH_WRITE_NO_RESULT */
355 0x26, 0x4D, /* LDR.N R5, ??u32FlashResult */
356 0x00, 0x26, /* MOVS R6, #0 */
357 0x2E, 0x60, /* STR R6, [R5] */
358 /* while ((u32Count > 0 ) */
359 /* && (u32FlashResult */
360 /* == FLASH_WRITE_NO_RESULT)) */
361 0x01, 0x2A, /* L0: CMP R2, #1 */
362 0x2C, 0xDB, /* BLT.N L1 */
363 0x24, 0x4D, /* LDR.N R5, ??u32FlashResult */
364 0x2D, 0x68, /* LDR R5, [R5] */
365 0x00, 0x2D, /* CMP R5, #0 */
366 0x28, 0xD1, /* BNE.N L1 */
367 /* *u32FlashSeq1 = FLASH_WRITE_1; */
368 0xAA, 0x25, /* MOVS R5, #0xAA */
369 0x1D, 0x60, /* STR R5, [R3] */
370 /* *u32FlashSeq2 = FLASH_WRITE_2; */
371 0x55, 0x25, /* MOVS R5, #0x55 */
372 0x25, 0x60, /* STR R5, [R4] */
373 /* *u32FlashSeq1 = FLASH_WRITE_3; */
374 0xA0, 0x25, /* MOVS R5, #0xA0 */
375 0x1D, 0x60, /* STRH R5, [R3] */
376 /* *(volatile uint16_t*)u32Target */
377 /* = *(volatile uint16_t*)u32Source; */
378 0x05, 0x88, /* LDRH R5, [R0] */
379 0x0D, 0x80, /* STRH R5, [R1] */
380 /* while (u32FlashResult */
381 /* == FLASH_WRITE_NO_RESTULT) */
382 0x1E, 0x4D, /* L2: LDR.N R5, ??u32FlashResult */
383 0x2D, 0x68, /* LDR R5, [R5] */
384 0x00, 0x2D, /* CMP R5, #0 */
385 0x11, 0xD1, /* BNE.N L3 */
386 /* if ((*(volatile uint16_t*)u32Target */
387 /* & FLASH_DQ5) == FLASH_DQ5) */
388 0x0D, 0x88, /* LDRH R5, [R1] */
389 0xAD, 0x06, /* LSLS R5, R5, #0x1A */
390 0x02, 0xD5, /* BPL.N L4 */
391 /* u32FlashResult = FLASH_WRITE_TIMEOUT */
392 0x1A, 0x4D, /* LDR.N R5, ??u32FlashResult */
393 0x02, 0x26, /* MOVS R6, #2 */
394 0x2E, 0x60, /* STR R6, [R5] */
395 /* if ((*(volatile uint16_t *)u32Target */
396 /* & FLASH_DQ7) */
397 /* == (*(volatile uint16_t*)u32Source */
398 /* & FLASH_DQ7)) */
399 0x0D, 0x88, /* L4: LDRH R5, [R1] */
400 0x15, 0xF0, 0x80, 0x05, /* ANDS.W R5, R5, #0x80 */
401 0x06, 0x88, /* LDRH R6, [R0] */
402 0x16, 0xF0, 0x80, 0x06, /* ANDS.W R6, R6, #0x80 */
403 0xB5, 0x42, /* CMP R5, R6 */
404 0xED, 0xD1, /* BNE.N L2 */
405 /* u32FlashResult = FLASH_WRITE_OKAY */
406 0x15, 0x4D, /* LDR.N R5, ??u32FlashResult */
407 0x01, 0x26, /* MOVS R6, #1 */
408 0x2E, 0x60, /* STR R6, [R5] */
409 0xE9, 0xE7, /* B.N L2 */
410 /* if (u32FlashResult */
411 /* != FLASH_WRITE_TIMEOUT) */
412 0x13, 0x4D, /* LDR.N R5, ??u32FlashResult */
413 0x2D, 0x68, /* LDR R5, [R5] */
414 0x02, 0x2D, /* CMP R5, #2 */
415 0x02, 0xD0, /* BEQ.N L5 */
416 /* u32FlashResult = FLASH_WRITE_NO_RESULT */
417 0x11, 0x4D, /* LDR.N R5, ??u32FlashResult */
418 0x00, 0x26, /* MOVS R6, #0 */
419 0x2E, 0x60, /* STR R6, [R5] */
420 /* u32Count--; */
421 0x52, 0x1E, /* L5: SUBS R2, R2, #1 */
422 /* u32Source += 2; */
423 0x80, 0x1C, /* ADDS R0, R0, #2 */
424 /* u32Target += 2; */
425 0x89, 0x1C, /* ADDS R1, R1, #2 */
426 0xD0, 0xE7, /* B.N L0 */
427 /* fm3_FLASH_IF->FASZ &= 0xFFFE; */
428 0x5F, 0xF0, 0x80, 0x45, /* L1: MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
429 0x2D, 0x68, /* LDR R5, [R5] */
430 0x4F, 0xF6, 0xFE, 0x76, /* MOVW R6, #0xFFFE */
431 0x35, 0x40, /* ANDS R5, R5, R6 */
432 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
433 0x35, 0x60, /* STR R5, [R6] */
434 /* fm3_FLASH_IF->FASZ |= 2; */
435 0x5F, 0xF0, 0x80, 0x45, /* MOVS.W R5, #(fm3_FLASH_IF->FASZ) */
436 0x2D, 0x68, /* LDR R5, [R5] */
437 0x55, 0xF0, 0x02, 0x05, /* ORRS.W R5, R5, #2 */
438 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
439 0x35, 0x60, /* STR R5, [R6] */
440 /* u32DummyRead = fm3_FLASH_IF->FASZ; */
441 0x04, 0x4D, /* LDR.N R5, ??u32DummyRead */
442 0x5F, 0xF0, 0x80, 0x46, /* MOVS.W R6, #(fm3_FLASH_IF->FASZ) */
443 0x36, 0x68, /* LDR R6, [R6] */
444 0x2E, 0x60, /* STR R6, [R5] */
445 /* copy u32FlashResult to R3 for return */
446 /* value */
447 0xDF, 0xF8, 0x08, 0x50, /* LDR.W R5, ??u32FlashResult */
448 0x2D, 0x68, /* LDR R5, [R5] */
449 /* Breakpoint here */
450 0x00, 0xBE, /* BKPT #0 */
451
452 /* The following address pointers assume, that the code is running from */
453 /* SRAM basic-address(BASE_ADDR)+8.These address pointers will be patched */
454 /* if a different start address in RAM is used (e.g. for Flash type 2)! */
455 0x00, 0x80, 0xFF, 0x1F, /* u32DummyRead address in RAM (BASE_ADDR) */
456 0x04, 0x80, 0xFF, 0x1F /* u32FlashResult address in RAM (BASE_ADDR+4)*/
457 };
458
459 LOG_INFO("Fujitsu MB9[A/B]FXXX: FLASH Write ...");
460
461 /* disable HW watchdog */
462 retval = target_write_u32(target, 0x40011C00, 0x1ACCE551);
463 if (retval != ERROR_OK)
464 return retval;
465
466 retval = target_write_u32(target, 0x40011C00, 0xE5331AAE);
467 if (retval != ERROR_OK)
468 return retval;
469
470 retval = target_write_u32(target, 0x40011008, 0x00000000);
471 if (retval != ERROR_OK)
472 return retval;
473
474 count = count / 2; /* number bytes -> number halfwords */
475
476 /* check code alignment */
477 if (offset & 0x1) {
478 LOG_WARNING("offset 0x%" PRIx32 " breaks required 2-byte alignment", offset);
479 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
480 }
481
482 /* allocate working area with flash programming code */
483 if (target_alloc_working_area(target, sizeof(fm3_flash_write_code),
484 &write_algorithm) != ERROR_OK) {
485 LOG_WARNING("no working area available, can't do block memory writes");
486 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
487 }
488
489 retval = target_write_buffer(target, write_algorithm->address,
490 sizeof(fm3_flash_write_code), fm3_flash_write_code);
491 if (retval != ERROR_OK)
492 return retval;
493
494 /* memory buffer */
495 while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) {
496 buffer_size /= 2;
497 if (buffer_size <= 256) {
498 /* free working area, write algorithm already allocated */
499 target_free_working_area(target, write_algorithm);
500
501 LOG_WARNING("No large enough working area available, can't do block memory writes");
502 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
503 }
504 }
505
506 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
507 armv7m_info.core_mode = ARM_MODE_THREAD;
508
509 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT); /* source start address */
510 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* target start address */
511 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* number of halfwords to program */
512 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* Flash Sequence address 1 */
513 init_reg_param(&reg_params[4], "r4", 32, PARAM_OUT); /* Flash Sequence address 1 */
514 init_reg_param(&reg_params[5], "r5", 32, PARAM_IN); /* result */
515
516 /* write code buffer and use Flash programming code within fm3 */
517 /* Set breakpoint to 0 with time-out of 1000 ms */
518 while (count > 0) {
519 uint32_t thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
520
521 retval = target_write_buffer(target, write_algorithm->address, 8,
522 fm3_flash_write_code);
523 if (retval != ERROR_OK)
524 break;
525
526 /* Patching 'local variable address' for different RAM addresses */
527 if (write_algorithm->address != (target->working_area_phys + 8)) {
528 /* Algorithm: u32DummyRead: */
529 retval = target_write_u32(target, (write_algorithm->address)
530 + sizeof(fm3_flash_write_code) - 8, (write_algorithm->address) - 8);
531 if (retval != ERROR_OK)
532 break;
533
534 /* Algorithm: u32FlashResult: */
535 retval = target_write_u32(target, (write_algorithm->address)
536 + sizeof(fm3_flash_write_code) - 4, (write_algorithm->address) - 4);
537 if (retval != ERROR_OK)
538 break;
539 }
540
541 retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer);
542 if (retval != ERROR_OK)
543 break;
544
545 buf_set_u32(reg_params[0].value, 0, 32, source->address);
546 buf_set_u32(reg_params[1].value, 0, 32, address);
547 buf_set_u32(reg_params[2].value, 0, 32, thisrun_count);
548 buf_set_u32(reg_params[3].value, 0, 32, u32FlashSeqAddress1);
549 buf_set_u32(reg_params[4].value, 0, 32, u32FlashSeqAddress2);
550
551 retval = target_run_algorithm(target, 0, NULL, 6, reg_params,
552 write_algorithm->address, 0, 1000, &armv7m_info);
553 if (retval != ERROR_OK) {
554 LOG_ERROR("Error executing fm3 Flash programming algorithm");
555 retval = ERROR_FLASH_OPERATION_FAILED;
556 break;
557 }
558
559 if (buf_get_u32(reg_params[5].value, 0, 32) != ERROR_OK) {
560 LOG_ERROR("Fujitsu MB9[A/B]FXXX: Flash programming ERROR (Timeout) -> Reg R3: %x",
561 buf_get_u32(reg_params[5].value, 0, 32));
562 retval = ERROR_FLASH_OPERATION_FAILED;
563 break;
564 }
565
566 buffer += thisrun_count * 2;
567 address += thisrun_count * 2;
568 count -= thisrun_count;
569 }
570
571 target_free_working_area(target, source);
572 target_free_working_area(target, write_algorithm);
573
574 destroy_reg_param(&reg_params[0]);
575 destroy_reg_param(&reg_params[1]);
576 destroy_reg_param(&reg_params[2]);
577 destroy_reg_param(&reg_params[3]);
578 destroy_reg_param(&reg_params[4]);
579 destroy_reg_param(&reg_params[5]);
580
581 return retval;
582 }
583
584 static int fm3_probe(struct flash_bank *bank)
585 {
586 struct fm3_flash_bank *fm3_info = bank->driver_priv;
587 uint16_t num_pages;
588
589 if (bank->target->state != TARGET_HALTED) {
590 LOG_ERROR("Target not halted");
591 return ERROR_TARGET_NOT_HALTED;
592 }
593
594 /*
595 -- page-- start -- blocksize - mpu - totalFlash --
596 page0 0x00000 16k
597 page1 0x04000 16k
598 page2 0x08000 96k ___ fxx3 128k Flash
599 page3 0x20000 128k ___ fxx4 256k Flash
600 page4 0x40000 128k ___ fxx5 384k Flash
601 page5 0x60000 128k ___ fxx6 512k Flash
602 -----------------------
603 page6 0x80000 128k
604 page7 0xa0000 128k ___ fxx7 256k Flash
605 page8 0xc0000 128k
606 page9 0xe0000 128k ___ fxx8 256k Flash
607 */
608
609 num_pages = 10; /* max number of Flash pages for malloc */
610 fm3_info->probed = 0;
611
612 bank->sectors = malloc(sizeof(struct flash_sector) * num_pages);
613 bank->base = 0x00000000;
614 bank->size = 32 * 1024; /* bytes */
615
616 bank->sectors[0].offset = 0;
617 bank->sectors[0].size = 16 * 1024;
618 bank->sectors[0].is_erased = -1;
619 bank->sectors[0].is_protected = -1;
620
621 bank->sectors[1].offset = 0x4000;
622 bank->sectors[1].size = 16 * 1024;
623 bank->sectors[1].is_erased = -1;
624 bank->sectors[1].is_protected = -1;
625
626 if ((fm3_info->variant == mb9bfxx1)
627 || (fm3_info->variant == mb9afxx1)) {
628 num_pages = 3;
629 bank->size = 64 * 1024; /* bytes */
630 bank->num_sectors = num_pages;
631
632 bank->sectors[2].offset = 0x8000;
633 bank->sectors[2].size = 32 * 1024;
634 bank->sectors[2].is_erased = -1;
635 bank->sectors[2].is_protected = -1;
636 }
637
638 if ((fm3_info->variant == mb9bfxx2)
639 || (fm3_info->variant == mb9bfxx4)
640 || (fm3_info->variant == mb9bfxx5)
641 || (fm3_info->variant == mb9bfxx6)
642 || (fm3_info->variant == mb9bfxx7)
643 || (fm3_info->variant == mb9bfxx8)
644 || (fm3_info->variant == mb9afxx2)
645 || (fm3_info->variant == mb9afxx4)
646 || (fm3_info->variant == mb9afxx5)
647 || (fm3_info->variant == mb9afxx6)
648 || (fm3_info->variant == mb9afxx7)
649 || (fm3_info->variant == mb9afxx8)) {
650 num_pages = 3;
651 bank->size = 128 * 1024; /* bytes */
652 bank->num_sectors = num_pages;
653
654 bank->sectors[2].offset = 0x8000;
655 bank->sectors[2].size = 96 * 1024;
656 bank->sectors[2].is_erased = -1;
657 bank->sectors[2].is_protected = -1;
658 }
659
660 if ((fm3_info->variant == mb9bfxx4)
661 || (fm3_info->variant == mb9bfxx5)
662 || (fm3_info->variant == mb9bfxx6)
663 || (fm3_info->variant == mb9bfxx7)
664 || (fm3_info->variant == mb9bfxx8)
665 || (fm3_info->variant == mb9afxx4)
666 || (fm3_info->variant == mb9afxx5)
667 || (fm3_info->variant == mb9afxx6)
668 || (fm3_info->variant == mb9afxx7)
669 || (fm3_info->variant == mb9afxx8)) {
670 num_pages = 4;
671 bank->size = 256 * 1024; /* bytes */
672 bank->num_sectors = num_pages;
673
674 bank->sectors[3].offset = 0x20000;
675 bank->sectors[3].size = 128 * 1024;
676 bank->sectors[3].is_erased = -1;
677 bank->sectors[3].is_protected = -1;
678 }
679
680 if ((fm3_info->variant == mb9bfxx5)
681 || (fm3_info->variant == mb9bfxx6)
682 || (fm3_info->variant == mb9bfxx7)
683 || (fm3_info->variant == mb9bfxx8)
684 || (fm3_info->variant == mb9afxx5)
685 || (fm3_info->variant == mb9afxx6)
686 || (fm3_info->variant == mb9afxx7)
687 || (fm3_info->variant == mb9afxx8)) {
688 num_pages = 5;
689 bank->size = 384 * 1024; /* bytes */
690 bank->num_sectors = num_pages;
691
692 bank->sectors[4].offset = 0x40000;
693 bank->sectors[4].size = 128 * 1024;
694 bank->sectors[4].is_erased = -1;
695 bank->sectors[4].is_protected = -1;
696 }
697
698 if ((fm3_info->variant == mb9bfxx6)
699 || (fm3_info->variant == mb9bfxx7)
700 || (fm3_info->variant == mb9bfxx8)
701 || (fm3_info->variant == mb9afxx6)
702 || (fm3_info->variant == mb9afxx7)
703 || (fm3_info->variant == mb9afxx8)) {
704 num_pages = 6;
705 bank->size = 512 * 1024; /* bytes */
706 bank->num_sectors = num_pages;
707
708 bank->sectors[5].offset = 0x60000;
709 bank->sectors[5].size = 128 * 1024;
710 bank->sectors[5].is_erased = -1;
711 bank->sectors[5].is_protected = -1;
712 }
713
714 if ((fm3_info->variant == mb9bfxx7)
715 || (fm3_info->variant == mb9bfxx8)
716 || (fm3_info->variant == mb9afxx7)
717 || (fm3_info->variant == mb9afxx8)) {
718 num_pages = 8;
719 bank->size = 768 * 1024; /* bytes */
720 bank->num_sectors = num_pages;
721
722 bank->sectors[6].offset = 0x80000;
723 bank->sectors[6].size = 128 * 1024;
724 bank->sectors[6].is_erased = -1;
725 bank->sectors[6].is_protected = -1;
726
727 bank->sectors[7].offset = 0xa0000;
728 bank->sectors[7].size = 128 * 1024;
729 bank->sectors[7].is_erased = -1;
730 bank->sectors[7].is_protected = -1;
731 }
732
733 if ((fm3_info->variant == mb9bfxx8)
734 || (fm3_info->variant == mb9afxx8)) {
735 num_pages = 10;
736 bank->size = 1024 * 1024; /* bytes */
737 bank->num_sectors = num_pages;
738
739 bank->sectors[8].offset = 0xc0000;
740 bank->sectors[8].size = 128 * 1024;
741 bank->sectors[8].is_erased = -1;
742 bank->sectors[8].is_protected = -1;
743
744 bank->sectors[9].offset = 0xe0000;
745 bank->sectors[9].size = 128 * 1024;
746 bank->sectors[9].is_erased = -1;
747 bank->sectors[9].is_protected = -1;
748 }
749
750 fm3_info->probed = 1;
751
752 return ERROR_OK;
753 }
754
755 static int fm3_auto_probe(struct flash_bank *bank)
756 {
757 struct fm3_flash_bank *fm3_info = bank->driver_priv;
758 if (fm3_info->probed)
759 return ERROR_OK;
760 return fm3_probe(bank);
761 }
762
763 static int fm3_info(struct flash_bank *bank, char *buf, int buf_size)
764 {
765 snprintf(buf, buf_size, "Fujitsu fm3 Device does not support Chip-ID (Type unknown)");
766 return ERROR_OK;
767 }
768
769 /* Chip erase */
770 static int fm3_chip_erase(struct flash_bank *bank)
771 {
772 struct target *target = bank->target;
773 struct fm3_flash_bank *fm3_info2 = bank->driver_priv;
774 int retval = ERROR_OK;
775 uint32_t u32DummyRead;
776 uint32_t u32FlashType;
777 uint32_t u32FlashSeqAddress1;
778 uint32_t u32FlashSeqAddress2;
779
780 u32FlashType = (uint32_t) fm3_info2->flashtype;
781
782 if (u32FlashType == fm3_flash_type1) {
783 LOG_INFO("*** Erasing mb9bfxxx type");
784 u32FlashSeqAddress1 = 0x00001550;
785 u32FlashSeqAddress2 = 0x00000AA8;
786 } else if (u32FlashType == fm3_flash_type2) {
787 LOG_INFO("*** Erasing mb9afxxx type");
788 u32FlashSeqAddress1 = 0x00000AA8;
789 u32FlashSeqAddress2 = 0x00000554;
790 } else {
791 LOG_ERROR("Flash/Device type unknown!");
792 return ERROR_FLASH_OPERATION_FAILED;
793 }
794
795 if (target->state != TARGET_HALTED) {
796 LOG_ERROR("Target not halted");
797 return ERROR_TARGET_NOT_HALTED;
798 }
799
800 LOG_INFO("Fujitsu MB9[AB]xxx: Chip Erase ... (may take several seconds)");
801
802 /* Implement Flash chip erase (mass erase) completely on host */
803
804 /* FASZR = 0x01, Enables CPU Programming Mode (16-bit Flash access) */
805 retval = target_write_u32(target, 0x40000000, 0x0001);
806 if (retval != ERROR_OK)
807 return retval;
808
809 /* dummy read of FASZR */
810 retval = target_read_u32(target, 0x40000000, &u32DummyRead);
811 if (retval != ERROR_OK)
812 return retval;
813
814 /* Flash unlock sequence */
815 retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
816 if (retval != ERROR_OK)
817 return retval;
818
819 retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
820 if (retval != ERROR_OK)
821 return retval;
822
823 retval = target_write_u16(target, u32FlashSeqAddress1, 0x0080);
824 if (retval != ERROR_OK)
825 return retval;
826
827 retval = target_write_u16(target, u32FlashSeqAddress1, 0x00AA);
828 if (retval != ERROR_OK)
829 return retval;
830
831 retval = target_write_u16(target, u32FlashSeqAddress2, 0x0055);
832 if (retval != ERROR_OK)
833 return retval;
834
835 /* Chip Erase command (0x0010) */
836 retval = target_write_u16(target, u32FlashSeqAddress1, 0x0010);
837 if (retval != ERROR_OK)
838 return retval;
839
840 retval = fm3_busy_wait(target, u32FlashSeqAddress2, 20000); /* 20s timeout */
841 if (retval != ERROR_OK)
842 return retval;
843
844 /* FASZR = 0x02, Re-enables CPU Run Mode (32-bit Flash access) */
845 retval = target_write_u32(target, 0x40000000, 0x0002);
846 if (retval != ERROR_OK)
847 return retval;
848
849 retval = target_read_u32(target, 0x40000000, &u32DummyRead); /* dummy read of FASZR */
850
851 return retval;
852 }
853
854 COMMAND_HANDLER(fm3_handle_chip_erase_command)
855 {
856 int i;
857
858 if (CMD_ARGC < 1)
859 return ERROR_COMMAND_SYNTAX_ERROR;
860
861 struct flash_bank *bank;
862 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank);
863 if (ERROR_OK != retval)
864 return retval;
865
866 if (fm3_chip_erase(bank) == ERROR_OK) {
867 /* set all sectors as erased */
868 for (i = 0; i < bank->num_sectors; i++)
869 bank->sectors[i].is_erased = 1;
870
871 command_print(CMD_CTX, "fm3 chip erase complete");
872 } else {
873 command_print(CMD_CTX, "fm3 chip erase failed");
874 }
875
876 return ERROR_OK;
877 }
878
879 static const struct command_registration fm3_exec_command_handlers[] = {
880 {
881 .name = "chip_erase",
882 .usage = "<bank>",
883 .handler = fm3_handle_chip_erase_command,
884 .mode = COMMAND_EXEC,
885 .help = "Erase entire Flash device.",
886 },
887 COMMAND_REGISTRATION_DONE
888 };
889
890 static const struct command_registration fm3_command_handlers[] = {
891 {
892 .name = "fm3",
893 .mode = COMMAND_ANY,
894 .help = "fm3 Flash command group",
895 .usage = "",
896 .chain = fm3_exec_command_handlers,
897 },
898 COMMAND_REGISTRATION_DONE
899 };
900
901 struct flash_driver fm3_flash = {
902 .name = "fm3",
903 .commands = fm3_command_handlers,
904 .flash_bank_command = fm3_flash_bank_command,
905 .erase = fm3_erase,
906 .write = fm3_write_block,
907 .probe = fm3_probe,
908 .auto_probe = fm3_auto_probe,
909 .erase_check = default_flash_blank_check,
910 .info = fm3_info,
911 };

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)