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

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)