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
;
197 int retval
= ERROR_OK
;
201 bool do_unlock
= false;
202 struct target
*target
= get_current_target(CMD_CTX
);
204 while (CMD_ARGC
>= 3)
206 /* Optionally pad out the address range to block/sector
207 * boundaries. We can't know if there's data in that part
208 * of the flash; only do padding if we're told to.
210 if (strcmp("pad", CMD_ARGV
[0]) == 0)
213 } else if (strcmp("unlock", CMD_ARGV
[0]) == 0)
218 return ERROR_COMMAND_SYNTAX_ERROR
;
225 return ERROR_COMMAND_SYNTAX_ERROR
;
228 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[0], address
);
229 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], length
);
233 command_print(CMD_CTX
, "Length must be >0");
234 return ERROR_COMMAND_SYNTAX_ERROR
;
237 p
= get_flash_bank_by_addr(target
, address
);
243 /* We can't know if we did a resume + halt, in which case we no longer know the erased state */
246 struct duration bench
;
247 duration_start(&bench
);
251 retval
= flash_unlock_address_range(target
, address
, length
);
254 if (retval
== ERROR_OK
)
256 retval
= flash_erase_address_range(target
, do_pad
, address
, length
);
259 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
261 command_print(CMD_CTX
, "erased address 0x%8.8x (length %i)"
262 " in %fs (%0.3f kb/s)", address
, length
,
263 duration_elapsed(&bench
), duration_kbps(&bench
, length
));
269 COMMAND_HANDLER(handle_flash_protect_check_command
)
272 return ERROR_COMMAND_SYNTAX_ERROR
;
274 struct flash_bank
*p
;
275 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
276 if (ERROR_OK
!= retval
)
279 if ((retval
= p
->driver
->protect_check(p
)) == ERROR_OK
)
281 command_print(CMD_CTX
, "successfully checked protect state");
283 else if (retval
== ERROR_FLASH_OPERATION_FAILED
)
285 command_print(CMD_CTX
, "checking protection state failed (possibly unsupported) by flash #%s at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
289 command_print(CMD_CTX
, "unknown error when checking protection state of flash bank '#%s' at 0x%8.8" PRIx32
, CMD_ARGV
[0], p
->base
);
295 static int flash_check_sector_parameters(struct command_context
*cmd_ctx
,
296 uint32_t first
, uint32_t last
, uint32_t num_sectors
)
298 if (!(first
<= last
)) {
299 command_print(cmd_ctx
, "ERROR: "
300 "first sector must be <= last sector");
304 if (!(last
<= (num_sectors
- 1))) {
305 command_print(cmd_ctx
, "ERROR: last sector must be <= %d",
306 (int) num_sectors
- 1);
313 COMMAND_HANDLER(handle_flash_erase_command
)
316 return ERROR_COMMAND_SYNTAX_ERROR
;
322 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
324 struct flash_bank
*p
;
326 retval
= get_flash_bank_by_num(bank_nr
, &p
);
327 if (retval
!= ERROR_OK
)
330 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
331 if (strcmp(CMD_ARGV
[2], "last") == 0)
332 last
= p
->num_sectors
- 1;
334 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
336 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
337 first
, last
, p
->num_sectors
)) != ERROR_OK
)
340 struct duration bench
;
341 duration_start(&bench
);
343 retval
= flash_driver_erase(p
, first
, last
);
345 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
347 command_print(CMD_CTX
, "erased sectors %" PRIu32
" "
348 "through %" PRIu32
" on flash bank %" PRIu32
" "
349 "in %fs", first
, last
, bank_nr
, duration_elapsed(&bench
));
355 COMMAND_HANDLER(handle_flash_protect_command
)
358 return ERROR_COMMAND_SYNTAX_ERROR
;
364 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], bank_nr
);
365 struct flash_bank
*p
;
366 int retval
= get_flash_bank_by_num(bank_nr
, &p
);
367 if (retval
!= ERROR_OK
)
370 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
371 if (strcmp(CMD_ARGV
[2], "last") == 0)
372 last
= p
->num_sectors
- 1;
374 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
377 COMMAND_PARSE_ON_OFF(CMD_ARGV
[3], set
);
379 if ((retval
= flash_check_sector_parameters(CMD_CTX
,
380 first
, last
, p
->num_sectors
)) != ERROR_OK
)
383 retval
= flash_driver_protect(p
, set
, first
, last
);
384 if (retval
== ERROR_OK
) {
385 command_print(CMD_CTX
, "%s protection for sectors %i "
386 "through %i on flash bank %i",
387 (set
) ? "set" : "cleared", (int) first
,
388 (int) last
, (int) bank_nr
);
394 COMMAND_HANDLER(handle_flash_write_image_command
)
396 struct target
*target
= get_current_target(CMD_CTX
);
405 return ERROR_COMMAND_SYNTAX_ERROR
;
408 /* flash auto-erase is disabled by default*/
410 bool auto_unlock
= false;
414 if (strcmp(CMD_ARGV
[0], "erase") == 0)
419 command_print(CMD_CTX
, "auto erase enabled");
420 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0)
425 command_print(CMD_CTX
, "auto unlock enabled");
434 return ERROR_COMMAND_SYNTAX_ERROR
;
439 LOG_ERROR("no target selected");
443 struct duration bench
;
444 duration_start(&bench
);
448 image
.base_address_set
= 1;
449 COMMAND_PARSE_NUMBER(llong
, CMD_ARGV
[1], image
.base_address
);
453 image
.base_address_set
= 0;
454 image
.base_address
= 0x0;
457 image
.start_address_set
= 0;
459 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
460 if (retval
!= ERROR_OK
)
465 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
466 if (retval
!= ERROR_OK
)
472 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
474 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes from file %s "
475 "in %fs (%0.3f kb/s)", written
, CMD_ARGV
[0],
476 duration_elapsed(&bench
), duration_kbps(&bench
, written
));
484 COMMAND_HANDLER(handle_flash_fill_command
)
491 uint32_t cur_size
= 0;
492 uint32_t chunk_count
;
493 struct target
*target
= get_current_target(CMD_CTX
);
496 int retval
= ERROR_OK
;
498 static size_t const chunksize
= 1024;
499 uint8_t *chunk
= malloc(chunksize
);
503 uint8_t *readback
= malloc(chunksize
);
504 if (readback
== NULL
)
513 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
518 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
519 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], pattern
);
520 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], count
);
537 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
541 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
545 for (i
= 0; i
< chunk_count
; i
++)
547 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
551 for (i
= 0; i
< chunk_count
; i
++)
553 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
557 memset(chunk
, pattern
, chunk_count
);
560 LOG_ERROR("BUG: can't happen");
564 struct duration bench
;
565 duration_start(&bench
);
567 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
)
569 struct flash_bank
*bank
;
571 bank
= get_flash_bank_by_addr(target
, address
);
578 cur_size
= MIN((count
* wordsize
- wrote
), chunksize
);
579 err
= flash_driver_write(bank
, chunk
, address
- bank
->base
+ wrote
, cur_size
);
586 err
= target_read_buffer(target
, address
+ wrote
, cur_size
, readback
);
594 for (i
= 0; i
< cur_size
; i
++)
596 if (readback
[i
]!=chunk
[i
])
598 LOG_ERROR("Verfication error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
599 address
+ wrote
+ i
, readback
[i
], chunk
[i
]);
606 if (duration_measure(&bench
) == ERROR_OK
)
608 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes to 0x%8.8" PRIx32
609 " in %fs (%0.3f kb/s)", wrote
, address
,
610 duration_elapsed(&bench
), duration_kbps(&bench
, wrote
));
620 COMMAND_HANDLER(handle_flash_write_bank_command
)
624 struct fileio fileio
;
627 return ERROR_COMMAND_SYNTAX_ERROR
;
629 struct duration bench
;
630 duration_start(&bench
);
632 struct flash_bank
*p
;
633 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
634 if (ERROR_OK
!= retval
)
637 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
639 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
644 buffer
= malloc(fileio
.size
);
646 if (fileio_read(&fileio
, fileio
.size
, buffer
, &buf_cnt
) != ERROR_OK
)
649 fileio_close(&fileio
);
653 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
658 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
))
660 command_print(CMD_CTX
, "wrote %ld bytes from file %s to flash bank %u"
661 " at offset 0x%8.8" PRIx32
" in %fs (%0.3f kb/s)",
662 (long)fileio
.size
, CMD_ARGV
[1], p
->bank_number
, offset
,
663 duration_elapsed(&bench
), duration_kbps(&bench
, fileio
.size
));
666 fileio_close(&fileio
);
671 void flash_set_dirty(void)
673 struct flash_bank
*c
;
676 /* set all flash to require erasing */
677 for (c
= flash_bank_list(); c
; c
= c
->next
)
679 for (i
= 0; i
< c
->num_sectors
; i
++)
681 c
->sectors
[i
].is_erased
= 0;
686 static const struct command_registration flash_exec_command_handlers
[] = {
689 .handler
= handle_flash_probe_command
,
690 .mode
= COMMAND_EXEC
,
692 .help
= "Identify a flash bank.",
696 .handler
= handle_flash_info_command
,
697 .mode
= COMMAND_EXEC
,
699 .help
= "Print information about a flash bank.",
702 .name
= "erase_check",
703 .handler
= handle_flash_erase_check_command
,
704 .mode
= COMMAND_EXEC
,
706 .help
= "Check erase state of all blocks in a "
710 .name
= "protect_check",
711 .handler
= handle_flash_protect_check_command
,
712 .mode
= COMMAND_EXEC
,
714 .help
= "Check protection state of all blocks in a "
718 .name
= "erase_sector",
719 .handler
= handle_flash_erase_command
,
720 .mode
= COMMAND_EXEC
,
721 .usage
= "bank_id first_sector_num last_sector_num",
722 .help
= "Erase a range of sectors in a flash bank.",
725 .name
= "erase_address",
726 .handler
= handle_flash_erase_address_command
,
727 .mode
= COMMAND_EXEC
,
728 .usage
= "['pad'] ['unlock'] address length",
729 .help
= "Erase flash sectors starting at address and "
730 "continuing for length bytes. If 'pad' is specified, "
731 "data outside that range may also be erased: the start "
732 "address may be decreased, and length increased, so "
733 "that all of the first and last sectors are erased. "
734 "If 'unlock' is specified, then the flash is unprotected "
740 .handler
= handle_flash_fill_command
,
741 .mode
= COMMAND_EXEC
,
742 .usage
= "address value n",
743 .help
= "Fill n words with 32-bit value, starting at "
744 "word address. (No autoerase.)",
748 .handler
= handle_flash_fill_command
,
749 .mode
= COMMAND_EXEC
,
750 .usage
= "address value n",
751 .help
= "Fill n halfwords with 16-bit value, starting at "
752 "word address. (No autoerase.)",
756 .handler
= handle_flash_fill_command
,
757 .mode
= COMMAND_EXEC
,
758 .usage
= "address value n",
759 .help
= "Fill n bytes with 8-bit value, starting at "
760 "word address. (No autoerase.)",
763 .name
= "write_bank",
764 .handler
= handle_flash_write_bank_command
,
765 .mode
= COMMAND_EXEC
,
766 .usage
= "bank_id filename offset",
767 .help
= "Write binary data from file to flash bank, "
768 "starting at specified byte offset from the "
769 "beginning of the bank.",
772 .name
= "write_image",
773 .handler
= handle_flash_write_image_command
,
774 .mode
= COMMAND_EXEC
,
775 .usage
= "[erase] [unlock] filename [offset [file_type]]",
776 .help
= "Write an image to flash. Optionally first unprotect "
777 "and/or erase the region to be used. Allow optional "
778 "offset from beginning of bank (defaults to zero)",
782 .handler
= handle_flash_protect_command
,
783 .mode
= COMMAND_EXEC
,
784 .usage
= "bank_id first_sector [last_sector|'last'] "
786 .help
= "Turn protection on or off for a range of sectors "
787 "in a given flash bank.",
789 COMMAND_REGISTRATION_DONE
792 static int flash_init_drivers(struct command_context
*cmd_ctx
)
794 if (!flash_bank_list())
797 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
798 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
802 COMMAND_HANDLER(handle_flash_bank_command
)
806 LOG_ERROR("usage: flash bank <name> <driver> "
807 "<base> <size> <chip_width> <bus_width> <target>");
808 return ERROR_COMMAND_SYNTAX_ERROR
;
810 // save bank name and advance arguments for compatibility
811 const char *bank_name
= *CMD_ARGV
++;
814 struct target
*target
;
815 if ((target
= get_target(CMD_ARGV
[5])) == NULL
)
817 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
821 const char *driver_name
= CMD_ARGV
[0];
822 struct flash_driver
*driver
= flash_driver_find_by_name(driver_name
);
825 /* no matching flash driver found */
826 LOG_ERROR("flash driver '%s' not found", driver_name
);
830 /* register flash specific commands */
831 if (NULL
!= driver
->commands
)
833 int retval
= register_commands(CMD_CTX
, NULL
,
835 if (ERROR_OK
!= retval
)
837 LOG_ERROR("couldn't register '%s' commands",
843 struct flash_bank
*c
= malloc(sizeof(*c
));
844 c
->name
= strdup(bank_name
);
847 c
->driver_priv
= NULL
;
848 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], c
->base
);
849 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], c
->size
);
850 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], c
->chip_width
);
851 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[4], c
->bus_width
);
857 retval
= CALL_COMMAND_HANDLER(driver
->flash_bank_command
, c
);
858 if (ERROR_OK
!= retval
)
860 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32
,
861 driver_name
, c
->base
);
871 COMMAND_HANDLER(handle_flash_banks_command
)
874 return ERROR_INVALID_ARGUMENTS
;
877 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++)
879 LOG_USER("#%u: %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", "
880 "buswidth %u, chipwidth %u", n
,
881 p
->driver
->name
, p
->base
, p
->size
,
882 p
->bus_width
, p
->chip_width
);
887 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
891 Jim_WrongNumArgs(interp
, 1, argv
,
892 "no arguments to 'flash list' command");
896 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
898 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
)
900 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
902 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "name", -1));
903 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, p
->driver
->name
, -1));
904 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "base", -1));
905 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->base
));
906 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "size", -1));
907 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->size
));
908 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "bus_width", -1));
909 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->bus_width
));
910 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "chip_width", -1));
911 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->chip_width
));
913 Jim_ListAppendElement(interp
, list
, elem
);
916 Jim_SetResult(interp
, list
);
922 COMMAND_HANDLER(handle_flash_init_command
)
925 return ERROR_COMMAND_SYNTAX_ERROR
;
927 static bool flash_initialized
= false;
928 if (flash_initialized
)
930 LOG_INFO("'flash init' has already been called");
933 flash_initialized
= true;
935 LOG_DEBUG("Initializing flash devices...");
936 return flash_init_drivers(CMD_CTX
);
939 static const struct command_registration flash_config_command_handlers
[] = {
942 .handler
= handle_flash_bank_command
,
943 .mode
= COMMAND_CONFIG
,
944 .usage
= "bank_id driver_name base_address size_bytes "
945 "chip_width_bytes bus_width_bytes target "
946 "[driver_options ...]",
947 .help
= "Define a new bank with the given name, "
948 "using the specified NOR flash driver.",
952 .mode
= COMMAND_CONFIG
,
953 .handler
= handle_flash_init_command
,
954 .help
= "Initialize flash devices.",
959 .handler
= handle_flash_banks_command
,
960 .help
= "Display table with information about flash banks.",
965 .jim_handler
= jim_flash_list
,
966 .help
= "Returns a list of details about the flash banks.",
968 COMMAND_REGISTRATION_DONE
970 static const struct command_registration flash_command_handlers
[] = {
974 .help
= "NOR flash command group",
975 .chain
= flash_config_command_handlers
,
977 COMMAND_REGISTRATION_DONE
980 int flash_register_commands(struct command_context
*cmd_ctx
)
982 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)