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 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 *bank
= get_flash_bank_by_name(name
);
43 COMMAND_PARSE_NUMBER(uint
, name
, bank_num
);
45 return get_flash_bank_by_num(bank_num
, bank
);
49 COMMAND_HANDLER(handle_flash_info_command
)
57 return ERROR_COMMAND_SYNTAX_ERROR
;
60 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], bank_nr
);
62 for (p
= flash_bank_list(); p
; p
= p
->next
, i
++)
69 /* attempt auto probe */
70 if ((retval
= p
->driver
->auto_probe(p
)) != ERROR_OK
)
73 command_print(CMD_CTX
,
74 "#%" PRIi32
" : %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", buswidth %i, chipwidth %i",
81 for (j
= 0; j
< p
->num_sectors
; j
++)
85 if (p
->sectors
[j
].is_protected
== 0)
86 protect_state
= "not protected";
87 else if (p
->sectors
[j
].is_protected
== 1)
88 protect_state
= "protected";
90 protect_state
= "protection state unknown";
92 command_print(CMD_CTX
,
93 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
97 p
->sectors
[j
].size
>> 10,
101 *buf
= '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
102 retval
= p
->driver
->info(p
, buf
, sizeof(buf
));
103 command_print(CMD_CTX
, "%s", buf
);
104 if (retval
!= ERROR_OK
)
105 LOG_ERROR("error retrieving flash info (%d)", retval
);
111 COMMAND_HANDLER(handle_flash_probe_command
)
117 return ERROR_COMMAND_SYNTAX_ERROR
;
121 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], bank_nr
);
122 struct flash_bank
*p
= get_flash_bank_by_num_noprobe(bank_nr
);
125 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
127 command_print(CMD_CTX
, "flash '%s' found at 0x%8.8" PRIx32
, p
->driver
->name
, p
->base
);
129 else if (retval
== ERROR_FLASH_BANK_INVALID
)
131 command_print(CMD_CTX
, "probing failed for flash bank '#%s' at 0x%8.8" PRIx32
,
132 CMD_ARGV
[0], p
->base
);
136 command_print(CMD_CTX
, "unknown error when probing flash bank '#%s' at 0x%8.8" PRIx32
,
137 CMD_ARGV
[0], p
->base
);
142 command_print(CMD_CTX
, "flash bank '#%s' is out of bounds", CMD_ARGV
[0]);
148 COMMAND_HANDLER(handle_flash_erase_check_command
)
152 return ERROR_COMMAND_SYNTAX_ERROR
;
155 struct flash_bank
*p
;
156 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
157 if (ERROR_OK
!= retval
)
161 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
163 command_print(CMD_CTX
, "successfully checked erase state");
167 command_print(CMD_CTX
, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32
,
168 CMD_ARGV
[0], p
->base
);
171 for (j
= 0; j
< p
->num_sectors
; j
++)
175 if (p
->sectors
[j
].is_erased
== 0)
176 erase_state
= "not erased";
177 else if (p
->sectors
[j
].is_erased
== 1)
178 erase_state
= "erased";
180 erase_state
= "erase state unknown";
182 command_print(CMD_CTX
,
183 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
185 p
->sectors
[j
].offset
,
187 p
->sectors
[j
].size
>> 10,
194 COMMAND_HANDLER(handle_flash_erase_address_command
)
196 struct flash_bank
*p
;
201 struct target
*target
= get_current_target(CMD_CTX
);
205 /* Optionally pad out the address range to block/sector
206 * boundaries. We can't know if there's data in that part
207 * of the flash; only do padding if we're told to.
209 if (strcmp("pad", CMD_ARGV
[0]) != 0)
210 return ERROR_COMMAND_SYNTAX_ERROR
;
216 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], address
);
217 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], length
);
220 return ERROR_COMMAND_SYNTAX_ERROR
;
225 command_print(CMD_CTX
, "Length must be >0");
226 return ERROR_COMMAND_SYNTAX_ERROR
;
229 p
= get_flash_bank_by_addr(target
, address
);
235 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
238 struct duration bench
;
239 duration_start(&bench
);
241 retval
= flash_erase_address_range(target
, do_pad
, address
, length
);
243 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
245 command_print(CMD_CTX
, "erased address 0x%8.8x (length %i)"
246 " in %fs (%0.3f kb/s)", address
, length
,
247 duration_elapsed(&bench
), duration_kbps(&bench
, length
));
253 COMMAND_HANDLER(handle_flash_protect_check_command
)
256 return ERROR_COMMAND_SYNTAX_ERROR
;
258 struct flash_bank
*p
;
259 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
260 if (ERROR_OK
!= retval
)
263 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
265 command_print(CMD_CTX
, "successfully checked protect state");
267 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
269 command_print(CMD_CTX
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
273 command_print(CMD_CTX
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
279 static int flash_check_sector_parameters(struct command_context
*cmd_ctx
,
280 uint32_t first
, uint32_t last
, uint32_t num_sectors
)
282 if (!(first
<= last
)) {
283 command_print(cmd_ctx
, "ERROR: "
284 "first sector must be <= last sector");
288 if (!(last
<= (num_sectors
- 1))) {
289 command_print(cmd_ctx
, "ERROR: last sector must be <= %d",
290 (int) num_sectors
- 1);
297 COMMAND_HANDLER(handle_flash_erase_command
)
300 return ERROR_COMMAND_SYNTAX_ERROR
;
306 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
308 struct flash_bank
*p
;
310 retval
= get_flash_bank_by_num(bank_nr
, &p
);
311 if (retval
!= ERROR_OK
)
314 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
315 if (strcmp(CMD_ARGV
[2], "last") == 0)
316 last
= p
->num_sectors
- 1;
318 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
320 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
321 first
, last
, p
->num_sectors
)) != ERROR_OK
)
324 struct duration bench
;
325 duration_start(&bench
);
327 retval
= flash_driver_erase(p
, first
, last
);
329 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
331 command_print(CMD_CTX
, "erased sectors %" PRIu32
" "
332 "through %" PRIu32
" on flash bank %" PRIu32
" "
333 "in %fs", first
, last
, bank_nr
, duration_elapsed(&bench
));
339 COMMAND_HANDLER(handle_flash_protect_command
)
342 return ERROR_COMMAND_SYNTAX_ERROR
;
348 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
349 struct flash_bank
*p
;
350 int retval
= get_flash_bank_by_num(bank_nr
, &p
);
351 if (retval
!= ERROR_OK
)
354 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
355 if (strcmp(CMD_ARGV
[2], "last") == 0)
356 last
= p
->num_sectors
- 1;
358 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
361 COMMAND_PARSE_ON_OFF(CMD_ARGV
[3], set
);
363 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
364 first
, last
, p
->num_sectors
)) != ERROR_OK
)
367 retval
= flash_driver_protect(p
, set
, first
, last
);
368 if (retval
== ERROR_OK
) {
369 command_print(CMD_CTX
, "%s protection for sectors %i "
370 "through %i on flash bank %i",
371 (set
) ? "set" : "cleared", (int) first
,
372 (int) last
, (int) bank_nr
);
378 COMMAND_HANDLER(handle_flash_write_image_command
)
380 struct target
*target
= get_current_target(CMD_CTX
);
389 return ERROR_COMMAND_SYNTAX_ERROR
;
392 /* flash auto-erase is disabled by default*/
394 bool auto_unlock
= false;
398 if (strcmp(CMD_ARGV
[0], "erase") == 0)
403 command_print(CMD_CTX
, "auto erase enabled");
404 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0)
409 command_print(CMD_CTX
, "auto unlock enabled");
418 return ERROR_COMMAND_SYNTAX_ERROR
;
423 LOG_ERROR("no target selected");
427 struct duration bench
;
428 duration_start(&bench
);
432 image
.base_address_set
= 1;
433 COMMAND_PARSE_NUMBER(llong
, CMD_ARGV
[1], image
.base_address
);
437 image
.base_address_set
= 0;
438 image
.base_address
= 0x0;
441 image
.start_address_set
= 0;
443 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
444 if (retval
!= ERROR_OK
)
449 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
450 if (retval
!= ERROR_OK
)
456 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
458 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes from file %s "
459 "in %fs (%0.3f kb/s)", written
, CMD_ARGV
[0],
460 duration_elapsed(&bench
), duration_kbps(&bench
, written
));
468 COMMAND_HANDLER(handle_flash_fill_command
)
475 uint32_t cur_size
= 0;
476 uint32_t chunk_count
;
477 struct target
*target
= get_current_target(CMD_CTX
);
480 int retval
= ERROR_OK
;
482 static size_t const chunksize
= 1024;
483 uint8_t *chunk
= malloc(chunksize
);
487 uint8_t *readback
= malloc(chunksize
);
488 if (readback
== NULL
)
497 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
502 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
503 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], pattern
);
504 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], count
);
521 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
525 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
529 for (i
= 0; i
< chunk_count
; i
++)
531 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
535 for (i
= 0; i
< chunk_count
; i
++)
537 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
541 memset(chunk
, pattern
, chunk_count
);
544 LOG_ERROR("BUG: can't happen");
548 struct duration bench
;
549 duration_start(&bench
);
551 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
)
553 struct flash_bank
*bank
;
555 bank
= get_flash_bank_by_addr(target
, address
);
562 cur_size
= MIN((count
* wordsize
- wrote
), chunksize
);
563 err
= flash_driver_write(bank
, chunk
, address
- bank
->base
+ wrote
, cur_size
);
570 err
= target_read_buffer(target
, address
+ wrote
, cur_size
, readback
);
578 for (i
= 0; i
< cur_size
; i
++)
580 if (readback
[i
]!=chunk
[i
])
582 LOG_ERROR("Verfication error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
583 address
+ wrote
+ i
, readback
[i
], chunk
[i
]);
590 if (duration_measure(&bench
) == ERROR_OK
)
592 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes to 0x%8.8" PRIx32
593 " in %fs (%0.3f kb/s)", wrote
, address
,
594 duration_elapsed(&bench
), duration_kbps(&bench
, wrote
));
604 COMMAND_HANDLER(handle_flash_write_bank_command
)
608 struct fileio fileio
;
611 return ERROR_COMMAND_SYNTAX_ERROR
;
613 struct duration bench
;
614 duration_start(&bench
);
616 struct flash_bank
*p
;
617 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
618 if (ERROR_OK
!= retval
)
621 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
623 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
628 buffer
= malloc(fileio
.size
);
630 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
633 fileio_close(&fileio
);
637 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
642 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
644 command_print(CMD_CTX
, "wrote %ld bytes from file %s to flash bank %u"
645 " at offset 0x%8.8" PRIx32
" in %fs (%0.3f kb/s)",
646 (long)fileio
.size
, CMD_ARGV
[1], p
->bank_number
, offset
,
647 duration_elapsed(&bench
), duration_kbps(&bench
, fileio
.size
));
650 fileio_close(&fileio
);
655 void flash_set_dirty(void)
657 struct flash_bank
*c
;
660 /* set all flash to require erasing */
661 for (c
= flash_bank_list(); c
; c
= c
->next
)
663 for (i
= 0; i
< c
->num_sectors
; i
++)
665 c
->sectors
[i
].is_erased
= 0;
670 static const struct command_registration flash_exec_command_handlers
[] = {
673 .handler
= handle_flash_probe_command
,
674 .mode
= COMMAND_EXEC
,
676 .help
= "Identify a flash bank.",
680 .handler
= handle_flash_info_command
,
681 .mode
= COMMAND_EXEC
,
683 .help
= "Print information about a flash bank.",
686 .name
= "erase_check",
687 .handler
= handle_flash_erase_check_command
,
688 .mode
= COMMAND_EXEC
,
690 .help
= "Check erase state of all blocks in a "
694 .name
= "protect_check",
695 .handler
= handle_flash_protect_check_command
,
696 .mode
= COMMAND_EXEC
,
698 .help
= "Check protection state of all blocks in a "
702 .name
= "erase_sector",
703 .handler
= handle_flash_erase_command
,
704 .mode
= COMMAND_EXEC
,
705 .usage
= "bank_id first_sector_num last_sector_num",
706 .help
= "Erase a range of sectors in a flash bank.",
709 .name
= "erase_address",
710 .handler
= handle_flash_erase_address_command
,
711 .mode
= COMMAND_EXEC
,
712 .usage
= "['pad'] address length",
713 .help
= "Erase flash sectors starting at address and "
714 "continuing for length bytes. If 'pad' is specified, "
715 "data outside that range may also be erased: the start "
716 "address may be decreased, and length increased, so "
717 "that all of the first and last sectors are erased.",
721 .handler
= handle_flash_fill_command
,
722 .mode
= COMMAND_EXEC
,
723 .usage
= "address value n",
724 .help
= "Fill n words with 32-bit value, starting at "
725 "word address. (No autoerase.)",
729 .handler
= handle_flash_fill_command
,
730 .mode
= COMMAND_EXEC
,
731 .usage
= "address value n",
732 .help
= "Fill n halfwords with 16-bit value, starting at "
733 "word address. (No autoerase.)",
737 .handler
= handle_flash_fill_command
,
738 .mode
= COMMAND_EXEC
,
739 .usage
= "address value n",
740 .help
= "Fill n bytes with 8-bit value, starting at "
741 "word address. (No autoerase.)",
744 .name
= "write_bank",
745 .handler
= handle_flash_write_bank_command
,
746 .mode
= COMMAND_EXEC
,
747 .usage
= "bank_id filename offset",
748 .help
= "Write binary data from file to flash bank, "
749 "starting at specified byte offset from the "
750 "beginning of the bank.",
753 .name
= "write_image",
754 .handler
= handle_flash_write_image_command
,
755 .mode
= COMMAND_EXEC
,
756 .usage
= "[erase] [unlock] filename [offset [file_type]]",
757 .help
= "Write an image to flash. Optionally first unprotect "
758 "and/or erase the region to be used. Allow optional "
759 "offset from beginning of bank (defaults to zero)",
763 .handler
= handle_flash_protect_command
,
764 .mode
= COMMAND_EXEC
,
765 .usage
= "bank_id first_sector [last_sector|'last'] "
767 .help
= "Turn protection on or off for a range of sectors "
768 "in a given flash bank.",
770 COMMAND_REGISTRATION_DONE
773 static int flash_init_drivers(struct command_context
*cmd_ctx
)
775 if (!flash_bank_list())
778 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
779 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
783 COMMAND_HANDLER(handle_flash_bank_command
)
787 LOG_ERROR("usage: flash bank <name> <driver> "
788 "<base> <size> <chip_width> <bus_width> <target>");
789 return ERROR_COMMAND_SYNTAX_ERROR
;
791 // save bank name and advance arguments for compatibility
792 const char *bank_name
= *CMD_ARGV
++;
795 struct target
*target
;
796 if ((target
= get_target(CMD_ARGV
[5])) == NULL
)
798 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
802 const char *driver_name
= CMD_ARGV
[0];
803 struct flash_driver
*driver
= flash_driver_find_by_name(driver_name
);
806 /* no matching flash driver found */
807 LOG_ERROR("flash driver '%s' not found", driver_name
);
811 /* register flash specific commands */
812 if (NULL
!= driver
->commands
)
814 int retval
= register_commands(CMD_CTX
, NULL
,
816 if (ERROR_OK
!= retval
)
818 LOG_ERROR("couldn't register '%s' commands",
824 struct flash_bank
*c
= malloc(sizeof(*c
));
825 c
->name
= strdup(bank_name
);
828 c
->driver_priv
= NULL
;
829 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], c
->base
);
830 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], c
->size
);
831 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], c
->chip_width
);
832 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[4], c
->bus_width
);
838 retval
= CALL_COMMAND_HANDLER(driver
->flash_bank_command
, c
);
839 if (ERROR_OK
!= retval
)
841 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32
,
842 driver_name
, c
->base
);
852 COMMAND_HANDLER(handle_flash_banks_command
)
855 return ERROR_INVALID_ARGUMENTS
;
858 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++)
860 LOG_USER("#%u: %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", "
861 "buswidth %u, chipwidth %u", n
,
862 p
->driver
->name
, p
->base
, p
->size
,
863 p
->bus_width
, p
->chip_width
);
868 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
872 Jim_WrongNumArgs(interp
, 1, argv
,
873 "no arguments to 'flash list' command");
877 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
879 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
)
881 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
883 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "name", -1));
884 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, p
->driver
->name
, -1));
885 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "base", -1));
886 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->base
));
887 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "size", -1));
888 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->size
));
889 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "bus_width", -1));
890 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->bus_width
));
891 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "chip_width", -1));
892 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->chip_width
));
894 Jim_ListAppendElement(interp
, list
, elem
);
897 Jim_SetResult(interp
, list
);
903 COMMAND_HANDLER(handle_flash_init_command
)
906 return ERROR_COMMAND_SYNTAX_ERROR
;
908 static bool flash_initialized
= false;
909 if (flash_initialized
)
911 LOG_INFO("'flash init' has already been called");
914 flash_initialized
= true;
916 LOG_DEBUG("Initializing flash devices...");
917 return flash_init_drivers(CMD_CTX
);
920 static const struct command_registration flash_config_command_handlers
[] = {
923 .handler
= handle_flash_bank_command
,
924 .mode
= COMMAND_CONFIG
,
925 .usage
= "bank_id driver_name base_address size_bytes "
926 "chip_width_bytes bus_width_bytes target "
927 "[driver_options ...]",
928 .help
= "Define a new bank with the given name, "
929 "using the specified NOR flash driver.",
933 .mode
= COMMAND_CONFIG
,
934 .handler
= handle_flash_init_command
,
935 .help
= "Initialize flash devices.",
940 .handler
= handle_flash_banks_command
,
941 .help
= "Display table with information about flash banks.",
946 .jim_handler
= jim_flash_list
,
947 .help
= "Returns a list of details about the flash banks.",
949 COMMAND_REGISTRATION_DONE
951 static const struct command_registration flash_command_handlers
[] = {
955 .help
= "NOR flash command group",
956 .chain
= flash_config_command_handlers
,
958 COMMAND_REGISTRATION_DONE
961 int flash_register_commands(struct command_context
*cmd_ctx
)
963 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)