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> *
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. *
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. *
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 ***************************************************************************/
26 #include <helper/time_support.h>
27 #include <target/image.h>
31 * Implements Tcl commands used to access NOR flash facilities.
34 COMMAND_HELPER(flash_command_get_bank
, unsigned name_index
,
35 struct flash_bank
**bank
)
37 const char *name
= CMD_ARGV
[name_index
];
38 int retval
= get_flash_bank_by_name(name
, bank
);
39 if (retval
!= ERROR_OK
)
45 COMMAND_PARSE_NUMBER(uint
, name
, bank_num
);
47 return get_flash_bank_by_num(bank_num
, bank
);
50 COMMAND_HANDLER(handle_flash_info_command
)
57 return ERROR_COMMAND_SYNTAX_ERROR
;
59 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
60 if (retval
!= ERROR_OK
)
66 /* attempt auto probe */
67 retval
= p
->driver
->auto_probe(p
);
68 if (retval
!= ERROR_OK
)
71 /* We must query the hardware to avoid printing stale information! */
72 retval
= p
->driver
->protect_check(p
);
73 if (retval
!= ERROR_OK
)
76 command_print(CMD_CTX
,
77 "#%" PRIu32
" : %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
78 ", buswidth %i, chipwidth %i",
85 for (j
= 0; j
< p
->num_sectors
; j
++) {
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";
93 protect_state
= "protection state unknown";
95 command_print(CMD_CTX
,
96 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
100 p
->sectors
[j
].size
>> 10,
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
);
109 LOG_ERROR("error retrieving flash info");
116 COMMAND_HANDLER(handle_flash_probe_command
)
118 struct flash_bank
*p
;
122 return ERROR_COMMAND_SYNTAX_ERROR
;
124 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
125 if (retval
!= ERROR_OK
)
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
,
136 command_print(CMD_CTX
, "flash bank '#%s' is out of bounds", CMD_ARGV
[0]);
143 COMMAND_HANDLER(handle_flash_erase_check_command
)
146 return ERROR_COMMAND_SYNTAX_ERROR
;
148 struct flash_bank
*p
;
149 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
150 if (ERROR_OK
!= retval
)
154 retval
= p
->driver
->erase_check(p
);
155 if (retval
== ERROR_OK
)
156 command_print(CMD_CTX
, "successfully checked erase state");
158 command_print(CMD_CTX
,
159 "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32
,
164 for (j
= 0; j
< p
->num_sectors
; j
++) {
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";
172 erase_state
= "erase state unknown";
174 command_print(CMD_CTX
,
175 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
177 p
->sectors
[j
].offset
,
179 p
->sectors
[j
].size
>> 10,
186 COMMAND_HANDLER(handle_flash_erase_address_command
)
188 struct flash_bank
*p
;
189 int retval
= ERROR_OK
;
193 bool do_unlock
= false;
194 struct target
*target
= get_current_target(CMD_CTX
);
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.
201 if (strcmp("pad", CMD_ARGV
[0]) == 0)
203 else if (strcmp("unlock", CMD_ARGV
[0]) == 0)
206 return ERROR_COMMAND_SYNTAX_ERROR
;
211 return ERROR_COMMAND_SYNTAX_ERROR
;
213 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
214 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], length
);
217 command_print(CMD_CTX
, "Length must be >0");
218 return ERROR_COMMAND_SYNTAX_ERROR
;
221 retval
= get_flash_bank_by_addr(target
, address
, true, &p
);
222 if (retval
!= ERROR_OK
)
225 /* We can't know if we did a resume + halt, in which case we no longer know the erased state
229 struct duration bench
;
230 duration_start(&bench
);
233 retval
= flash_unlock_address_range(target
, address
, length
);
235 if (retval
== ERROR_OK
)
236 retval
= flash_erase_address_range(target
, do_pad
, address
, length
);
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
));
247 static int flash_check_sector_parameters(struct command_context
*cmd_ctx
,
248 uint32_t first
, uint32_t last
, uint32_t num_sectors
)
250 if (!(first
<= last
)) {
251 command_print(cmd_ctx
, "ERROR: "
252 "first sector must be <= last sector");
256 if (!(last
<= (num_sectors
- 1))) {
257 command_print(cmd_ctx
, "ERROR: last sector must be <= %d",
258 (int) num_sectors
- 1);
265 COMMAND_HANDLER(handle_flash_erase_command
)
268 return ERROR_COMMAND_SYNTAX_ERROR
;
273 struct flash_bank
*p
;
276 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
277 if (retval
!= ERROR_OK
)
280 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
281 if (strcmp(CMD_ARGV
[2], "last") == 0)
282 last
= p
->num_sectors
- 1;
284 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
286 retval
= flash_check_sector_parameters(CMD_CTX
, first
, last
, p
->num_sectors
);
287 if (retval
!= ERROR_OK
)
290 struct duration bench
;
291 duration_start(&bench
);
293 retval
= flash_driver_erase(p
, first
, last
);
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
));
304 COMMAND_HANDLER(handle_flash_protect_command
)
307 return ERROR_COMMAND_SYNTAX_ERROR
;
312 struct flash_bank
*p
;
315 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
316 if (retval
!= ERROR_OK
)
319 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
320 if (strcmp(CMD_ARGV
[2], "last") == 0)
321 last
= p
->num_sectors
- 1;
323 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
326 COMMAND_PARSE_ON_OFF(CMD_ARGV
[3], set
);
328 retval
= flash_check_sector_parameters(CMD_CTX
, first
, last
, p
->num_sectors
);
329 if (retval
!= ERROR_OK
)
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
);
343 COMMAND_HANDLER(handle_flash_write_image_command
)
345 struct target
*target
= get_current_target(CMD_CTX
);
353 return ERROR_COMMAND_SYNTAX_ERROR
;
355 /* flash auto-erase is disabled by default*/
357 bool auto_unlock
= false;
360 if (strcmp(CMD_ARGV
[0], "erase") == 0) {
364 command_print(CMD_CTX
, "auto erase enabled");
365 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0) {
369 command_print(CMD_CTX
, "auto unlock enabled");
375 return ERROR_COMMAND_SYNTAX_ERROR
;
378 LOG_ERROR("no target selected");
382 struct duration bench
;
383 duration_start(&bench
);
386 image
.base_address_set
= 1;
387 COMMAND_PARSE_NUMBER(llong
, CMD_ARGV
[1], image
.base_address
);
389 image
.base_address_set
= 0;
390 image
.base_address
= 0x0;
393 image
.start_address_set
= 0;
395 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
396 if (retval
!= ERROR_OK
)
399 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
400 if (retval
!= ERROR_OK
) {
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
));
416 COMMAND_HANDLER(handle_flash_fill_command
)
423 uint32_t cur_size
= 0;
424 uint32_t chunk_count
;
425 struct target
*target
= get_current_target(CMD_CTX
);
428 int retval
= ERROR_OK
;
430 static size_t const chunksize
= 1024;
431 uint8_t *chunk
= NULL
, *readback
= NULL
;
434 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
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
);
442 chunk
= malloc(chunksize
);
446 readback
= malloc(chunksize
);
447 if (readback
== NULL
) {
455 switch (CMD_NAME
[4]) {
466 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
470 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
473 for (i
= 0; i
< chunk_count
; i
++)
474 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
477 for (i
= 0; i
< chunk_count
; i
++)
478 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
481 memset(chunk
, pattern
, chunk_count
);
484 LOG_ERROR("BUG: can't happen");
488 struct duration bench
;
489 duration_start(&bench
);
491 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
) {
492 struct flash_bank
*bank
;
494 retval
= get_flash_bank_by_addr(target
, address
, true, &bank
);
495 if (retval
!= ERROR_OK
)
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
) {
505 err
= flash_driver_read(bank
, readback
, address
- bank
->base
+ wrote
, cur_size
);
506 if (err
!= ERROR_OK
) {
511 for (i
= 0; i
< cur_size
; i
++) {
512 if (readback
[i
] != chunk
[i
]) {
514 "Verification error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
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
));
537 COMMAND_HANDLER(handle_flash_write_bank_command
)
541 struct fileio fileio
;
544 return ERROR_COMMAND_SYNTAX_ERROR
;
546 struct duration bench
;
547 duration_start(&bench
);
549 struct flash_bank
*p
;
550 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
551 if (ERROR_OK
!= retval
)
554 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
556 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
560 retval
= fileio_size(&fileio
, &filesize
);
561 if (retval
!= ERROR_OK
) {
562 fileio_close(&fileio
);
566 buffer
= malloc(filesize
);
567 if (buffer
== NULL
) {
568 fileio_close(&fileio
);
569 LOG_ERROR("Out of memory");
573 if (fileio_read(&fileio
, filesize
, buffer
, &buf_cnt
) != ERROR_OK
) {
575 fileio_close(&fileio
);
579 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
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
));
591 fileio_close(&fileio
);
596 void flash_set_dirty(void)
598 struct flash_bank
*c
;
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;
608 COMMAND_HANDLER(handle_flash_padded_value_command
)
611 return ERROR_COMMAND_SYNTAX_ERROR
;
613 struct flash_bank
*p
;
614 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
615 if (ERROR_OK
!= retval
)
618 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[1], p
->default_padded_value
);
620 command_print(CMD_CTX
, "Default padded value set to 0x%" PRIx8
" for flash bank %u", \
621 p
->default_padded_value
, p
->bank_number
);
626 static const struct command_registration flash_exec_command_handlers
[] = {
629 .handler
= handle_flash_probe_command
,
630 .mode
= COMMAND_EXEC
,
632 .help
= "Identify a flash bank.",
636 .handler
= handle_flash_info_command
,
637 .mode
= COMMAND_EXEC
,
639 .help
= "Print information about a flash bank.",
642 .name
= "erase_check",
643 .handler
= handle_flash_erase_check_command
,
644 .mode
= COMMAND_EXEC
,
646 .help
= "Check erase state of all blocks in a "
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.",
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 "
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.)",
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.)",
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.)",
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.",
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)",
714 .handler
= handle_flash_protect_command
,
715 .mode
= COMMAND_EXEC
,
716 .usage
= "bank_id first_sector [last_sector|'last'] "
718 .help
= "Turn protection on or off for a range of sectors "
719 "in a given flash bank.",
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",
728 COMMAND_REGISTRATION_DONE
731 static int flash_init_drivers(struct command_context
*cmd_ctx
)
733 if (!flash_bank_list())
736 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
737 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
740 COMMAND_HANDLER(handle_flash_bank_command
)
743 LOG_ERROR("usage: flash bank <name> <driver> "
744 "<base> <size> <chip_width> <bus_width> <target>");
745 return ERROR_COMMAND_SYNTAX_ERROR
;
747 /* save bank name and advance arguments for compatibility */
748 const char *bank_name
= *CMD_ARGV
++;
751 struct target
*target
= get_target(CMD_ARGV
[5]);
752 if (target
== NULL
) {
753 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
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
);
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
);
772 /* register flash specific commands */
773 if (NULL
!= driver
->commands
) {
774 int retval
= register_commands(CMD_CTX
, NULL
,
776 if (ERROR_OK
!= retval
) {
777 LOG_ERROR("couldn't register '%s' commands",
783 struct flash_bank
*c
= malloc(sizeof(*c
));
784 c
->name
= strdup(bank_name
);
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;
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
);
806 if (driver
->usage
== NULL
)
807 LOG_DEBUG("'%s' driver usage field missing", driver_name
);
814 COMMAND_HANDLER(handle_flash_banks_command
)
817 return ERROR_COMMAND_SYNTAX_ERROR
;
820 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++) {
821 LOG_USER("#%" PRIu32
" : %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
);
829 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
* const *argv
)
832 Jim_WrongNumArgs(interp
, 1, argv
,
833 "no arguments to 'flash list' command");
837 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
839 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
) {
840 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
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
));
853 Jim_ListAppendElement(interp
, list
, elem
);
856 Jim_SetResult(interp
, list
);
861 COMMAND_HANDLER(handle_flash_init_command
)
864 return ERROR_COMMAND_SYNTAX_ERROR
;
866 static bool flash_initialized
;
867 if (flash_initialized
) {
868 LOG_INFO("'flash init' has already been called");
871 flash_initialized
= true;
873 LOG_DEBUG("Initializing flash devices...");
874 return flash_init_drivers(CMD_CTX
);
877 static const struct command_registration flash_config_command_handlers
[] = {
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.",
890 .mode
= COMMAND_CONFIG
,
891 .handler
= handle_flash_init_command
,
892 .help
= "Initialize flash devices.",
897 .handler
= handle_flash_banks_command
,
898 .help
= "Display table with information about flash banks.",
903 .jim_handler
= jim_flash_list
,
904 .help
= "Returns a list of details about the flash banks.",
906 COMMAND_REGISTRATION_DONE
908 static const struct command_registration flash_command_handlers
[] = {
912 .help
= "NOR flash command group",
913 .chain
= flash_config_command_handlers
,
915 COMMAND_REGISTRATION_DONE
918 int flash_register_commands(struct command_context
*cmd_ctx
)
920 return register_commands(cmd_ctx
, NULL
, flash_command_handlers
);
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)