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

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)