Add remote bitbang write buffer.
[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, see <http://www.gnu.org/licenses/>. *
26 ***************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "imp.h"
33 #include <helper/binarybuffer.h>
34 #include <target/algorithm.h>
35 #include <target/armv7m.h>
36
37 #define MD_RST_CLK 0x40020000
38 #define MD_PER_CLOCK (MD_RST_CLK + 0x1C)
39 #define MD_PER_CLOCK_EEPROM (1 << 3)
40 #define MD_PER_CLOCK_RST_CLK (1 << 4)
41
42 #define FLASH_REG_BASE 0x40018000
43 #define FLASH_CMD (FLASH_REG_BASE + 0x00)
44 #define FLASH_ADR (FLASH_REG_BASE + 0x04)
45 #define FLASH_DI (FLASH_REG_BASE + 0x08)
46 #define FLASH_DO (FLASH_REG_BASE + 0x0C)
47 #define FLASH_KEY (FLASH_REG_BASE + 0x10)
48
49 #define FLASH_NVSTR (1 << 13)
50 #define FLASH_PROG (1 << 12)
51 #define FLASH_MAS1 (1 << 11)
52 #define FLASH_ERASE (1 << 10)
53 #define FLASH_IFREN (1 << 9)
54 #define FLASH_SE (1 << 8)
55 #define FLASH_YE (1 << 7)
56 #define FLASH_XE (1 << 6)
57 #define FLASH_RD (1 << 2)
58 #define FLASH_WR (1 << 1)
59 #define FLASH_CON (1 << 0)
60 #define FLASH_DELAY_MASK (7 << 3)
61
62 #define KEY 0x8AAA5551
63
64 struct mdr_flash_bank {
65 bool probed;
66 unsigned int mem_type;
67 unsigned int page_count;
68 unsigned int sec_count;
69 };
70
71 /* flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count> */
72 FLASH_BANK_COMMAND_HANDLER(mdr_flash_bank_command)
73 {
74 struct mdr_flash_bank *mdr_info;
75
76 if (CMD_ARGC < 9)
77 return ERROR_COMMAND_SYNTAX_ERROR;
78
79 mdr_info = malloc(sizeof(struct mdr_flash_bank));
80
81 bank->driver_priv = mdr_info;
82 mdr_info->probed = false;
83 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[6], mdr_info->mem_type);
84 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[7], mdr_info->page_count);
85 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[8], mdr_info->sec_count);
86 return ERROR_OK;
87 }
88
89 static int mdr_mass_erase(struct flash_bank *bank)
90 {
91 struct target *target = bank->target;
92 struct mdr_flash_bank *mdr_info = bank->driver_priv;
93 uint32_t flash_cmd;
94 int retval;
95 unsigned int i;
96
97 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
98 if (retval != ERROR_OK)
99 return retval;
100
101 for (i = 0; i < mdr_info->sec_count; i++) {
102 retval = target_write_u32(target, FLASH_ADR, i << 2);
103 if (retval != ERROR_OK)
104 return retval;
105
106 flash_cmd |= FLASH_XE | FLASH_MAS1 | FLASH_ERASE;
107 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
108 if (retval != ERROR_OK)
109 return retval;
110 flash_cmd |= FLASH_NVSTR;
111 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
112 if (retval != ERROR_OK)
113 return retval;
114 flash_cmd &= ~FLASH_ERASE;
115 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
116 if (retval != ERROR_OK)
117 return retval;
118 flash_cmd &= ~(FLASH_XE | FLASH_MAS1 | FLASH_NVSTR);
119 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
120 if (retval != ERROR_OK)
121 return retval;
122 }
123
124 return retval;
125 }
126
127 static int mdr_erase(struct flash_bank *bank, unsigned int first,
128 unsigned int last)
129 {
130 struct target *target = bank->target;
131 struct mdr_flash_bank *mdr_info = bank->driver_priv;
132 int retval, retval2;
133 unsigned int j;
134 uint32_t flash_cmd, cur_per_clock;
135
136 if (bank->target->state != TARGET_HALTED) {
137 LOG_ERROR("Target not halted");
138 return ERROR_TARGET_NOT_HALTED;
139 }
140
141 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
142 if (retval != ERROR_OK)
143 return retval;
144
145 if (!(cur_per_clock & 0x10)) {
146 LOG_ERROR("Target needs reset before flash operations");
147 return ERROR_FLASH_OPERATION_FAILED;
148 }
149
150 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
151 if (retval != ERROR_OK)
152 return retval;
153
154 retval = target_write_u32(target, FLASH_KEY, KEY);
155 if (retval != ERROR_OK)
156 return retval;
157
158 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
159 if (retval != ERROR_OK)
160 goto reset_pg_and_lock;
161
162 /* Switch on register access */
163 flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
164 if (mdr_info->mem_type)
165 flash_cmd |= FLASH_IFREN;
166 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
167 if (retval != ERROR_OK)
168 goto reset_pg_and_lock;
169
170 if ((first == 0) && (last == (bank->num_sectors - 1)) &&
171 !mdr_info->mem_type) {
172 retval = mdr_mass_erase(bank);
173 goto reset_pg_and_lock;
174 }
175
176 unsigned int page_size = bank->size / mdr_info->page_count;
177 for (unsigned int i = first; i <= last; i++) {
178 for (j = 0; j < mdr_info->sec_count; j++) {
179 retval = target_write_u32(target, FLASH_ADR, (i * page_size) | (j << 2));
180 if (retval != ERROR_OK)
181 goto reset_pg_and_lock;
182
183 flash_cmd |= FLASH_XE | FLASH_ERASE;
184 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
185 if (retval != ERROR_OK)
186 goto reset_pg_and_lock;
187 flash_cmd |= FLASH_NVSTR;
188 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
189 if (retval != ERROR_OK)
190 goto reset_pg_and_lock;
191 flash_cmd &= ~FLASH_ERASE;
192 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
193 if (retval != ERROR_OK)
194 goto reset_pg_and_lock;
195 flash_cmd &= ~(FLASH_XE | FLASH_NVSTR);
196 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
197 if (retval != ERROR_OK)
198 goto reset_pg_and_lock;
199 }
200 bank->sectors[i].is_erased = 1;
201 }
202
203 reset_pg_and_lock:
204 flash_cmd &= FLASH_DELAY_MASK;
205 retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
206 if (retval == ERROR_OK)
207 retval = retval2;
208
209 retval2 = target_write_u32(target, FLASH_KEY, 0);
210 if (retval == ERROR_OK)
211 retval = retval2;
212
213 return retval;
214 }
215
216 static int mdr_write_block(struct flash_bank *bank, const uint8_t *buffer,
217 uint32_t offset, uint32_t count)
218 {
219 struct target *target = bank->target;
220 uint32_t buffer_size = 16384;
221 struct working_area *write_algorithm;
222 struct working_area *source;
223 uint32_t address = bank->base + offset;
224 struct reg_param reg_params[5];
225 struct armv7m_algorithm armv7m_info;
226 int retval = ERROR_OK;
227
228 /* see contrib/loaders/flash/mdr32fx.S for src */
229 static const uint8_t mdr32fx_flash_write_code[] = {
230 0x07, 0x68, 0x16, 0x68, 0x00, 0x2e, 0x2e, 0xd0, 0x55, 0x68, 0xb5, 0x42,
231 0xf9, 0xd0, 0x2e, 0x68, 0x44, 0x60, 0x86, 0x60, 0x17, 0x4e, 0x37, 0x43,
232 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0, 0x25, 0xf8, 0x15, 0x4e, 0x37, 0x43,
233 0x07, 0x60, 0x0d, 0x26, 0x00, 0xf0, 0x1f, 0xf8, 0x80, 0x26, 0x37, 0x43,
234 0x07, 0x60, 0x3d, 0x26, 0x00, 0xf0, 0x19, 0xf8, 0x80, 0x26, 0xb7, 0x43,
235 0x07, 0x60, 0x0f, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x05, 0x26, 0x00, 0xf0,
236 0x10, 0xf8, 0x0d, 0x4e, 0xb7, 0x43, 0x07, 0x60, 0x04, 0x35, 0x04, 0x34,
237 0x9d, 0x42, 0x01, 0xd3, 0x15, 0x46, 0x08, 0x35, 0x55, 0x60, 0x01, 0x39,
238 0x00, 0x29, 0x00, 0xd0, 0xcd, 0xe7, 0x30, 0x46, 0x00, 0xbe, 0x01, 0x3e,
239 0x00, 0x2e, 0xfc, 0xd1, 0x70, 0x47, 0x00, 0x00, 0x40, 0x10, 0x00, 0x00,
240 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00
241 };
242
243 /* flash write code */
244 if (target_alloc_working_area(target, sizeof(mdr32fx_flash_write_code),
245 &write_algorithm) != ERROR_OK) {
246 LOG_WARNING("no working area available, can't do block memory writes");
247 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
248 }
249
250 retval = target_write_buffer(target, write_algorithm->address,
251 sizeof(mdr32fx_flash_write_code), mdr32fx_flash_write_code);
252 if (retval != ERROR_OK)
253 return retval;
254
255 /* memory buffer */
256 while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) {
257 buffer_size /= 2;
258 buffer_size &= ~3UL; /* Make sure it's 4 byte aligned */
259 if (buffer_size <= 256) {
260 /* we already allocated the writing code, but failed to get a
261 * buffer, free the algorithm */
262 target_free_working_area(target, write_algorithm);
263
264 LOG_WARNING("no large enough working area available, can't do block memory writes");
265 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
266 }
267 }
268
269 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT); /* flash base (in), status (out) */
270 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT); /* count (32bit) */
271 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT); /* buffer start */
272 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT); /* buffer end */
273 init_reg_param(&reg_params[4], "r4", 32, PARAM_IN_OUT); /* target address */
274
275 buf_set_u32(reg_params[0].value, 0, 32, FLASH_REG_BASE);
276 buf_set_u32(reg_params[1].value, 0, 32, count);
277 buf_set_u32(reg_params[2].value, 0, 32, source->address);
278 buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size);
279 buf_set_u32(reg_params[4].value, 0, 32, address);
280
281 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
282 armv7m_info.core_mode = ARM_MODE_THREAD;
283
284 retval = target_run_flash_async_algorithm(target, buffer, count, 4,
285 0, NULL,
286 5, reg_params,
287 source->address, source->size,
288 write_algorithm->address, 0,
289 &armv7m_info);
290
291 if (retval == ERROR_FLASH_OPERATION_FAILED)
292 LOG_ERROR("flash write failed at address 0x%"PRIx32,
293 buf_get_u32(reg_params[4].value, 0, 32));
294
295 target_free_working_area(target, source);
296 target_free_working_area(target, write_algorithm);
297
298 destroy_reg_param(&reg_params[0]);
299 destroy_reg_param(&reg_params[1]);
300 destroy_reg_param(&reg_params[2]);
301 destroy_reg_param(&reg_params[3]);
302 destroy_reg_param(&reg_params[4]);
303
304 return retval;
305 }
306
307 static int mdr_write(struct flash_bank *bank, const uint8_t *buffer,
308 uint32_t offset, uint32_t count)
309 {
310 struct target *target = bank->target;
311 struct mdr_flash_bank *mdr_info = bank->driver_priv;
312 uint8_t *new_buffer = NULL;
313
314 if (bank->target->state != TARGET_HALTED) {
315 LOG_ERROR("Target not halted");
316 return ERROR_TARGET_NOT_HALTED;
317 }
318
319 if (offset & 0x3) {
320 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
321 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
322 }
323
324 /* If there's an odd number of bytes, the data has to be padded. Duplicate
325 * the buffer and use the normal code path with a single block write since
326 * it's probably cheaper than to special case the last odd write using
327 * discrete accesses. */
328 int rem = count % 4;
329 if (rem) {
330 new_buffer = malloc(count + rem);
331 if (new_buffer == NULL) {
332 LOG_ERROR("odd number of bytes to write and no memory for padding buffer");
333 return ERROR_FAIL;
334 }
335 LOG_INFO("odd number of bytes to write, padding with 0xff");
336 buffer = memcpy(new_buffer, buffer, count);
337 while (rem--)
338 new_buffer[count++] = 0xff;
339 }
340
341 uint32_t flash_cmd, cur_per_clock;
342 int retval, retval2;
343
344 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
345 if (retval != ERROR_OK)
346 goto free_buffer;
347
348 if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
349 /* Something's very wrong if the RST_CLK module is not clocked */
350 LOG_ERROR("Target needs reset before flash operations");
351 retval = ERROR_FLASH_OPERATION_FAILED;
352 goto free_buffer;
353 }
354
355 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
356 if (retval != ERROR_OK)
357 goto free_buffer;
358
359 retval = target_write_u32(target, FLASH_KEY, KEY);
360 if (retval != ERROR_OK)
361 goto free_buffer;
362
363 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
364 if (retval != ERROR_OK)
365 goto reset_pg_and_lock;
366
367 /* Switch on register access */
368 flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON;
369 if (mdr_info->mem_type)
370 flash_cmd |= FLASH_IFREN;
371 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
372 if (retval != ERROR_OK)
373 goto reset_pg_and_lock;
374
375 /* try using block write */
376 retval = mdr_write_block(bank, buffer, offset, count/4);
377
378 if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) {
379 /* if block write failed (no sufficient working area),
380 * we use normal (slow) single halfword accesses */
381 LOG_WARNING("Can't use block writes, falling back to single memory accesses");
382
383 unsigned int page_size = bank->size / mdr_info->page_count;
384 unsigned int page_mask = page_size - 1;
385 while (count > 0) {
386 unsigned int i, j;
387 unsigned int cur_page = offset & ~page_mask;
388 unsigned int bytes_to_write = cur_page + page_size - offset;
389 if (count < bytes_to_write)
390 bytes_to_write = count;
391
392 /*LOG_INFO("Selecting next page: %08x", cur_page);*/
393
394 for (i = 0; i < mdr_info->sec_count; i++) {
395 retval = target_write_u32(target, FLASH_ADR, offset + i*4);
396 if (retval != ERROR_OK)
397 goto reset_pg_and_lock;
398 /*LOG_INFO("Selecting page/sector: %08x", offset + i*4);*/
399
400 flash_cmd |= FLASH_XE | FLASH_PROG;
401 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
402 if (retval != ERROR_OK)
403 goto reset_pg_and_lock;
404
405 flash_cmd |= FLASH_NVSTR;
406 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
407 if (retval != ERROR_OK)
408 goto reset_pg_and_lock;
409
410 for (j = 0;
411 (((offset + j + i*4) & ~page_mask) == cur_page) &&
412 (j + i*4 < count);
413 j += mdr_info->sec_count*4) {
414 uint32_t value;
415 memcpy(&value, buffer + j + i*4, sizeof(uint32_t));
416 retval = target_write_u32(target, FLASH_DI, value);
417 if (retval != ERROR_OK)
418 goto reset_pg_and_lock;
419 /*LOG_INFO("Writing to addr %08x", offset + j + i*4);*/
420 retval = target_write_u32(target, FLASH_ADR, offset + j + i*4);
421 if (retval != ERROR_OK)
422 goto reset_pg_and_lock;
423
424 flash_cmd |= FLASH_YE;
425 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
426 if (retval != ERROR_OK)
427 goto reset_pg_and_lock;
428 flash_cmd &= ~FLASH_YE;
429 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
430 if (retval != ERROR_OK)
431 goto reset_pg_and_lock;
432 }
433 flash_cmd &= ~FLASH_NVSTR;
434 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
435 if (retval != ERROR_OK)
436 goto reset_pg_and_lock;
437
438 flash_cmd &= ~(FLASH_XE | FLASH_PROG);
439 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
440 if (retval != ERROR_OK)
441 goto reset_pg_and_lock;
442 }
443
444 buffer += bytes_to_write;
445 offset += bytes_to_write;
446 count -= bytes_to_write;
447 }
448 }
449
450 reset_pg_and_lock:
451 flash_cmd &= FLASH_DELAY_MASK;
452 retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
453 if (retval == ERROR_OK)
454 retval = retval2;
455
456 retval2 = target_write_u32(target, FLASH_KEY, 0);
457 if (retval == ERROR_OK)
458 retval = retval2;
459
460 free_buffer:
461 free(new_buffer);
462
463 /* read some bytes bytes to flush buffer in flash accelerator.
464 * See errata for 1986VE1T and 1986VE3. Error 0007 */
465 if ((retval == ERROR_OK) && (!mdr_info->mem_type)) {
466 uint32_t tmp;
467 target_checksum_memory(bank->target, bank->base, 64, &tmp);
468 }
469
470 return retval;
471 }
472
473 static int mdr_read(struct flash_bank *bank, uint8_t *buffer,
474 uint32_t offset, uint32_t count)
475 {
476 struct target *target = bank->target;
477 struct mdr_flash_bank *mdr_info = bank->driver_priv;
478 int retval, retval2;
479
480 if (!mdr_info->mem_type)
481 return default_flash_read(bank, buffer, offset, count);
482
483 if (bank->target->state != TARGET_HALTED) {
484 LOG_ERROR("Target not halted");
485 return ERROR_TARGET_NOT_HALTED;
486 }
487
488 if (offset & 0x3) {
489 LOG_ERROR("offset 0x%" PRIx32 " breaks required 4-byte alignment", offset);
490 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
491 }
492
493 if (count & 0x3) {
494 LOG_ERROR("count 0x%" PRIx32 " breaks required 4-byte alignment", count);
495 return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
496 }
497
498 uint32_t flash_cmd, cur_per_clock;
499
500 retval = target_read_u32(target, MD_PER_CLOCK, &cur_per_clock);
501 if (retval != ERROR_OK)
502 goto err;
503
504 if (!(cur_per_clock & MD_PER_CLOCK_RST_CLK)) {
505 /* Something's very wrong if the RST_CLK module is not clocked */
506 LOG_ERROR("Target needs reset before flash operations");
507 retval = ERROR_FLASH_OPERATION_FAILED;
508 goto err;
509 }
510
511 retval = target_write_u32(target, MD_PER_CLOCK, cur_per_clock | MD_PER_CLOCK_EEPROM);
512 if (retval != ERROR_OK)
513 goto err;
514
515 retval = target_write_u32(target, FLASH_KEY, KEY);
516 if (retval != ERROR_OK)
517 goto err;
518
519 retval = target_read_u32(target, FLASH_CMD, &flash_cmd);
520 if (retval != ERROR_OK)
521 goto err_lock;
522
523 /* Switch on register access */
524 flash_cmd = (flash_cmd & FLASH_DELAY_MASK) | FLASH_CON | FLASH_IFREN;
525 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
526 if (retval != ERROR_OK)
527 goto reset_pg_and_lock;
528
529 for (uint32_t i = 0; i < count; i += 4) {
530 retval = target_write_u32(target, FLASH_ADR, offset + i);
531 if (retval != ERROR_OK)
532 goto reset_pg_and_lock;
533
534 retval = target_write_u32(target, FLASH_CMD, flash_cmd |
535 FLASH_XE | FLASH_YE | FLASH_SE);
536 if (retval != ERROR_OK)
537 goto reset_pg_and_lock;
538
539 uint32_t buf;
540 retval = target_read_u32(target, FLASH_DO, &buf);
541 if (retval != ERROR_OK)
542 goto reset_pg_and_lock;
543
544 buf_set_u32(buffer, i * 8, 32, buf);
545
546 retval = target_write_u32(target, FLASH_CMD, flash_cmd);
547 if (retval != ERROR_OK)
548 goto reset_pg_and_lock;
549
550 }
551
552 reset_pg_and_lock:
553 flash_cmd &= FLASH_DELAY_MASK;
554 retval2 = target_write_u32(target, FLASH_CMD, flash_cmd);
555 if (retval == ERROR_OK)
556 retval = retval2;
557
558 err_lock:
559 retval2 = target_write_u32(target, FLASH_KEY, 0);
560 if (retval == ERROR_OK)
561 retval = retval2;
562
563 err:
564 return retval;
565 }
566
567 static int mdr_probe(struct flash_bank *bank)
568 {
569 struct mdr_flash_bank *mdr_info = bank->driver_priv;
570 unsigned int page_count, page_size, i;
571
572 page_count = mdr_info->page_count;
573 page_size = bank->size / page_count;
574
575 free(bank->sectors);
576
577 bank->num_sectors = page_count;
578 bank->sectors = malloc(sizeof(struct flash_sector) * page_count);
579
580 for (i = 0; i < page_count; i++) {
581 bank->sectors[i].offset = i * page_size;
582 bank->sectors[i].size = page_size;
583 bank->sectors[i].is_erased = -1;
584 bank->sectors[i].is_protected = 0;
585 }
586
587 mdr_info->probed = true;
588
589 return ERROR_OK;
590 }
591
592 static int mdr_auto_probe(struct flash_bank *bank)
593 {
594 struct mdr_flash_bank *mdr_info = bank->driver_priv;
595 if (mdr_info->probed)
596 return ERROR_OK;
597 return mdr_probe(bank);
598 }
599
600 static int get_mdr_info(struct flash_bank *bank, char *buf, int buf_size)
601 {
602 struct mdr_flash_bank *mdr_info = bank->driver_priv;
603 snprintf(buf, buf_size, "MDR32Fx - %s",
604 mdr_info->mem_type ? "info memory" : "main memory");
605
606 return ERROR_OK;
607 }
608
609 const struct flash_driver mdr_flash = {
610 .name = "mdr",
611 .usage = "flash bank <name> mdr <base> <size> 0 0 <target#> <type> <page_count> <sec_count>\n"
612 "<type>: 0 for main memory, 1 for info memory",
613 .flash_bank_command = mdr_flash_bank_command,
614 .erase = mdr_erase,
615 .write = mdr_write,
616 .read = mdr_read,
617 .probe = mdr_probe,
618 .auto_probe = mdr_auto_probe,
619 .erase_check = default_flash_blank_check,
620 .info = get_mdr_info,
621 .free_driver_priv = default_flash_free_driver_priv,
622 };

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)