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 *bank
= get_flash_bank_by_num(bank_num
);
48 command_print(CMD_CTX
, "flash bank '%s' not found", name
);
49 return ERROR_INVALID_ARGUMENTS
;
55 COMMAND_HANDLER(handle_flash_info_command
)
63 return ERROR_COMMAND_SYNTAX_ERROR
;
66 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], bank_nr
);
68 for (p
= flash_bank_list(); p
; p
= p
->next
, i
++)
75 /* attempt auto probe */
76 if ((retval
= p
->driver
->auto_probe(p
)) != ERROR_OK
)
79 command_print(CMD_CTX
,
80 "#%" PRIi32
" : %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", buswidth %i, chipwidth %i",
87 for (j
= 0; j
< p
->num_sectors
; j
++)
91 if (p
->sectors
[j
].is_protected
== 0)
92 protect_state
= "not protected";
93 else if (p
->sectors
[j
].is_protected
== 1)
94 protect_state
= "protected";
96 protect_state
= "protection state unknown";
98 command_print(CMD_CTX
,
99 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
101 p
->sectors
[j
].offset
,
103 p
->sectors
[j
].size
>> 10,
107 *buf
= '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
108 retval
= p
->driver
->info(p
, buf
, sizeof(buf
));
109 command_print(CMD_CTX
, "%s", buf
);
110 if (retval
!= ERROR_OK
)
111 LOG_ERROR("error retrieving flash info (%d)", retval
);
117 COMMAND_HANDLER(handle_flash_probe_command
)
123 return ERROR_COMMAND_SYNTAX_ERROR
;
127 COMMAND_PARSE_NUMBER(uint
, CMD_ARGV
[0], bank_nr
);
128 struct flash_bank
*p
= get_flash_bank_by_num_noprobe(bank_nr
);
131 if ((retval
= p
->driver
->probe(p
)) == ERROR_OK
)
133 command_print(CMD_CTX
, "flash '%s' found at 0x%8.8" PRIx32
, p
->driver
->name
, p
->base
);
135 else if (retval
== ERROR_FLASH_BANK_INVALID
)
137 command_print(CMD_CTX
, "probing failed for flash bank '#%s' at 0x%8.8" PRIx32
,
138 CMD_ARGV
[0], p
->base
);
142 command_print(CMD_CTX
, "unknown error when probing flash bank '#%s' at 0x%8.8" PRIx32
,
143 CMD_ARGV
[0], p
->base
);
148 command_print(CMD_CTX
, "flash bank '#%s' is out of bounds", CMD_ARGV
[0]);
154 COMMAND_HANDLER(handle_flash_erase_check_command
)
158 return ERROR_COMMAND_SYNTAX_ERROR
;
161 struct flash_bank
*p
;
162 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
163 if (ERROR_OK
!= retval
)
167 if ((retval
= p
->driver
->erase_check(p
)) == ERROR_OK
)
169 command_print(CMD_CTX
, "successfully checked erase state");
173 command_print(CMD_CTX
, "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32
,
174 CMD_ARGV
[0], p
->base
);
177 for (j
= 0; j
< p
->num_sectors
; j
++)
181 if (p
->sectors
[j
].is_erased
== 0)
182 erase_state
= "not erased";
183 else if (p
->sectors
[j
].is_erased
== 1)
184 erase_state
= "erased";
186 erase_state
= "erase state unknown";
188 command_print(CMD_CTX
,
189 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
191 p
->sectors
[j
].offset
,
193 p
->sectors
[j
].size
>> 10,
200 COMMAND_HANDLER(handle_flash_erase_address_command
)
202 struct flash_bank
*p
;
207 struct target
*target
= get_current_target(CMD_CTX
);
211 /* Optionally pad out the address range to block/sector
212 * boundaries. We can't know if there's data in that part
213 * of the flash; only do padding if we're told to.
215 if (strcmp("pad", CMD_ARGV
[0]) != 0)
216 return ERROR_COMMAND_SYNTAX_ERROR
;
222 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], address
);
223 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], length
);
226 return ERROR_COMMAND_SYNTAX_ERROR
;
231 command_print(CMD_CTX
, "Length must be >0");
232 return ERROR_COMMAND_SYNTAX_ERROR
;
235 p
= get_flash_bank_by_addr(target
, address
);
241 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
244 struct duration bench
;
245 duration_start(&bench
);
247 retval
= flash_erase_address_range(target
, do_pad
, address
, length
);
249 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
251 command_print(CMD_CTX
, "erased address 0x%8.8x (length %i)"
252 " in %fs (%0.3f kb/s)", address
, length
,
253 duration_elapsed(&bench
), duration_kbps(&bench
, length
));
259 COMMAND_HANDLER(handle_flash_protect_check_command
)
262 return ERROR_COMMAND_SYNTAX_ERROR
;
264 struct flash_bank
*p
;
265 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
266 if (ERROR_OK
!= retval
)
269 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
271 command_print(CMD_CTX
, "successfully checked protect state");
273 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
275 command_print(CMD_CTX
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
279 command_print(CMD_CTX
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
285 static int flash_check_sector_parameters(struct command_context
*cmd_ctx
,
286 uint32_t first
, uint32_t last
, uint32_t num_sectors
)
288 if (!(first
<= last
)) {
289 command_print(cmd_ctx
, "ERROR: "
290 "first sector must be <= last sector");
294 if (!(last
<= (num_sectors
- 1))) {
295 command_print(cmd_ctx
, "ERROR: last sector must be <= %d",
296 (int) num_sectors
- 1);
303 COMMAND_HANDLER(handle_flash_erase_command
)
306 return ERROR_COMMAND_SYNTAX_ERROR
;
312 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
313 struct flash_bank
*p
= get_flash_bank_by_num(bank_nr
);
317 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
318 if (strcmp(CMD_ARGV
[2], "last") == 0)
319 last
= p
->num_sectors
- 1;
321 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
324 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
325 first
, last
, p
->num_sectors
)) != ERROR_OK
)
328 struct duration bench
;
329 duration_start(&bench
);
331 retval
= flash_driver_erase(p
, first
, last
);
333 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
335 command_print(CMD_CTX
, "erased sectors %" PRIu32
" "
336 "through %" PRIu32
" on flash bank %" PRIu32
" "
337 "in %fs", first
, last
, bank_nr
, duration_elapsed(&bench
));
343 COMMAND_HANDLER(handle_flash_protect_command
)
346 return ERROR_COMMAND_SYNTAX_ERROR
;
352 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
353 struct flash_bank
*p
= get_flash_bank_by_num(bank_nr
);
357 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
358 if (strcmp(CMD_ARGV
[2], "last") == 0)
359 last
= p
->num_sectors
- 1;
361 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
364 COMMAND_PARSE_ON_OFF(CMD_ARGV
[3], set
);
367 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
368 first
, last
, p
->num_sectors
)) != ERROR_OK
)
371 retval
= flash_driver_protect(p
, set
, first
, last
);
372 if (retval
== ERROR_OK
) {
373 command_print(CMD_CTX
, "%s protection for sectors %i "
374 "through %i on flash bank %i",
375 (set
) ? "set" : "cleared", (int) first
,
376 (int) last
, (int) bank_nr
);
382 COMMAND_HANDLER(handle_flash_write_image_command
)
384 struct target
*target
= get_current_target(CMD_CTX
);
393 return ERROR_COMMAND_SYNTAX_ERROR
;
396 /* flash auto-erase is disabled by default*/
398 bool auto_unlock
= false;
402 if (strcmp(CMD_ARGV
[0], "erase") == 0)
407 command_print(CMD_CTX
, "auto erase enabled");
408 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0)
413 command_print(CMD_CTX
, "auto unlock enabled");
422 return ERROR_COMMAND_SYNTAX_ERROR
;
427 LOG_ERROR("no target selected");
431 struct duration bench
;
432 duration_start(&bench
);
436 image
.base_address_set
= 1;
437 COMMAND_PARSE_NUMBER(llong
, CMD_ARGV
[1], image
.base_address
);
441 image
.base_address_set
= 0;
442 image
.base_address
= 0x0;
445 image
.start_address_set
= 0;
447 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
448 if (retval
!= ERROR_OK
)
453 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
454 if (retval
!= ERROR_OK
)
460 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
462 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes from file %s "
463 "in %fs (%0.3f kb/s)", written
, CMD_ARGV
[0],
464 duration_elapsed(&bench
), duration_kbps(&bench
, written
));
472 COMMAND_HANDLER(handle_flash_fill_command
)
479 uint32_t cur_size
= 0;
480 uint32_t chunk_count
;
481 struct target
*target
= get_current_target(CMD_CTX
);
484 int retval
= ERROR_OK
;
486 static size_t const chunksize
= 1024;
487 uint8_t *chunk
= malloc(chunksize
);
491 uint8_t *readback
= malloc(chunksize
);
492 if (readback
== NULL
)
501 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
506 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
507 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], pattern
);
508 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], count
);
525 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
529 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
533 for (i
= 0; i
< chunk_count
; i
++)
535 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
539 for (i
= 0; i
< chunk_count
; i
++)
541 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
545 memset(chunk
, pattern
, chunk_count
);
548 LOG_ERROR("BUG: can't happen");
552 struct duration bench
;
553 duration_start(&bench
);
555 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
)
557 struct flash_bank
*bank
;
559 bank
= get_flash_bank_by_addr(target
, address
);
566 cur_size
= MIN((count
* wordsize
- wrote
), chunksize
);
567 err
= flash_driver_write(bank
, chunk
, address
- bank
->base
+ wrote
, cur_size
);
574 err
= target_read_buffer(target
, address
+ wrote
, cur_size
, readback
);
582 for (i
= 0; i
< cur_size
; i
++)
584 if (readback
[i
]!=chunk
[i
])
586 LOG_ERROR("Verfication error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
587 address
+ wrote
+ i
, readback
[i
], chunk
[i
]);
594 if (duration_measure(&bench
) == ERROR_OK
)
596 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes to 0x%8.8" PRIx32
597 " in %fs (%0.3f kb/s)", wrote
, address
,
598 duration_elapsed(&bench
), duration_kbps(&bench
, wrote
));
608 COMMAND_HANDLER(handle_flash_write_bank_command
)
612 struct fileio fileio
;
615 return ERROR_COMMAND_SYNTAX_ERROR
;
617 struct duration bench
;
618 duration_start(&bench
);
620 struct flash_bank
*p
;
621 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
622 if (ERROR_OK
!= retval
)
625 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
627 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
632 buffer
= malloc(fileio
.size
);
634 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
637 fileio_close(&fileio
);
641 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
646 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
648 command_print(CMD_CTX
, "wrote %ld bytes from file %s to flash bank %u"
649 " at offset 0x%8.8" PRIx32
" in %fs (%0.3f kb/s)",
650 (long)fileio
.size
, CMD_ARGV
[1], p
->bank_number
, offset
,
651 duration_elapsed(&bench
), duration_kbps(&bench
, fileio
.size
));
654 fileio_close(&fileio
);
659 void flash_set_dirty(void)
661 struct flash_bank
*c
;
664 /* set all flash to require erasing */
665 for (c
= flash_bank_list(); c
; c
= c
->next
)
667 for (i
= 0; i
< c
->num_sectors
; i
++)
669 c
->sectors
[i
].is_erased
= 0;
674 static const struct command_registration flash_exec_command_handlers
[] = {
677 .handler
= handle_flash_probe_command
,
678 .mode
= COMMAND_EXEC
,
680 .help
= "Identify a flash bank.",
684 .handler
= handle_flash_info_command
,
685 .mode
= COMMAND_EXEC
,
687 .help
= "Print information about a flash bank.",
690 .name
= "erase_check",
691 .handler
= handle_flash_erase_check_command
,
692 .mode
= COMMAND_EXEC
,
694 .help
= "Check erase state of all blocks in a "
698 .name
= "protect_check",
699 .handler
= handle_flash_protect_check_command
,
700 .mode
= COMMAND_EXEC
,
702 .help
= "Check protection state of all blocks in a "
706 .name
= "erase_sector",
707 .handler
= handle_flash_erase_command
,
708 .mode
= COMMAND_EXEC
,
709 .usage
= "bank_id first_sector_num last_sector_num",
710 .help
= "Erase a range of sectors in a flash bank.",
713 .name
= "erase_address",
714 .handler
= handle_flash_erase_address_command
,
715 .mode
= COMMAND_EXEC
,
716 .usage
= "['pad'] address length",
717 .help
= "Erase flash sectors starting at address and "
718 "continuing for length bytes. If 'pad' is specified, "
719 "data outside that range may also be erased: the start "
720 "address may be decreased, and length increased, so "
721 "that all of the first and last sectors are erased.",
725 .handler
= handle_flash_fill_command
,
726 .mode
= COMMAND_EXEC
,
727 .usage
= "address value n",
728 .help
= "Fill n words with 32-bit value, starting at "
729 "word address. (No autoerase.)",
733 .handler
= handle_flash_fill_command
,
734 .mode
= COMMAND_EXEC
,
735 .usage
= "address value n",
736 .help
= "Fill n halfwords with 16-bit value, starting at "
737 "word address. (No autoerase.)",
741 .handler
= handle_flash_fill_command
,
742 .mode
= COMMAND_EXEC
,
743 .usage
= "address value n",
744 .help
= "Fill n bytes with 8-bit value, starting at "
745 "word address. (No autoerase.)",
748 .name
= "write_bank",
749 .handler
= handle_flash_write_bank_command
,
750 .mode
= COMMAND_EXEC
,
751 .usage
= "bank_id filename offset",
752 .help
= "Write binary data from file to flash bank, "
753 "starting at specified byte offset from the "
754 "beginning of the bank.",
757 .name
= "write_image",
758 .handler
= handle_flash_write_image_command
,
759 .mode
= COMMAND_EXEC
,
760 .usage
= "[erase] [unlock] filename [offset [file_type]]",
761 .help
= "Write an image to flash. Optionally first unprotect "
762 "and/or erase the region to be used. Allow optional "
763 "offset from beginning of bank (defaults to zero)",
767 .handler
= handle_flash_protect_command
,
768 .mode
= COMMAND_EXEC
,
769 .usage
= "bank_id first_sector [last_sector|'last'] "
771 .help
= "Turn protection on or off for a range of sectors "
772 "in a given flash bank.",
774 COMMAND_REGISTRATION_DONE
777 static int flash_init_drivers(struct command_context
*cmd_ctx
)
779 if (!flash_bank_list())
782 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
783 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
787 COMMAND_HANDLER(handle_flash_bank_command
)
791 LOG_ERROR("usage: flash bank <name> <driver> "
792 "<base> <size> <chip_width> <bus_width> <target>");
793 return ERROR_COMMAND_SYNTAX_ERROR
;
795 // save bank name and advance arguments for compatibility
796 const char *bank_name
= *CMD_ARGV
++;
799 struct target
*target
;
800 if ((target
= get_target(CMD_ARGV
[5])) == NULL
)
802 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
806 const char *driver_name
= CMD_ARGV
[0];
807 struct flash_driver
*driver
= flash_driver_find_by_name(driver_name
);
810 /* no matching flash driver found */
811 LOG_ERROR("flash driver '%s' not found", driver_name
);
815 /* register flash specific commands */
816 if (NULL
!= driver
->commands
)
818 int retval
= register_commands(CMD_CTX
, NULL
,
820 if (ERROR_OK
!= retval
)
822 LOG_ERROR("couldn't register '%s' commands",
828 struct flash_bank
*c
= malloc(sizeof(*c
));
829 c
->name
= strdup(bank_name
);
832 c
->driver_priv
= NULL
;
833 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], c
->base
);
834 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], c
->size
);
835 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], c
->chip_width
);
836 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[4], c
->bus_width
);
842 retval
= CALL_COMMAND_HANDLER(driver
->flash_bank_command
, c
);
843 if (ERROR_OK
!= retval
)
845 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32
,
846 driver_name
, c
->base
);
856 COMMAND_HANDLER(handle_flash_banks_command
)
859 return ERROR_INVALID_ARGUMENTS
;
862 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++)
864 LOG_USER("#%u: %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", "
865 "buswidth %u, chipwidth %u", n
,
866 p
->driver
->name
, p
->base
, p
->size
,
867 p
->bus_width
, p
->chip_width
);
872 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
876 Jim_WrongNumArgs(interp
, 1, argv
,
877 "no arguments to 'flash list' command");
881 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
883 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
)
885 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
887 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "name", -1));
888 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, p
->driver
->name
, -1));
889 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "base", -1));
890 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->base
));
891 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "size", -1));
892 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->size
));
893 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "bus_width", -1));
894 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->bus_width
));
895 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "chip_width", -1));
896 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->chip_width
));
898 Jim_ListAppendElement(interp
, list
, elem
);
901 Jim_SetResult(interp
, list
);
907 COMMAND_HANDLER(handle_flash_init_command
)
910 return ERROR_COMMAND_SYNTAX_ERROR
;
912 static bool flash_initialized
= false;
913 if (flash_initialized
)
915 LOG_INFO("'flash init' has already been called");
918 flash_initialized
= true;
920 LOG_DEBUG("Initializing flash devices...");
921 return flash_init_drivers(CMD_CTX
);
924 static const struct command_registration flash_config_command_handlers
[] = {
927 .handler
= handle_flash_bank_command
,
928 .mode
= COMMAND_CONFIG
,
929 .usage
= "bank_id driver_name base_address size_bytes "
930 "chip_width_bytes bus_width_bytes target "
931 "[driver_options ...]",
932 .help
= "Define a new bank with the given name, "
933 "using the specified NOR flash driver.",
937 .mode
= COMMAND_CONFIG
,
938 .handler
= handle_flash_init_command
,
939 .help
= "Initialize flash devices.",
944 .handler
= handle_flash_banks_command
,
945 .help
= "Display table with information about flash banks.",
950 .jim_handler
= jim_flash_list
,
951 .help
= "Returns a list of details about the flash banks.",
953 COMMAND_REGISTRATION_DONE
955 static const struct command_registration flash_command_handlers
[] = {
959 .help
= "NOR flash command group",
960 .chain
= flash_config_command_handlers
,
962 COMMAND_REGISTRATION_DONE
965 int flash_register_commands(struct command_context
*cmd_ctx
)
967 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)