flash/nor/mdr.c: fix uninitialised variable warning
[openocd.git] / src / flash / nor / mdr.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
7 * *
8 * Copyright (C) 2011 by Andreas Fritiofson *
9 * andreas.fritiofson@gmail.com *
10 * *
11 * Copyright (C) 2013 by Paul Fertser *
12 * fercerpav@gmail.com *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
28 ***************************************************************************/
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "imp.h"
35 #include <helper/binarybuffer.h>
36 #include <target/algorithm.h>
37 #include <target/armv7m.h>
38
39 #define MD_RST_CLK 0x40020000
40 #define MD_PER_CLOCK (MD_RST_CLK + 0x1C)
41 #define MD_PER_CLOCK_EEPROM (1 << 3)
42 #define MD_PER_CLOCK_RST_CLK (1 << 4)
43
44 #define FLASH_REG_BASE 0x40018000
45 #define FLASH_CMD (FLASH_REG_BASE + 0x00)
46 #define FLASH_ADR (FLASH_REG_BASE + 0x04)
47 #define FLASH_DI (FLASH_REG_BASE + 0x08)
48 #define FLASH_DO (FLASH_REG_BASE + 0x0C)
49 #define FLASH_KEY (FLASH_REG_BASE + 0x10)
50
51 #define FLASH_NVSTR (1 << 13)
52 #define FLASH_PROG (1 << 12)
53 #define FLASH_MAS1 (1 << 11)
54 #define FLASH_ERASE (1 << 10)
55 #define FLASH_IFREN (1 << 9)
56 #define FLASH_SE (1 << 8)
57 #define FLASH_YE (1 << 7)
58 #define FLASH_XE (1 << 6)
59 #define FLASH_RD (1 << 2)
60 #define FLASH_WR (1 << 1)
61 #define FLASH_CON (1 << 0)
62 #define FLASH_DELAY_MASK (7 << 3)
63
64 #define KEY 0x8AAA5551
65
66 struct mdr_flash_bank {
67 int probed;
68 unsigned int mem_type;
69 unsigned int page_count;
70 unsigned int sec_count;
71 };
72
73 /* flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count> */
74 FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
75 {
76 struct mdr_flash_bank *mdr_info;
77
78 if (CMD_ARGC < 9)
79 return ERROR_COMMAND_SYNTAX_ERROR;
80
81 mdr_info = malloc(sizeof(struct mdr_flash_bank));
82
83 bank->driver_priv = mdr_info;
84 mdr_info->probed = 0;
85 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], mdr_info->mem_type);
86 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], mdr_info->page_count);
87 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], mdr_info->sec_count);
88 return ERROR_OK;
89 }
90
91 static int mdr_protect_check(struct flash_bank *bank)
92 {
93 return ERROR_OK;
94 }
95
96 static int mdr_mass_erase(struct flash_bank *bank)
97 {
98 struct target *target = bank->target;
99 struct mdr_flash_bank *mdr_info = bank->driver_priv;
100 uint32_t flash_cmd;
101 int retval;
102 unsigned int i;
103
104 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
105 if (retval != ERROR_OK)
106 return retval;
107
108 for (i = 0; i < mdr_info->sec_count; i++) {
109 retval = target_write_u32(target, FLASH_ADR, i << 2);
110 if (retval != ERROR_OK)
111 return retval;
112
113 flash_cmd |= FLASH_XE | FLASH_MAS1 | FLASH_ERASE;
114 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
115 if (retval != ERROR_OK)
116 return retval;
117 flash_cmd |= FLASH_NVSTR;
118 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
119 if (retval != ERROR_OK)
120 return retval;
121 flash_cmd &= ~FLASH_ERASE;
122 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
123 if (retval != ERROR_OK)
124 return retval;
125 flash_cmd &= ~(FLASH_XE | FLASH_MAS1 | FLASH_NVSTR);
126 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
127 if (retval != ERROR_OK)
128 return retval;
129 }
130
131 return retval;
132 }
133
134 static int mdr_erase(struct flash_bank *bank, int first, int last)
135 {
136 struct target *target = bank->target;
137 struct mdr_flash_bank *mdr_info = bank->driver_priv;
138 int i, retval, retval2;
139 unsigned int j;
140 uint32_t flash_cmd, cur_per_clock;
141
142 if (bank->target->state != TARGET_HALTED) {
143 LOG_ERROR("Target not halted");
144 return ERROR_TARGET_NOT_HALTED;
145 }
146
147 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
148 if (retval != ERROR_OK)
149 return retval;
150
151 if (!(cur_per_clock & 0x10)) {
152 LOG_ERROR("Target needs reset before flash operations");
153 return ERROR_FLASH_OPERATION_FAILED;
154 }
155
156 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
157 if (retval != ERROR_OK)
158 return retval;
159
160 retval = target_write_u32(target, FLASH_KEY, KEY);
161 if (retval != ERROR_OK)
162 return retval;
163
164 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
165 if (retval != ERROR_OK)
166 goto reset_pg_and_lock;
167
168 /* Switch on register access */
169 flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
170 if (mdr_info->mem_type)
171 flash_cmd |= FLASH_IFREN;
172 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
173 if (retval != ERROR_OK)
174 goto reset_pg_and_lock;
175
176 if ((first == 0) && (last == (bank->num_sectors - 1))) {
177 retval = mdr_mass_erase(bank);
178 goto reset_pg_and_lock;
179 }
180
181 unsigned int page_size = bank->size / mdr_info->page_count;
182 for (i = first; i <= last; i++) {
183 for (j = 0; j < mdr_info->sec_count; j++) {
184 retval = target_write_u32(target, FLASH_ADR, (i * page_size) | (j << 2));
185 if (retval != ERROR_OK)
186 goto reset_pg_and_lock;
187
188 flash_cmd |= FLASH_XE | FLASH_ERASE;
189 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
190 if (retval != ERROR_OK)
191 goto reset_pg_and_lock;
192 flash_cmd |= FLASH_NVSTR;
193 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
194 if (retval != ERROR_OK)
195 goto reset_pg_and_lock;
196 flash_cmd &= ~FLASH_ERASE;
197 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
198 if (retval != ERROR_OK)
199 goto reset_pg_and_lock;
200 flash_cmd &= ~(FLASH_XE | FLASH_NVSTR);
201 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
202 if (retval != ERROR_OK)
203 goto reset_pg_and_lock;
204 }
205 bank->sectors[i].is_erased = 1;
206 }
207
208 reset_pg_and_lock:
209 flash_cmd &= FLASH_DELAY_MASK;
210 retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
211 if (retval == ERROR_OK)
212 retval = retval2;
213
214 retval2 = target_write_u32(target, FLASH_KEY, 0);
215 if (retval == ERROR_OK)
216 retval = retval2;
217
218 return retval;
219 }
220
221 static int mdr_protect(struct flash_bank *bank, int set, int first, int last)
222 {
223 return ERROR_OK;
224 }
225
226 static int mdr_write_block(struct flash_bank *bank, uint8_t *buffer,
227 uint32_t offset, uint32_t count)
228 {
229 struct target *target = bank->target;
230 uint32_t buffer_size = 16384;
231 struct working_area *write_algorithm;
232 struct working_area *source;
233 uint32_t address = bank->base + offset;
234 struct reg_param reg_params[5];
235 struct armv7m_algorithm armv7m_info;
236 int retval = ERROR_OK;
237
238 /* see contrib/loaders/flash/mdr32fx.S for src */
239 static const uint8_t mdr32fx_flash_write_code[] = {
240 0x07, 0x68, 0x16, 0x68, 0x00, 0x2e, 0x2e, 0xd0, 0x55, 0x68, 0xb5, 0x42,
241 0xf9, 0xd0, 0x2e, 0x68, 0x44, 0x60, 0x86, 0x60, 0x17, 0x4e, 0x37, 0x43,
242 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x25, 0xf8, 0x15, 0x4e, 0x37, 0x43,
243 0x07, 0x60, 0x0d, 0x26, 0x00, 0xf0, 0x1f, 0xf8, 0x80, 0x26, 0x37, 0x43,
244 0x07, 0x60, 0x3d, 0x26, 0x00, 0xf0, 0x19, 0xf8, 0x80, 0x26, 0xb7, 0x43,
245 0x07, 0x60, 0x0f, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0,
246 0x10, 0xf8, 0x0d, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x04, 0x35, 0x04, 0x34,
247 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46, 0x08, 0x35, 0x55, 0x60, 0x01, 0x39,
248 0x00, 0x29, 0x00, 0xd0, 0xcd, 0xe7, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x3e,
249 0x00, 0x2e, 0xfc, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00,
250 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00
251 };
252
253 /* flash write code */
254 if (target_alloc_working_area(target, sizeof(mdr32fx_flash_write_code),
255 &write_algorithm) != ERROR_OK) {
256 LOG_WARNING("no working area available, can't do block memory writes");
257 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
258 };
259
260 retval = target_write_buffer(target, write_algorithm->address,
261 sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code);
262 if (retval != ERROR_OK)
263 return retval;
264
265 /* memory buffer */
266 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
267 buffer_size /= 2;
268 buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
269 if (buffer_size <= 256) {
270 /* we already allocated the writing code, but failed to get a
271 * buffer, free the algorithm */
272 target_free_working_area(target, write_algorithm);
273
274 LOG_WARNING("no large enough working area available, can't do block memory writes");
275 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
276 }
277 };
278
279 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
280 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (32bit) */
281 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
282 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
283 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
284
285 buf_set_u32(reg_params[0].value, 0, 32, FLASH_REG_BASE);
286 buf_set_u32(reg_params[1].value, 0, 32, count);
287 buf_set_u32(reg_params[2].value, 0, 32, source->address);
288 buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
289 buf_set_u32(reg_params[4].value, 0, 32, address);
290
291 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
292 armv7m_info.core_mode = ARM_MODE_THREAD;
293
294 retval = target_run_flash_async_algorithm(target, buffer, count, 4,
295 0, NULL,
296 5, reg_params,
297 source->address, source->size,
298 write_algorithm->address, 0,
299 &armv7m_info);
300
301 if (retval == ERROR_FLASH_OPERATION_FAILED)
302 LOG_ERROR("flash write failed at address 0x%"PRIx32,
303 buf_get_u32(reg_params[4].value, 0, 32));
304
305 target_free_working_area(target, source);
306 target_free_working_area(target, write_algorithm);
307
308 destroy_reg_param(&reg_params[0]);
309 destroy_reg_param(&reg_params[1]);
310 destroy_reg_param(&reg_params[2]);
311 destroy_reg_param(&reg_params[3]);
312 destroy_reg_param(&reg_params[4]);
313
314 return retval;
315 }
316
317 static int mdr_write(struct flash_bank *bank, uint8_t *buffer,
318 uint32_t offset, uint32_t count)
319 {
320 struct target *target = bank->target;
321 struct mdr_flash_bank *mdr_info = bank->driver_priv;
322 uint8_t *new_buffer = NULL;
323
324 if (bank->target->state != TARGET_HALTED) {
325 LOG_ERROR("Target not halted");
326 return ERROR_TARGET_NOT_HALTED;
327 }
328
329 if (offset & 0x3) {
330 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
331 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
332 }
333
334 /* If there's an odd number of bytes, the data has to be padded. Duplicate
335 * the buffer and use the normal code path with a single block write since
336 * it's probably cheaper than to special case the last odd write using
337 * discrete accesses. */
338 int rem = count % 4;
339 if (rem) {
340 new_buffer = malloc(count + rem);
341 if (new_buffer == NULL) {
342 LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
343 return ERROR_FAIL;
344 }
345 LOG_INFO("odd number of bytes to write, padding with 0xff");
346 buffer = memcpy(new_buffer, buffer, count);
347 while (rem--)
348 buffer[count++] = 0xff;
349 }
350
351 uint32_t flash_cmd, cur_per_clock;
352 int retval, retval2;
353
354 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
355 if (retval != ERROR_OK)
356 goto free_buffer;
357
358 if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
359 /* Something's very wrong if the RST_CLK module is not clocked */
360 LOG_ERROR("Target needs reset before flash operations");
361 retval = ERROR_FLASH_OPERATION_FAILED;
362 goto free_buffer;
363 }
364
365 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
366 if (retval != ERROR_OK)
367 goto free_buffer;
368
369 retval = target_write_u32(target, FLASH_KEY, KEY);
370 if (retval != ERROR_OK)
371 goto free_buffer;
372
373 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
374 if (retval != ERROR_OK)
375 goto reset_pg_and_lock;
376
377 /* Switch on register access */
378 flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
379 if (mdr_info->mem_type)
380 flash_cmd |= FLASH_IFREN;
381 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
382 if (retval != ERROR_OK)
383 goto reset_pg_and_lock;
384
385 /* try using block write */
386 retval = mdr_write_block(bank, buffer, offset, count/4);
387
388 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
389 /* if block write failed (no sufficient working area),
390 * we use normal (slow) single halfword accesses */
391 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
392
393 unsigned int page_size = bank->size / mdr_info->page_count;
394 unsigned int page_mask = page_size - 1;
395 while (count > 0) {
396 unsigned int i, j;
397 unsigned int cur_page = offset & ~page_mask;
398 unsigned int bytes_to_write = cur_page + page_size - offset;
399 if (count < bytes_to_write)
400 bytes_to_write = count;
401
402 /*LOG_INFO("Selecting next page: %08x", cur_page);*/
403
404 for (i = 0; i < mdr_info->sec_count; i++) {
405 retval = target_write_u32(target, FLASH_ADR, offset + i*4);
406 if (retval != ERROR_OK)
407 goto reset_pg_and_lock;
408 /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/
409
410 flash_cmd |= FLASH_XE | FLASH_PROG;
411 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
412 if (retval != ERROR_OK)
413 goto reset_pg_and_lock;
414
415 flash_cmd |= FLASH_NVSTR;
416 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
417 if (retval != ERROR_OK)
418 goto reset_pg_and_lock;
419
420 for (j = 0;
421 (((offset + j + i*4) & ~page_mask) == cur_page) &&
422 (j + i*4 < count);
423 j += mdr_info->sec_count*4) {
424 uint32_t value;
425 memcpy(&value, buffer + j + i*4, sizeof(uint32_t));
426 retval = target_write_u32(target, FLASH_DI, value);
427 if (retval != ERROR_OK)
428 goto reset_pg_and_lock;
429 /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/
430 retval = target_write_u32(target, FLASH_ADR, offset + j + i*4);
431 if (retval != ERROR_OK)
432 goto reset_pg_and_lock;
433
434 flash_cmd |= FLASH_YE;
435 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
436 if (retval != ERROR_OK)
437 goto reset_pg_and_lock;
438 flash_cmd &= ~FLASH_YE;
439 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
440 if (retval != ERROR_OK)
441 goto reset_pg_and_lock;
442 }
443 flash_cmd &= ~FLASH_NVSTR;
444 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
445 if (retval != ERROR_OK)
446 goto reset_pg_and_lock;
447
448 flash_cmd &= ~(FLASH_XE | FLASH_PROG);
449 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
450 if (retval != ERROR_OK)
451 goto reset_pg_and_lock;
452 }
453
454 buffer += bytes_to_write;
455 offset += bytes_to_write;
456 count -= bytes_to_write;
457 }
458 }
459
460 reset_pg_and_lock:
461 flash_cmd &= FLASH_DELAY_MASK;
462 retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
463 if (retval == ERROR_OK)
464 retval = retval2;
465
466 retval2 = target_write_u32(target, FLASH_KEY, 0);
467 if (retval == ERROR_OK)
468 retval = retval2;
469
470 free_buffer:
471 if (new_buffer)
472 free(new_buffer);
473
474 return retval;
475 }
476
477 static int mdr_probe(struct flash_bank *bank)
478 {
479 struct mdr_flash_bank *mdr_info = bank->driver_priv;
480 unsigned int page_count, page_size, i;
481
482 page_count = mdr_info->page_count;
483 page_size = bank->size / page_count;
484
485 bank->num_sectors = page_count;
486 bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
487
488 for (i = 0; i < page_count; i++) {
489 bank->sectors[i].offset = i * page_size;
490 bank->sectors[i].size = page_size;
491 bank->sectors[i].is_erased = -1;
492 bank->sectors[i].is_protected = 0;
493 }
494
495 mdr_info->probed = 1;
496
497 return ERROR_OK;
498 }
499
500 static int mdr_auto_probe(struct flash_bank *bank)
501 {
502 struct mdr_flash_bank *mdr_info = bank->driver_priv;
503 if (mdr_info->probed)
504 return ERROR_OK;
505 return mdr_probe(bank);
506 }
507
508 static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
509 {
510 struct mdr_flash_bank *mdr_info = bank->driver_priv;
511 snprintf(buf, buf_size, "MDR32Fx - %s",
512 mdr_info->mem_type ? "info memory" : "main memory");
513
514 return ERROR_OK;
515 }
516
517 struct flash_driver mdr_flash = {
518 .name = "mdr",
519 .flash_bank_command = mdr_flash_bank_command,
520 .erase = mdr_erase,
521 .protect = mdr_protect,
522 .write = mdr_write,
523 .read = default_flash_read,
524 .probe = mdr_probe,
525 .auto_probe = mdr_auto_probe,
526 .erase_check = default_flash_blank_check,
527 .protect_check = mdr_protect_check,
528 .info = get_mdr_info,
529 };

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)