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 "#%d : %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.8" PRIx32
" (length %" PRIi32
")"
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 %d "
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 %d",
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
);
352 /* flash auto-erase is disabled by default*/
354 bool auto_unlock
= false;
357 if (strcmp(CMD_ARGV
[0], "erase") == 0) {
361 command_print(CMD_CTX
, "auto erase enabled");
362 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0) {
366 command_print(CMD_CTX
, "auto unlock enabled");
372 return ERROR_COMMAND_SYNTAX_ERROR
;
375 LOG_ERROR("no target selected");
379 struct duration bench
;
380 duration_start(&bench
);
383 image
.base_address_set
= 1;
384 COMMAND_PARSE_NUMBER(llong
, CMD_ARGV
[1], image
.base_address
);
386 image
.base_address_set
= 0;
387 image
.base_address
= 0x0;
390 image
.start_address_set
= 0;
392 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
393 if (retval
!= ERROR_OK
)
396 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
397 if (retval
!= ERROR_OK
) {
402 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
)) {
403 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes from file %s "
404 "in %fs (%0.3f KiB/s)", written
, CMD_ARGV
[0],
405 duration_elapsed(&bench
), duration_kbps(&bench
, written
));
413 COMMAND_HANDLER(handle_flash_fill_command
)
420 uint32_t cur_size
= 0;
421 uint32_t chunk_count
;
422 struct target
*target
= get_current_target(CMD_CTX
);
425 int retval
= ERROR_OK
;
427 static size_t const chunksize
= 1024;
428 uint8_t *chunk
= NULL
, *readback
= NULL
;
431 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
435 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
436 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], pattern
);
437 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], count
);
439 chunk
= malloc(chunksize
);
443 readback
= malloc(chunksize
);
444 if (readback
== NULL
) {
452 switch (CMD_NAME
[4]) {
463 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
467 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
470 for (i
= 0; i
< chunk_count
; i
++)
471 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
474 for (i
= 0; i
< chunk_count
; i
++)
475 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
478 memset(chunk
, pattern
, chunk_count
);
481 LOG_ERROR("BUG: can't happen");
485 struct duration bench
;
486 duration_start(&bench
);
488 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
) {
489 struct flash_bank
*bank
;
491 retval
= get_flash_bank_by_addr(target
, address
, true, &bank
);
492 if (retval
!= ERROR_OK
)
495 cur_size
= MIN((count
* wordsize
- wrote
), chunksize
);
496 err
= flash_driver_write(bank
, chunk
, address
- bank
->base
+ wrote
, cur_size
);
497 if (err
!= ERROR_OK
) {
502 err
= flash_driver_read(bank
, readback
, address
- bank
->base
+ wrote
, cur_size
);
503 if (err
!= ERROR_OK
) {
508 for (i
= 0; i
< cur_size
; i
++) {
509 if (readback
[i
] != chunk
[i
]) {
511 "Verification error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
521 if ((retval
== ERROR_OK
) && (duration_measure(&bench
) == ERROR_OK
)) {
522 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes to 0x%8.8" PRIx32
523 " in %fs (%0.3f KiB/s)", wrote
, address
,
524 duration_elapsed(&bench
), duration_kbps(&bench
, wrote
));
534 COMMAND_HANDLER(handle_flash_write_bank_command
)
538 struct fileio fileio
;
541 return ERROR_COMMAND_SYNTAX_ERROR
;
543 struct duration bench
;
544 duration_start(&bench
);
546 struct flash_bank
*p
;
547 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
548 if (ERROR_OK
!= retval
)
551 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
553 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
557 retval
= fileio_size(&fileio
, &filesize
);
558 if (retval
!= ERROR_OK
) {
559 fileio_close(&fileio
);
563 buffer
= malloc(filesize
);
564 if (buffer
== NULL
) {
565 fileio_close(&fileio
);
566 LOG_ERROR("Out of memory");
570 if (fileio_read(&fileio
, filesize
, buffer
, &buf_cnt
) != ERROR_OK
) {
572 fileio_close(&fileio
);
576 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
581 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
)) {
582 command_print(CMD_CTX
, "wrote %ld bytes from file %s to flash bank %u"
583 " at offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
584 (long)filesize
, CMD_ARGV
[1], p
->bank_number
, offset
,
585 duration_elapsed(&bench
), duration_kbps(&bench
, filesize
));
588 fileio_close(&fileio
);
593 void flash_set_dirty(void)
595 struct flash_bank
*c
;
598 /* set all flash to require erasing */
599 for (c
= flash_bank_list(); c
; c
= c
->next
) {
600 for (i
= 0; i
< c
->num_sectors
; i
++)
601 c
->sectors
[i
].is_erased
= 0;
605 COMMAND_HANDLER(handle_flash_padded_value_command
)
608 return ERROR_COMMAND_SYNTAX_ERROR
;
610 struct flash_bank
*p
;
611 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
612 if (ERROR_OK
!= retval
)
615 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[1], p
->default_padded_value
);
617 command_print(CMD_CTX
, "Default padded value set to 0x%" PRIx8
" for flash bank %u", \
618 p
->default_padded_value
, p
->bank_number
);
623 static const struct command_registration flash_exec_command_handlers
[] = {
626 .handler
= handle_flash_probe_command
,
627 .mode
= COMMAND_EXEC
,
629 .help
= "Identify a flash bank.",
633 .handler
= handle_flash_info_command
,
634 .mode
= COMMAND_EXEC
,
636 .help
= "Print information about a flash bank.",
639 .name
= "erase_check",
640 .handler
= handle_flash_erase_check_command
,
641 .mode
= COMMAND_EXEC
,
643 .help
= "Check erase state of all blocks in a "
647 .name
= "erase_sector",
648 .handler
= handle_flash_erase_command
,
649 .mode
= COMMAND_EXEC
,
650 .usage
= "bank_id first_sector_num last_sector_num",
651 .help
= "Erase a range of sectors in a flash bank.",
654 .name
= "erase_address",
655 .handler
= handle_flash_erase_address_command
,
656 .mode
= COMMAND_EXEC
,
657 .usage
= "['pad'] ['unlock'] address length",
658 .help
= "Erase flash sectors starting at address and "
659 "continuing for length bytes. If 'pad' is specified, "
660 "data outside that range may also be erased: the start "
661 "address may be decreased, and length increased, so "
662 "that all of the first and last sectors are erased. "
663 "If 'unlock' is specified, then the flash is unprotected "
669 .handler
= handle_flash_fill_command
,
670 .mode
= COMMAND_EXEC
,
671 .usage
= "address value n",
672 .help
= "Fill n words with 32-bit value, starting at "
673 "word address. (No autoerase.)",
677 .handler
= handle_flash_fill_command
,
678 .mode
= COMMAND_EXEC
,
679 .usage
= "address value n",
680 .help
= "Fill n halfwords with 16-bit value, starting at "
681 "word address. (No autoerase.)",
685 .handler
= handle_flash_fill_command
,
686 .mode
= COMMAND_EXEC
,
687 .usage
= "address value n",
688 .help
= "Fill n bytes with 8-bit value, starting at "
689 "word address. (No autoerase.)",
692 .name
= "write_bank",
693 .handler
= handle_flash_write_bank_command
,
694 .mode
= COMMAND_EXEC
,
695 .usage
= "bank_id filename offset",
696 .help
= "Write binary data from file to flash bank, "
697 "starting at specified byte offset from the "
698 "beginning of the bank.",
701 .name
= "write_image",
702 .handler
= handle_flash_write_image_command
,
703 .mode
= COMMAND_EXEC
,
704 .usage
= "[erase] [unlock] filename [offset [file_type]]",
705 .help
= "Write an image to flash. Optionally first unprotect "
706 "and/or erase the region to be used. Allow optional "
707 "offset from beginning of bank (defaults to zero)",
711 .handler
= handle_flash_protect_command
,
712 .mode
= COMMAND_EXEC
,
713 .usage
= "bank_id first_sector [last_sector|'last'] "
715 .help
= "Turn protection on or off for a range of sectors "
716 "in a given flash bank.",
719 .name
= "padded_value",
720 .handler
= handle_flash_padded_value_command
,
721 .mode
= COMMAND_EXEC
,
722 .usage
= "bank_id value",
723 .help
= "Set default flash padded value",
725 COMMAND_REGISTRATION_DONE
728 static int flash_init_drivers(struct command_context
*cmd_ctx
)
730 if (!flash_bank_list())
733 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
734 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
737 COMMAND_HANDLER(handle_flash_bank_command
)
740 LOG_ERROR("usage: flash bank <name> <driver> "
741 "<base> <size> <chip_width> <bus_width> <target>");
742 return ERROR_COMMAND_SYNTAX_ERROR
;
744 /* save bank name and advance arguments for compatibility */
745 const char *bank_name
= *CMD_ARGV
++;
748 struct target
*target
= get_target(CMD_ARGV
[5]);
749 if (target
== NULL
) {
750 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
754 const char *driver_name
= CMD_ARGV
[0];
755 struct flash_driver
*driver
= flash_driver_find_by_name(driver_name
);
756 if (NULL
== driver
) {
757 /* no matching flash driver found */
758 LOG_ERROR("flash driver '%s' not found", driver_name
);
762 /* check the flash bank name is unique */
763 if (get_flash_bank_by_name_noprobe(bank_name
) != NULL
) {
764 /* flash bank name already exists */
765 LOG_ERROR("flash bank name '%s' already exists", bank_name
);
769 /* register flash specific commands */
770 if (NULL
!= driver
->commands
) {
771 int retval
= register_commands(CMD_CTX
, NULL
,
773 if (ERROR_OK
!= retval
) {
774 LOG_ERROR("couldn't register '%s' commands",
780 struct flash_bank
*c
= malloc(sizeof(*c
));
781 c
->name
= strdup(bank_name
);
784 c
->driver_priv
= NULL
;
785 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], c
->base
);
786 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], c
->size
);
787 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], c
->chip_width
);
788 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[4], c
->bus_width
);
789 c
->default_padded_value
= 0xff;
795 retval
= CALL_COMMAND_HANDLER(driver
->flash_bank_command
, c
);
796 if (ERROR_OK
!= retval
) {
797 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32
"Usage %s",
798 driver_name
, c
->base
, driver
->usage
);
803 if (driver
->usage
== NULL
)
804 LOG_DEBUG("'%s' driver usage field missing", driver_name
);
811 COMMAND_HANDLER(handle_flash_banks_command
)
814 return ERROR_COMMAND_SYNTAX_ERROR
;
817 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++) {
818 LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", "
819 "buswidth %u, chipwidth %u", p
->bank_number
,
820 p
->name
, p
->driver
->name
, p
->base
, p
->size
,
821 p
->bus_width
, p
->chip_width
);
826 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
* const *argv
)
829 Jim_WrongNumArgs(interp
, 1, argv
,
830 "no arguments to 'flash list' command");
834 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
836 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
) {
837 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
839 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "name", -1));
840 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, p
->driver
->name
, -1));
841 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "base", -1));
842 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->base
));
843 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "size", -1));
844 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->size
));
845 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "bus_width", -1));
846 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->bus_width
));
847 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "chip_width", -1));
848 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->chip_width
));
850 Jim_ListAppendElement(interp
, list
, elem
);
853 Jim_SetResult(interp
, list
);
858 COMMAND_HANDLER(handle_flash_init_command
)
861 return ERROR_COMMAND_SYNTAX_ERROR
;
863 static bool flash_initialized
;
864 if (flash_initialized
) {
865 LOG_INFO("'flash init' has already been called");
868 flash_initialized
= true;
870 LOG_DEBUG("Initializing flash devices...");
871 return flash_init_drivers(CMD_CTX
);
874 static const struct command_registration flash_config_command_handlers
[] = {
877 .handler
= handle_flash_bank_command
,
878 .mode
= COMMAND_CONFIG
,
879 .usage
= "bank_id driver_name base_address size_bytes "
880 "chip_width_bytes bus_width_bytes target "
881 "[driver_options ...]",
882 .help
= "Define a new bank with the given name, "
883 "using the specified NOR flash driver.",
887 .mode
= COMMAND_CONFIG
,
888 .handler
= handle_flash_init_command
,
889 .help
= "Initialize flash devices.",
894 .handler
= handle_flash_banks_command
,
895 .help
= "Display table with information about flash banks.",
900 .jim_handler
= jim_flash_list
,
901 .help
= "Returns a list of details about the flash banks.",
903 COMMAND_REGISTRATION_DONE
905 static const struct command_registration flash_command_handlers
[] = {
909 .help
= "NOR flash command group",
910 .chain
= flash_config_command_handlers
,
912 COMMAND_REGISTRATION_DONE
915 int flash_register_commands(struct command_context
*cmd_ctx
)
917 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)