916ebf73848153af10e621bb78ab68c6723cf551
[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 "#%d : %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.8" PRIx32 " (length %" PRIi32 ")"
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 %d "
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 %d",
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 COMMAND_HANDLER(handle_flash_padded_value_command)
609 {
610 if (CMD_ARGC != 2)
611 return ERROR_COMMAND_SYNTAX_ERROR;
612
613 struct flash_bank *p;
614 int retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &p);
615 if (ERROR_OK != retval)
616 return retval;
617
618 COMMAND_PARSE_NUMBER(u8, CMD_ARGV[1], p->default_padded_value);
619
620 command_print(CMD_CTX, "Default padded value set to 0x%" PRIx8 " for flash bank %u", \
621 p->default_padded_value, p->bank_number);
622
623 return retval;
624 }
625
626 static const struct command_registration flash_exec_command_handlers[] = {
627 {
628 .name = "probe",
629 .handler = handle_flash_probe_command,
630 .mode = COMMAND_EXEC,
631 .usage = "bank_id",
632 .help = "Identify a flash bank.",
633 },
634 {
635 .name = "info",
636 .handler = handle_flash_info_command,
637 .mode = COMMAND_EXEC,
638 .usage = "bank_id",
639 .help = "Print information about a flash bank.",
640 },
641 {
642 .name = "erase_check",
643 .handler = handle_flash_erase_check_command,
644 .mode = COMMAND_EXEC,
645 .usage = "bank_id",
646 .help = "Check erase state of all blocks in a "
647 "flash bank.",
648 },
649 {
650 .name = "erase_sector",
651 .handler = handle_flash_erase_command,
652 .mode = COMMAND_EXEC,
653 .usage = "bank_id first_sector_num last_sector_num",
654 .help = "Erase a range of sectors in a flash bank.",
655 },
656 {
657 .name = "erase_address",
658 .handler = handle_flash_erase_address_command,
659 .mode = COMMAND_EXEC,
660 .usage = "['pad'] ['unlock'] address length",
661 .help = "Erase flash sectors starting at address and "
662 "continuing for length bytes. If 'pad' is specified, "
663 "data outside that range may also be erased: the start "
664 "address may be decreased, and length increased, so "
665 "that all of the first and last sectors are erased. "
666 "If 'unlock' is specified, then the flash is unprotected "
667 "before erasing.",
668
669 },
670 {
671 .name = "fillw",
672 .handler = handle_flash_fill_command,
673 .mode = COMMAND_EXEC,
674 .usage = "address value n",
675 .help = "Fill n words with 32-bit value, starting at "
676 "word address. (No autoerase.)",
677 },
678 {
679 .name = "fillh",
680 .handler = handle_flash_fill_command,
681 .mode = COMMAND_EXEC,
682 .usage = "address value n",
683 .help = "Fill n halfwords with 16-bit value, starting at "
684 "word address. (No autoerase.)",
685 },
686 {
687 .name = "fillb",
688 .handler = handle_flash_fill_command,
689 .mode = COMMAND_EXEC,
690 .usage = "address value n",
691 .help = "Fill n bytes with 8-bit value, starting at "
692 "word address. (No autoerase.)",
693 },
694 {
695 .name = "write_bank",
696 .handler = handle_flash_write_bank_command,
697 .mode = COMMAND_EXEC,
698 .usage = "bank_id filename offset",
699 .help = "Write binary data from file to flash bank, "
700 "starting at specified byte offset from the "
701 "beginning of the bank.",
702 },
703 {
704 .name = "write_image",
705 .handler = handle_flash_write_image_command,
706 .mode = COMMAND_EXEC,
707 .usage = "[erase] [unlock] filename [offset [file_type]]",
708 .help = "Write an image to flash. Optionally first unprotect "
709 "and/or erase the region to be used. Allow optional "
710 "offset from beginning of bank (defaults to zero)",
711 },
712 {
713 .name = "protect",
714 .handler = handle_flash_protect_command,
715 .mode = COMMAND_EXEC,
716 .usage = "bank_id first_sector [last_sector|'last'] "
717 "('on'|'off')",
718 .help = "Turn protection on or off for a range of sectors "
719 "in a given flash bank.",
720 },
721 {
722 .name = "padded_value",
723 .handler = handle_flash_padded_value_command,
724 .mode = COMMAND_EXEC,
725 .usage = "bank_id value",
726 .help = "Set default flash padded value",
727 },
728 COMMAND_REGISTRATION_DONE
729 };
730
731 static int flash_init_drivers(struct command_context *cmd_ctx)
732 {
733 if (!flash_bank_list())
734 return ERROR_OK;
735
736 struct command *parent = command_find_in_context(cmd_ctx, "flash");
737 return register_commands(cmd_ctx, parent, flash_exec_command_handlers);
738 }
739
740 COMMAND_HANDLER(handle_flash_bank_command)
741 {
742 if (CMD_ARGC < 7) {
743 LOG_ERROR("usage: flash bank <name> <driver> "
744 "<base> <size> <chip_width> <bus_width> <target>");
745 return ERROR_COMMAND_SYNTAX_ERROR;
746 }
747 /* save bank name and advance arguments for compatibility */
748 const char *bank_name = *CMD_ARGV++;
749 CMD_ARGC--;
750
751 struct target *target = get_target(CMD_ARGV[5]);
752 if (target == NULL) {
753 LOG_ERROR("target '%s' not defined", CMD_ARGV[5]);
754 return ERROR_FAIL;
755 }
756
757 const char *driver_name = CMD_ARGV[0];
758 struct flash_driver *driver = flash_driver_find_by_name(driver_name);
759 if (NULL == driver) {
760 /* no matching flash driver found */
761 LOG_ERROR("flash driver '%s' not found", driver_name);
762 return ERROR_FAIL;
763 }
764
765 /* check the flash bank name is unique */
766 if (get_flash_bank_by_name_noprobe(bank_name) != NULL) {
767 /* flash bank name already exists */
768 LOG_ERROR("flash bank name '%s' already exists", bank_name);
769 return ERROR_FAIL;
770 }
771
772 /* register flash specific commands */
773 if (NULL != driver->commands) {
774 int retval = register_commands(CMD_CTX, NULL,
775 driver->commands);
776 if (ERROR_OK != retval) {
777 LOG_ERROR("couldn't register '%s' commands",
778 driver_name);
779 return ERROR_FAIL;
780 }
781 }
782
783 struct flash_bank *c = malloc(sizeof(*c));
784 c->name = strdup(bank_name);
785 c->target = target;
786 c->driver = driver;
787 c->driver_priv = NULL;
788 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], c->base);
789 COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size);
790 COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width);
791 COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width);
792 c->default_padded_value = 0xff;
793 c->num_sectors = 0;
794 c->sectors = NULL;
795 c->next = NULL;
796
797 int retval;
798 retval = CALL_COMMAND_HANDLER(driver->flash_bank_command, c);
799 if (ERROR_OK != retval) {
800 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32 "Usage %s",
801 driver_name, c->base, driver->usage);
802 free(c);
803 return retval;
804 }
805
806 if (driver->usage == NULL)
807 LOG_DEBUG("'%s' driver usage field missing", driver_name);
808
809 flash_bank_add(c);
810
811 return ERROR_OK;
812 }
813
814 COMMAND_HANDLER(handle_flash_banks_command)
815 {
816 if (CMD_ARGC != 0)
817 return ERROR_COMMAND_SYNTAX_ERROR;
818
819 unsigned n = 0;
820 for (struct flash_bank *p = flash_bank_list(); p; p = p->next, n++) {
821 LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32 ", size 0x%8.8" PRIx32 ", "
822 "buswidth %u, chipwidth %u", p->bank_number,
823 p->name, p->driver->name, p->base, p->size,
824 p->bus_width, p->chip_width);
825 }
826 return ERROR_OK;
827 }
828
829 static int jim_flash_list(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
830 {
831 if (argc != 1) {
832 Jim_WrongNumArgs(interp, 1, argv,
833 "no arguments to 'flash list' command");
834 return JIM_ERR;
835 }
836
837 Jim_Obj *list = Jim_NewListObj(interp, NULL, 0);
838
839 for (struct flash_bank *p = flash_bank_list(); p; p = p->next) {
840 Jim_Obj *elem = Jim_NewListObj(interp, NULL, 0);
841
842 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "name", -1));
843 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, p->driver->name, -1));
844 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "base", -1));
845 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->base));
846 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "size", -1));
847 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->size));
848 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "bus_width", -1));
849 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->bus_width));
850 Jim_ListAppendElement(interp, elem, Jim_NewStringObj(interp, "chip_width", -1));
851 Jim_ListAppendElement(interp, elem, Jim_NewIntObj(interp, p->chip_width));
852
853 Jim_ListAppendElement(interp, list, elem);
854 }
855
856 Jim_SetResult(interp, list);
857
858 return JIM_OK;
859 }
860
861 COMMAND_HANDLER(handle_flash_init_command)
862 {
863 if (CMD_ARGC != 0)
864 return ERROR_COMMAND_SYNTAX_ERROR;
865
866 static bool flash_initialized;
867 if (flash_initialized) {
868 LOG_INFO("'flash init' has already been called");
869 return ERROR_OK;
870 }
871 flash_initialized = true;
872
873 LOG_DEBUG("Initializing flash devices...");
874 return flash_init_drivers(CMD_CTX);
875 }
876
877 static const struct command_registration flash_config_command_handlers[] = {
878 {
879 .name = "bank",
880 .handler = handle_flash_bank_command,
881 .mode = COMMAND_CONFIG,
882 .usage = "bank_id driver_name base_address size_bytes "
883 "chip_width_bytes bus_width_bytes target "
884 "[driver_options ...]",
885 .help = "Define a new bank with the given name, "
886 "using the specified NOR flash driver.",
887 },
888 {
889 .name = "init",
890 .mode = COMMAND_CONFIG,
891 .handler = handle_flash_init_command,
892 .help = "Initialize flash devices.",
893 },
894 {
895 .name = "banks",
896 .mode = COMMAND_ANY,
897 .handler = handle_flash_banks_command,
898 .help = "Display table with information about flash banks.",
899 },
900 {
901 .name = "list",
902 .mode = COMMAND_ANY,
903 .jim_handler = jim_flash_list,
904 .help = "Returns a list of details about the flash banks.",
905 },
906 COMMAND_REGISTRATION_DONE
907 };
908 static const struct command_registration flash_command_handlers[] = {
909 {
910 .name = "flash",
911 .mode = COMMAND_ANY,
912 .help = "NOR flash command group",
913 .chain = flash_config_command_handlers,
914 },
915 COMMAND_REGISTRATION_DONE
916 };
917
918 int flash_register_commands(struct command_context *cmd_ctx)
919 {
920 return register_commands(cmd_ctx, NULL, flash_command_handlers);
921 }

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)