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

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)