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

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)