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

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)