flash: erase_address now has an unlock option
[openocd.git] / src / flash / nor / tcl.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath <Dominic.Rath@gmx.de> *
3 * Copyright (C) 2007,2008 Øyvind Harboe <oyvind.harboe@zylin.com> *
4 * Copyright (C) 2008 by Spencer Oliver <spen@spen-soft.co.uk> *
5 * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "imp.h"
26 #include <helper/time_support.h>
27 #include <target/image.h>
28
29 /**
30 * @file
31 * Implements Tcl commands used to access NOR flash facilities.
32 */
33
34 COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
35 struct flash_bank **bank)
36 {
37 const char *name = CMD_ARGV[name_index];
38 *bank = get_flash_bank_by_name(name);
39 if (*bank)
40 return ERROR_OK;
41
42 unsigned bank_num;
43 COMMAND_PARSE_NUMBER(uint, name, bank_num);
44
45 return get_flash_bank_by_num(bank_num, bank);
46 }
47
48
49 COMMAND_HANDLER(handle_flash_info_command)
50 {
51 struct flash_bank *p;
52 uint32_t i = 0;
53 int j = 0;
54 int retval;
55
56 if (CMD_ARGC != 1)
57 return ERROR_COMMAND_SYNTAX_ERROR;
58
59 unsigned bank_nr;
60 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], bank_nr);
61
62 for (p = flash_bank_list(); p; p = p->next, i++)
63 {
64 if (i != bank_nr)
65 continue;
66
67 char buf[1024];
68
69 /* attempt auto probe */
70 if ((retval = p->driver->auto_probe(p)) != ERROR_OK)
71 return retval;
72
73 command_print(CMD_CTX,
74 "#%" PRIi32 " : %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", buswidth %i, chipwidth %i",
75 i,
76 p->driver->name,
77 p->base,
78 p->size,
79 p->bus_width,
80 p->chip_width);
81 for (j = 0; j < p->num_sectors; j++)
82 {
83 char *protect_state;
84
85 if (p->sectors[j].is_protected == 0)
86 protect_state = "not protected";
87 else if (p->sectors[j].is_protected == 1)
88 protect_state = "protected";
89 else
90 protect_state = "protection state unknown";
91
92 command_print(CMD_CTX,
93 "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
94 j,
95 p->sectors[j].offset,
96 p->sectors[j].size,
97 p->sectors[j].size >> 10,
98 protect_state);
99 }
100
101 *buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
102 retval = p->driver->info(p, buf, sizeof(buf));
103 command_print(CMD_CTX, "%s", buf);
104 if (retval != ERROR_OK)
105 LOG_ERROR("error retrieving flash info (%d)", retval);
106 }
107
108 return ERROR_OK;
109 }
110
111 COMMAND_HANDLER(handle_flash_probe_command)
112 {
113 int retval;
114
115 if (CMD_ARGC != 1)
116 {
117 return ERROR_COMMAND_SYNTAX_ERROR;
118 }
119
120 unsigned bank_nr;
121 COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], bank_nr);
122 struct flash_bank *p = get_flash_bank_by_num_noprobe(bank_nr);
123 if (p)
124 {
125 if ((retval = p->driver->probe(p)) == ERROR_OK)
126 {
127 command_print(CMD_CTX, "flash '%s' found at 0x%8.8" PRIx32, p->driver->name, p->base);
128 }
129 else if (retval == ERROR_FLASH_BANK_INVALID)
130 {
131 command_print(CMD_CTX, "probing failed for flash bank '#%s' at 0x%8.8" PRIx32,
132 CMD_ARGV[0], p->base);
133 }
134 else
135 {
136 command_print(CMD_CTX, "unknown error when probing flash bank '#%s' at 0x%8.8" PRIx32,
137 CMD_ARGV[0], p->base);
138 }
139 }
140 else
141 {
142 command_print(CMD_CTX, "flash bank '#%s' is out of bounds", CMD_ARGV[0]);
143 }
144
145 return ERROR_OK;
146 }
147
148 COMMAND_HANDLER(handle_flash_erase_check_command)
149 {
150 if (CMD_ARGC != 1)
151 {
152 return ERROR_COMMAND_SYNTAX_ERROR;
153 }
154
155 struct flash_bank *p;
156 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
157 if (ERROR_OK != retval)
158 return retval;
159
160 int j;
161 if ((retval = p->driver->erase_check(p)) == ERROR_OK)
162 {
163 command_print(CMD_CTX, "successfully checked erase state");
164 }
165 else
166 {
167 command_print(CMD_CTX, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32,
168 CMD_ARGV[0], p->base);
169 }
170
171 for (j = 0; j < p->num_sectors; j++)
172 {
173 char *erase_state;
174
175 if (p->sectors[j].is_erased == 0)
176 erase_state = "not erased";
177 else if (p->sectors[j].is_erased == 1)
178 erase_state = "erased";
179 else
180 erase_state = "erase state unknown";
181
182 command_print(CMD_CTX,
183 "\t#%3i: 0x%8.8" PRIx32 " (0x%" PRIx32 " %" PRIi32 "kB) %s",
184 j,
185 p->sectors[j].offset,
186 p->sectors[j].size,
187 p->sectors[j].size >> 10,
188 erase_state);
189 }
190
191 return ERROR_OK;
192 }
193
194 COMMAND_HANDLER(handle_flash_erase_address_command)
195 {
196 struct flash_bank *p;
197 int retval = ERROR_OK;
198 int address;
199 int length;
200 bool do_pad = false;
201 bool do_unlock = false;
202 struct target *target = get_current_target(CMD_CTX);
203
204 while (CMD_ARGC >= 3)
205 {
206 /* Optionally pad out the address range to block/sector
207 * boundaries. We can't know if there's data in that part
208 * of the flash; only do padding if we're told to.
209 */
210 if (strcmp("pad", CMD_ARGV[0]) == 0)
211 {
212 do_pad = true;
213 } else if (strcmp("unlock", CMD_ARGV[0]) == 0)
214 {
215 do_unlock = true;
216 } else
217 {
218 return ERROR_COMMAND_SYNTAX_ERROR;
219 }
220 CMD_ARGC--;
221 CMD_ARGV++;
222 }
223 if (CMD_ARGC != 2)
224 {
225 return ERROR_COMMAND_SYNTAX_ERROR;
226 }
227
228 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
229 COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length);
230
231 if (length <= 0)
232 {
233 command_print(CMD_CTX, "Length must be >0");
234 return ERROR_COMMAND_SYNTAX_ERROR;
235 }
236
237 p = get_flash_bank_by_addr(target, address);
238 if (p == NULL)
239 {
240 return ERROR_FAIL;
241 }
242
243 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
244 flash_set_dirty();
245
246 struct duration bench;
247 duration_start(&bench);
248
249 if (do_unlock)
250 {
251 retval = flash_unlock_address_range(target, address, length);
252 }
253
254 if (retval == ERROR_OK)
255 {
256 retval = flash_erase_address_range(target, do_pad, address, length);
257 }
258
259 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
260 {
261 command_print(CMD_CTX, "erased address 0x%8.8x (length %i)"
262 " in %fs (%0.3f kb/s)", address, length,
263 duration_elapsed(&bench), duration_kbps(&bench, length));
264 }
265
266 return retval;
267 }
268
269 COMMAND_HANDLER(handle_flash_protect_check_command)
270 {
271 if (CMD_ARGC != 1)
272 return ERROR_COMMAND_SYNTAX_ERROR;
273
274 struct flash_bank *p;
275 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
276 if (ERROR_OK != retval)
277 return retval;
278
279 if ((retval = p->driver->protect_check(p)) == ERROR_OK)
280 {
281 command_print(CMD_CTX, "successfully checked protect state");
282 }
283 else if (retval == ERROR_FLASH_OPERATION_FAILED)
284 {
285 command_print(CMD_CTX, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8" PRIx32, CMD_ARGV[0], p->base);
286 }
287 else
288 {
289 command_print(CMD_CTX, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8" PRIx32, CMD_ARGV[0], p->base);
290 }
291
292 return ERROR_OK;
293 }
294
295 static int flash_check_sector_parameters(struct command_context *cmd_ctx,
296 uint32_t first, uint32_t last, uint32_t num_sectors)
297 {
298 if (!(first <= last)) {
299 command_print(cmd_ctx, "ERROR: "
300 "first sector must be <= last sector");
301 return ERROR_FAIL;
302 }
303
304 if (!(last <= (num_sectors - 1))) {
305 command_print(cmd_ctx, "ERROR: last sector must be <= %d",
306 (int) num_sectors - 1);
307 return ERROR_FAIL;
308 }
309
310 return ERROR_OK;
311 }
312
313 COMMAND_HANDLER(handle_flash_erase_command)
314 {
315 if (CMD_ARGC != 3)
316 return ERROR_COMMAND_SYNTAX_ERROR;
317
318 uint32_t bank_nr;
319 uint32_t first;
320 uint32_t last;
321
322 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bank_nr);
323
324 struct flash_bank *p;
325 int retval;
326 retval = get_flash_bank_by_num(bank_nr, &p);
327 if (retval != ERROR_OK)
328 return retval;
329
330 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
331 if (strcmp(CMD_ARGV[2], "last") == 0)
332 last = p->num_sectors - 1;
333 else
334 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
335
336 if ((retval = flash_check_sector_parameters(CMD_CTX,
337 first, last, p->num_sectors)) != ERROR_OK)
338 return retval;
339
340 struct duration bench;
341 duration_start(&bench);
342
343 retval = flash_driver_erase(p, first, last);
344
345 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
346 {
347 command_print(CMD_CTX, "erased sectors %" PRIu32 " "
348 "through %" PRIu32" on flash bank %" PRIu32 " "
349 "in %fs", first, last, bank_nr, duration_elapsed(&bench));
350 }
351
352 return ERROR_OK;
353 }
354
355 COMMAND_HANDLER(handle_flash_protect_command)
356 {
357 if (CMD_ARGC != 4)
358 return ERROR_COMMAND_SYNTAX_ERROR;
359
360 uint32_t bank_nr;
361 uint32_t first;
362 uint32_t last;
363
364 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], bank_nr);
365 struct flash_bank *p;
366 int retval = get_flash_bank_by_num(bank_nr, &p);
367 if (retval != ERROR_OK)
368 return retval;
369
370 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], first);
371 if (strcmp(CMD_ARGV[2], "last") == 0)
372 last = p->num_sectors - 1;
373 else
374 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last);
375
376 bool set;
377 COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set);
378
379 if ((retval = flash_check_sector_parameters(CMD_CTX,
380 first, last, p->num_sectors)) != ERROR_OK)
381 return retval;
382
383 retval = flash_driver_protect(p, set, first, last);
384 if (retval == ERROR_OK) {
385 command_print(CMD_CTX, "%s protection for sectors %i "
386 "through %i on flash bank %i",
387 (set) ? "set" : "cleared", (int) first,
388 (int) last, (int) bank_nr);
389 }
390
391 return ERROR_OK;
392 }
393
394 COMMAND_HANDLER(handle_flash_write_image_command)
395 {
396 struct target *target = get_current_target(CMD_CTX);
397
398 struct image image;
399 uint32_t written;
400
401 int retval;
402
403 if (CMD_ARGC < 1)
404 {
405 return ERROR_COMMAND_SYNTAX_ERROR;
406 }
407
408 /* flash auto-erase is disabled by default*/
409 int auto_erase = 0;
410 bool auto_unlock = false;
411
412 for (;;)
413 {
414 if (strcmp(CMD_ARGV[0], "erase") == 0)
415 {
416 auto_erase = 1;
417 CMD_ARGV++;
418 CMD_ARGC--;
419 command_print(CMD_CTX, "auto erase enabled");
420 } else if (strcmp(CMD_ARGV[0], "unlock") == 0)
421 {
422 auto_unlock = true;
423 CMD_ARGV++;
424 CMD_ARGC--;
425 command_print(CMD_CTX, "auto unlock enabled");
426 } else
427 {
428 break;
429 }
430 }
431
432 if (CMD_ARGC < 1)
433 {
434 return ERROR_COMMAND_SYNTAX_ERROR;
435 }
436
437 if (!target)
438 {
439 LOG_ERROR("no target selected");
440 return ERROR_FAIL;
441 }
442
443 struct duration bench;
444 duration_start(&bench);
445
446 if (CMD_ARGC >= 2)
447 {
448 image.base_address_set = 1;
449 COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address);
450 }
451 else
452 {
453 image.base_address_set = 0;
454 image.base_address = 0x0;
455 }
456
457 image.start_address_set = 0;
458
459 retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL);
460 if (retval != ERROR_OK)
461 {
462 return retval;
463 }
464
465 retval = flash_write_unlock(target, &image, &written, auto_erase, auto_unlock);
466 if (retval != ERROR_OK)
467 {
468 image_close(&image);
469 return retval;
470 }
471
472 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
473 {
474 command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
475 "in %fs (%0.3f kb/s)", written, CMD_ARGV[0],
476 duration_elapsed(&bench), duration_kbps(&bench, written));
477 }
478
479 image_close(&image);
480
481 return retval;
482 }
483
484 COMMAND_HANDLER(handle_flash_fill_command)
485 {
486 int err = ERROR_OK;
487 uint32_t address;
488 uint32_t pattern;
489 uint32_t count;
490 uint32_t wrote = 0;
491 uint32_t cur_size = 0;
492 uint32_t chunk_count;
493 struct target *target = get_current_target(CMD_CTX);
494 uint32_t i;
495 uint32_t wordsize;
496 int retval = ERROR_OK;
497
498 static size_t const chunksize = 1024;
499 uint8_t *chunk = malloc(chunksize);
500 if (chunk == NULL)
501 return ERROR_FAIL;
502
503 uint8_t *readback = malloc(chunksize);
504 if (readback == NULL)
505 {
506 free(chunk);
507 return ERROR_FAIL;
508 }
509
510
511 if (CMD_ARGC != 3)
512 {
513 retval = ERROR_COMMAND_SYNTAX_ERROR;
514 goto done;
515 }
516
517
518 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address);
519 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], pattern);
520 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], count);
521
522 if (count == 0)
523 goto done;
524
525 switch (CMD_NAME[4])
526 {
527 case 'w':
528 wordsize = 4;
529 break;
530 case 'h':
531 wordsize = 2;
532 break;
533 case 'b':
534 wordsize = 1;
535 break;
536 default:
537 retval = ERROR_COMMAND_SYNTAX_ERROR;
538 goto done;
539 }
540
541 chunk_count = MIN(count, (chunksize / wordsize));
542 switch (wordsize)
543 {
544 case 4:
545 for (i = 0; i < chunk_count; i++)
546 {
547 target_buffer_set_u32(target, chunk + i * wordsize, pattern);
548 }
549 break;
550 case 2:
551 for (i = 0; i < chunk_count; i++)
552 {
553 target_buffer_set_u16(target, chunk + i * wordsize, pattern);
554 }
555 break;
556 case 1:
557 memset(chunk, pattern, chunk_count);
558 break;
559 default:
560 LOG_ERROR("BUG: can't happen");
561 exit(-1);
562 }
563
564 struct duration bench;
565 duration_start(&bench);
566
567 for (wrote = 0; wrote < (count*wordsize); wrote += cur_size)
568 {
569 struct flash_bank *bank;
570
571 bank = get_flash_bank_by_addr(target, address);
572 if (bank == NULL)
573 {
574 retval = ERROR_FAIL;
575 goto done;
576 }
577
578 cur_size = MIN((count * wordsize - wrote), chunksize);
579 err = flash_driver_write(bank, chunk, address - bank->base + wrote, cur_size);
580 if (err != ERROR_OK)
581 {
582 retval = err;
583 goto done;
584 }
585
586 err = target_read_buffer(target, address + wrote, cur_size, readback);
587 if (err != ERROR_OK)
588 {
589 retval = err;
590 goto done;
591 }
592
593 unsigned i;
594 for (i = 0; i < cur_size; i++)
595 {
596 if (readback[i]!=chunk[i])
597 {
598 LOG_ERROR("Verfication error address 0x%08" PRIx32 ", read back 0x%02x, expected 0x%02x",
599 address + wrote + i, readback[i], chunk[i]);
600 retval = ERROR_FAIL;
601 goto done;
602 }
603 }
604 }
605
606 if (duration_measure(&bench) == ERROR_OK)
607 {
608 command_print(CMD_CTX, "wrote %" PRIu32 " bytes to 0x%8.8" PRIx32
609 " in %fs (%0.3f kb/s)", wrote, address,
610 duration_elapsed(&bench), duration_kbps(&bench, wrote));
611 }
612
613 done:
614 free(readback);
615 free(chunk);
616
617 return retval;
618 }
619
620 COMMAND_HANDLER(handle_flash_write_bank_command)
621 {
622 uint32_t offset;
623 uint8_t *buffer;
624 struct fileio fileio;
625
626 if (CMD_ARGC != 3)
627 return ERROR_COMMAND_SYNTAX_ERROR;
628
629 struct duration bench;
630 duration_start(&bench);
631
632 struct flash_bank *p;
633 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
634 if (ERROR_OK != retval)
635 return retval;
636
637 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset);
638
639 if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
640 {
641 return ERROR_OK;
642 }
643
644 buffer = malloc(fileio.size);
645 size_t buf_cnt;
646 if (fileio_read(&fileio, fileio.size, buffer, &buf_cnt) != ERROR_OK)
647 {
648 free(buffer);
649 fileio_close(&fileio);
650 return ERROR_OK;
651 }
652
653 retval = flash_driver_write(p, buffer, offset, buf_cnt);
654
655 free(buffer);
656 buffer = NULL;
657
658 if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
659 {
660 command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
661 " at offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
662 (long)fileio.size, CMD_ARGV[1], p->bank_number, offset,
663 duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
664 }
665
666 fileio_close(&fileio);
667
668 return retval;
669 }
670
671 void flash_set_dirty(void)
672 {
673 struct flash_bank *c;
674 int i;
675
676 /* set all flash to require erasing */
677 for (c = flash_bank_list(); c; c = c->next)
678 {
679 for (i = 0; i < c->num_sectors; i++)
680 {
681 c->sectors[i].is_erased = 0;
682 }
683 }
684 }
685
686 static const struct command_registration flash_exec_command_handlers[] = {
687 {
688 .name = "probe",
689 .handler = handle_flash_probe_command,
690 .mode = COMMAND_EXEC,
691 .usage = "bank_id",
692 .help = "Identify a flash bank.",
693 },
694 {
695 .name = "info",
696 .handler = handle_flash_info_command,
697 .mode = COMMAND_EXEC,
698 .usage = "bank_id",
699 .help = "Print information about a flash bank.",
700 },
701 {
702 .name = "erase_check",
703 .handler = handle_flash_erase_check_command,
704 .mode = COMMAND_EXEC,
705 .usage = "bank_id",
706 .help = "Check erase state of all blocks in a "
707 "flash bank.",
708 },
709 {
710 .name = "protect_check",
711 .handler = handle_flash_protect_check_command,
712 .mode = COMMAND_EXEC,
713 .usage = "bank_id",
714 .help = "Check protection state of all blocks in a "
715 "flash bank.",
716 },
717 {
718 .name = "erase_sector",
719 .handler = handle_flash_erase_command,
720 .mode = COMMAND_EXEC,
721 .usage = "bank_id first_sector_num last_sector_num",
722 .help = "Erase a range of sectors in a flash bank.",
723 },
724 {
725 .name = "erase_address",
726 .handler = handle_flash_erase_address_command,
727 .mode = COMMAND_EXEC,
728 .usage = "['pad'] ['unlock'] address length",
729 .help = "Erase flash sectors starting at address and "
730 "continuing for length bytes. If 'pad' is specified, "
731 "data outside that range may also be erased: the start "
732 "address may be decreased, and length increased, so "
733 "that all of the first and last sectors are erased. "
734 "If 'unlock' is specified, then the flash is unprotected "
735 "before erasing.",
736
737 },
738 {
739 .name = "fillw",
740 .handler = handle_flash_fill_command,
741 .mode = COMMAND_EXEC,
742 .usage = "address value n",
743 .help = "Fill n words with 32-bit value, starting at "
744 "word address. (No autoerase.)",
745 },
746 {
747 .name = "fillh",
748 .handler = handle_flash_fill_command,
749 .mode = COMMAND_EXEC,
750 .usage = "address value n",
751 .help = "Fill n halfwords with 16-bit value, starting at "
752 "word address. (No autoerase.)",
753 },
754 {
755 .name = "fillb",
756 .handler = handle_flash_fill_command,
757 .mode = COMMAND_EXEC,
758 .usage = "address value n",
759 .help = "Fill n bytes with 8-bit value, starting at "
760 "word address. (No autoerase.)",
761 },
762 {
763 .name = "write_bank",
764 .handler = handle_flash_write_bank_command,
765 .mode = COMMAND_EXEC,
766 .usage = "bank_id filename offset",
767 .help = "Write binary data from file to flash bank, "
768 "starting at specified byte offset from the "
769 "beginning of the bank.",
770 },
771 {
772 .name = "write_image",
773 .handler = handle_flash_write_image_command,
774 .mode = COMMAND_EXEC,
775 .usage = "[erase] [unlock] filename [offset [file_type]]",
776 .help = "Write an image to flash. Optionally first unprotect "
777 "and/or erase the region to be used. Allow optional "
778 "offset from beginning of bank (defaults to zero)",
779 },
780 {
781 .name = "protect",
782 .handler = handle_flash_protect_command,
783 .mode = COMMAND_EXEC,
784 .usage = "bank_id first_sector [last_sector|'last'] "
785 "('on'|'off')",
786 .help = "Turn protection on or off for a range of sectors "
787 "in a given flash bank.",
788 },
789 COMMAND_REGISTRATION_DONE
790 };
791
792 static int flash_init_drivers(struct command_context *cmd_ctx)
793 {
794 if (!flash_bank_list())
795 return ERROR_OK;
796
797 struct command *parent = command_find_in_context(cmd_ctx, "flash");
798 return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
799 }
800
801
802 COMMAND_HANDLER(handle_flash_bank_command)
803 {
804 if (CMD_ARGC < 7)
805 {
806 LOG_ERROR("usage: flash bank <name> <driver> "
807 "<base> <size> <chip_width> <bus_width> <target>");
808 return ERROR_COMMAND_SYNTAX_ERROR;
809 }
810 // save bank name and advance arguments for compatibility
811 const char *bank_name = *CMD_ARGV++;
812 CMD_ARGC--;
813
814 struct target *target;
815 if ((target = get_target(CMD_ARGV[5])) == NULL)
816 {
817 LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
818 return ERROR_FAIL;
819 }
820
821 const char *driver_name = CMD_ARGV[0];
822 struct flash_driver *driver = flash_driver_find_by_name(driver_name);
823 if (NULL == driver)
824 {
825 /* no matching flash driver found */
826 LOG_ERROR("flash driver '%s' not found", driver_name);
827 return ERROR_FAIL;
828 }
829
830 /* register flash specific commands */
831 if (NULL != driver->commands)
832 {
833 int retval = register_commands(CMD_CTX, NULL,
834 driver->commands);
835 if (ERROR_OK != retval)
836 {
837 LOG_ERROR("couldn't register '%s' commands",
838 driver_name);
839 return ERROR_FAIL;
840 }
841 }
842
843 struct flash_bank *c = malloc(sizeof(*c));
844 c->name = strdup(bank_name);
845 c->target = target;
846 c->driver = driver;
847 c->driver_priv = NULL;
848 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base);
849 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
850 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
851 COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
852 c->num_sectors = 0;
853 c->sectors = NULL;
854 c->next = NULL;
855
856 int retval;
857 retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
858 if (ERROR_OK != retval)
859 {
860 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32,
861 driver_name, c->base);
862 free(c);
863 return retval;
864 }
865
866 flash_bank_add(c);
867
868 return ERROR_OK;
869 }
870
871 COMMAND_HANDLER(handle_flash_banks_command)
872 {
873 if (CMD_ARGC != 0)
874 return ERROR_INVALID_ARGUMENTS;
875
876 unsigned n = 0;
877 for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++)
878 {
879 LOG_USER("#%u: %s at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
880 "buswidth %u, chipwidth %u", n,
881 p->driver->name, p->base, p->size,
882 p->bus_width, p->chip_width);
883 }
884 return ERROR_OK;
885 }
886
887 static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
888 {
889 if (argc != 1)
890 {
891 Jim_WrongNumArgs(interp, 1, argv,
892 "no arguments to 'flash list' command");
893 return JIM_ERR;
894 }
895
896 Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
897
898 for (struct flash_bank *p = flash_bank_list(); p; p = p->next)
899 {
900 Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
901
902 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
903 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
904 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
905 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
906 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
907 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
908 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
909 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
910 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
911 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
912
913 Jim_ListAppendElement(interp, list, elem);
914 }
915
916 Jim_SetResult(interp, list);
917
918 return JIM_OK;
919 }
920
921
922 COMMAND_HANDLER(handle_flash_init_command)
923 {
924 if (CMD_ARGC != 0)
925 return ERROR_COMMAND_SYNTAX_ERROR;
926
927 static bool flash_initialized = false;
928 if (flash_initialized)
929 {
930 LOG_INFO("'flash init' has already been called");
931 return ERROR_OK;
932 }
933 flash_initialized = true;
934
935 LOG_DEBUG("Initializing flash devices...");
936 return flash_init_drivers(CMD_CTX);
937 }
938
939 static const struct command_registration flash_config_command_handlers[] = {
940 {
941 .name = "bank",
942 .handler = handle_flash_bank_command,
943 .mode = COMMAND_CONFIG,
944 .usage = "bank_id driver_name base_address size_bytes "
945 "chip_width_bytes bus_width_bytes target "
946 "[driver_options ...]",
947 .help = "Define a new bank with the given name, "
948 "using the specified NOR flash driver.",
949 },
950 {
951 .name = "init",
952 .mode = COMMAND_CONFIG,
953 .handler = handle_flash_init_command,
954 .help = "Initialize flash devices.",
955 },
956 {
957 .name = "banks",
958 .mode = COMMAND_ANY,
959 .handler = handle_flash_banks_command,
960 .help = "Display table with information about flash banks.",
961 },
962 {
963 .name = "list",
964 .mode = COMMAND_ANY,
965 .jim_handler = jim_flash_list,
966 .help = "Returns a list of details about the flash banks.",
967 },
968 COMMAND_REGISTRATION_DONE
969 };
970 static const struct command_registration flash_command_handlers[] = {
971 {
972 .name = "flash",
973 .mode = COMMAND_ANY,
974 .help = "NOR flash command group",
975 .chain = flash_config_command_handlers,
976 },
977 COMMAND_REGISTRATION_DONE
978 };
979
980 int flash_register_commands(struct command_context *cmd_ctx)
981 {
982 return register_commands(cmd_ctx, NULL, flash_command_handlers);
983 }

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)