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_maybe_probe
, unsigned name_index
,
35 struct flash_bank
**bank
, bool do_probe
)
37 const char *name
= CMD_ARGV
[name_index
];
40 retval
= get_flash_bank_by_name(name
, bank
);
42 *bank
= get_flash_bank_by_name_noprobe(name
);
46 if (retval
!= ERROR_OK
)
52 COMMAND_PARSE_NUMBER(uint
, name
, bank_num
);
55 return get_flash_bank_by_num(bank_num
, bank
);
57 *bank
= get_flash_bank_by_num_noprobe(bank_num
);
58 retval
= (bank
) ? ERROR_OK
: ERROR_FAIL
;
63 COMMAND_HELPER(flash_command_get_bank
, unsigned name_index
,
64 struct flash_bank
**bank
)
66 return CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe
,
67 name_index
, bank
, true);
70 COMMAND_HANDLER(handle_flash_info_command
)
77 return ERROR_COMMAND_SYNTAX_ERROR
;
79 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
80 if (retval
!= ERROR_OK
)
86 /* attempt auto probe */
87 retval
= p
->driver
->auto_probe(p
);
88 if (retval
!= ERROR_OK
)
91 /* We must query the hardware to avoid printing stale information! */
92 retval
= p
->driver
->protect_check(p
);
93 if (retval
!= ERROR_OK
)
96 command_print(CMD_CTX
,
97 "#%d : %s at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
98 ", buswidth %i, chipwidth %i",
105 for (j
= 0; j
< p
->num_sectors
; j
++) {
108 if (p
->sectors
[j
].is_protected
== 0)
109 protect_state
= "not protected";
110 else if (p
->sectors
[j
].is_protected
== 1)
111 protect_state
= "protected";
113 protect_state
= "protection state unknown";
115 command_print(CMD_CTX
,
116 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
118 p
->sectors
[j
].offset
,
120 p
->sectors
[j
].size
>> 10,
124 if (p
->driver
->info
!= NULL
) {
125 retval
= p
->driver
->info(p
, buf
, sizeof(buf
));
126 if (retval
== ERROR_OK
)
127 command_print(CMD_CTX
, "%s", buf
);
129 LOG_ERROR("error retrieving flash info");
136 COMMAND_HANDLER(handle_flash_probe_command
)
138 struct flash_bank
*p
;
142 return ERROR_COMMAND_SYNTAX_ERROR
;
144 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank_maybe_probe
, 0, &p
, false);
145 if (retval
!= ERROR_OK
)
149 retval
= p
->driver
->probe(p
);
150 if (retval
== ERROR_OK
)
151 command_print(CMD_CTX
,
152 "flash '%s' found at 0x%8.8" PRIx32
,
156 command_print(CMD_CTX
, "flash bank '#%s' is out of bounds", CMD_ARGV
[0]);
163 COMMAND_HANDLER(handle_flash_erase_check_command
)
166 return ERROR_COMMAND_SYNTAX_ERROR
;
168 struct flash_bank
*p
;
169 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
170 if (ERROR_OK
!= retval
)
174 retval
= p
->driver
->erase_check(p
);
175 if (retval
== ERROR_OK
)
176 command_print(CMD_CTX
, "successfully checked erase state");
178 command_print(CMD_CTX
,
179 "unknown error when checking erase state of flash bank #%s at 0x%8.8" PRIx32
,
184 for (j
= 0; j
< p
->num_sectors
; j
++) {
187 if (p
->sectors
[j
].is_erased
== 0)
188 erase_state
= "not erased";
189 else if (p
->sectors
[j
].is_erased
== 1)
190 erase_state
= "erased";
192 erase_state
= "erase state unknown";
194 command_print(CMD_CTX
,
195 "\t#%3i: 0x%8.8" PRIx32
" (0x%" PRIx32
" %" PRIi32
"kB) %s",
197 p
->sectors
[j
].offset
,
199 p
->sectors
[j
].size
>> 10,
206 COMMAND_HANDLER(handle_flash_erase_address_command
)
208 struct flash_bank
*p
;
209 int retval
= ERROR_OK
;
213 bool do_unlock
= false;
214 struct target
*target
= get_current_target(CMD_CTX
);
216 while (CMD_ARGC
>= 3) {
217 /* Optionally pad out the address range to block/sector
218 * boundaries. We can't know if there's data in that part
219 * of the flash; only do padding if we're told to.
221 if (strcmp("pad", CMD_ARGV
[0]) == 0)
223 else if (strcmp("unlock", CMD_ARGV
[0]) == 0)
226 return ERROR_COMMAND_SYNTAX_ERROR
;
231 return ERROR_COMMAND_SYNTAX_ERROR
;
233 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
234 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], length
);
237 command_print(CMD_CTX
, "Length must be >0");
238 return ERROR_COMMAND_SYNTAX_ERROR
;
241 retval
= get_flash_bank_by_addr(target
, address
, true, &p
);
242 if (retval
!= ERROR_OK
)
245 /* We can't know if we did a resume + halt, in which case we no longer know the erased state
249 struct duration bench
;
250 duration_start(&bench
);
253 retval
= flash_unlock_address_range(target
, address
, length
);
255 if (retval
== ERROR_OK
)
256 retval
= flash_erase_address_range(target
, do_pad
, address
, length
);
258 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
)) {
259 command_print(CMD_CTX
, "erased address 0x%8.8" PRIx32
" (length %" PRIi32
")"
260 " in %fs (%0.3f KiB/s)", address
, length
,
261 duration_elapsed(&bench
), duration_kbps(&bench
, length
));
267 static int flash_check_sector_parameters(struct command_context
*cmd_ctx
,
268 uint32_t first
, uint32_t last
, uint32_t num_sectors
)
270 if (!(first
<= last
)) {
271 command_print(cmd_ctx
, "ERROR: "
272 "first sector must be <= last sector");
276 if (!(last
<= (num_sectors
- 1))) {
277 command_print(cmd_ctx
, "ERROR: last sector must be <= %d",
278 (int) num_sectors
- 1);
285 COMMAND_HANDLER(handle_flash_erase_command
)
288 return ERROR_COMMAND_SYNTAX_ERROR
;
293 struct flash_bank
*p
;
296 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
297 if (retval
!= ERROR_OK
)
300 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
301 if (strcmp(CMD_ARGV
[2], "last") == 0)
302 last
= p
->num_sectors
- 1;
304 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
306 retval
= flash_check_sector_parameters(CMD_CTX
, first
, last
, p
->num_sectors
);
307 if (retval
!= ERROR_OK
)
310 struct duration bench
;
311 duration_start(&bench
);
313 retval
= flash_driver_erase(p
, first
, last
);
315 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
)) {
316 command_print(CMD_CTX
, "erased sectors %" PRIu32
" "
317 "through %" PRIu32
" on flash bank %d "
318 "in %fs", first
, last
, p
->bank_number
, duration_elapsed(&bench
));
324 COMMAND_HANDLER(handle_flash_protect_command
)
327 return ERROR_COMMAND_SYNTAX_ERROR
;
332 struct flash_bank
*p
;
335 retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
336 if (retval
!= ERROR_OK
)
339 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], first
);
340 if (strcmp(CMD_ARGV
[2], "last") == 0)
341 last
= p
->num_sectors
- 1;
343 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], last
);
346 COMMAND_PARSE_ON_OFF(CMD_ARGV
[3], set
);
348 retval
= flash_check_sector_parameters(CMD_CTX
, first
, last
, p
->num_sectors
);
349 if (retval
!= ERROR_OK
)
352 retval
= flash_driver_protect(p
, set
, first
, last
);
353 if (retval
== ERROR_OK
) {
354 command_print(CMD_CTX
, "%s protection for sectors %i "
355 "through %i on flash bank %d",
356 (set
) ? "set" : "cleared", (int) first
,
357 (int) last
, p
->bank_number
);
363 COMMAND_HANDLER(handle_flash_write_image_command
)
365 struct target
*target
= get_current_target(CMD_CTX
);
372 /* flash auto-erase is disabled by default*/
374 bool auto_unlock
= false;
377 if (strcmp(CMD_ARGV
[0], "erase") == 0) {
381 command_print(CMD_CTX
, "auto erase enabled");
382 } else if (strcmp(CMD_ARGV
[0], "unlock") == 0) {
386 command_print(CMD_CTX
, "auto unlock enabled");
392 return ERROR_COMMAND_SYNTAX_ERROR
;
395 LOG_ERROR("no target selected");
399 struct duration bench
;
400 duration_start(&bench
);
403 image
.base_address_set
= 1;
404 COMMAND_PARSE_NUMBER(llong
, CMD_ARGV
[1], image
.base_address
);
406 image
.base_address_set
= 0;
407 image
.base_address
= 0x0;
410 image
.start_address_set
= 0;
412 retval
= image_open(&image
, CMD_ARGV
[0], (CMD_ARGC
== 3) ? CMD_ARGV
[2] : NULL
);
413 if (retval
!= ERROR_OK
)
416 retval
= flash_write_unlock(target
, &image
, &written
, auto_erase
, auto_unlock
);
417 if (retval
!= ERROR_OK
) {
422 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
)) {
423 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes from file %s "
424 "in %fs (%0.3f KiB/s)", written
, CMD_ARGV
[0],
425 duration_elapsed(&bench
), duration_kbps(&bench
, written
));
433 COMMAND_HANDLER(handle_flash_fill_command
)
440 uint32_t cur_size
= 0;
441 uint32_t chunk_count
;
442 struct target
*target
= get_current_target(CMD_CTX
);
445 int retval
= ERROR_OK
;
447 static size_t const chunksize
= 1024;
448 uint8_t *chunk
= NULL
, *readback
= NULL
;
451 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
455 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
456 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], pattern
);
457 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], count
);
459 chunk
= malloc(chunksize
);
463 readback
= malloc(chunksize
);
464 if (readback
== NULL
) {
472 switch (CMD_NAME
[4]) {
483 retval
= ERROR_COMMAND_SYNTAX_ERROR
;
487 chunk_count
= MIN(count
, (chunksize
/ wordsize
));
490 for (i
= 0; i
< chunk_count
; i
++)
491 target_buffer_set_u32(target
, chunk
+ i
* wordsize
, pattern
);
494 for (i
= 0; i
< chunk_count
; i
++)
495 target_buffer_set_u16(target
, chunk
+ i
* wordsize
, pattern
);
498 memset(chunk
, pattern
, chunk_count
);
501 LOG_ERROR("BUG: can't happen");
505 struct duration bench
;
506 duration_start(&bench
);
508 for (wrote
= 0; wrote
< (count
*wordsize
); wrote
+= cur_size
) {
509 struct flash_bank
*bank
;
511 retval
= get_flash_bank_by_addr(target
, address
, true, &bank
);
512 if (retval
!= ERROR_OK
)
515 cur_size
= MIN((count
* wordsize
- wrote
), chunksize
);
516 err
= flash_driver_write(bank
, chunk
, address
- bank
->base
+ wrote
, cur_size
);
517 if (err
!= ERROR_OK
) {
522 err
= flash_driver_read(bank
, readback
, address
- bank
->base
+ wrote
, cur_size
);
523 if (err
!= ERROR_OK
) {
528 for (i
= 0; i
< cur_size
; i
++) {
529 if (readback
[i
] != chunk
[i
]) {
531 "Verification error address 0x%08" PRIx32
", read back 0x%02x, expected 0x%02x",
541 if ((retval
== ERROR_OK
) && (duration_measure(&bench
) == ERROR_OK
)) {
542 command_print(CMD_CTX
, "wrote %" PRIu32
" bytes to 0x%8.8" PRIx32
543 " in %fs (%0.3f KiB/s)", wrote
, address
,
544 duration_elapsed(&bench
), duration_kbps(&bench
, wrote
));
554 COMMAND_HANDLER(handle_flash_write_bank_command
)
558 struct fileio fileio
;
561 return ERROR_COMMAND_SYNTAX_ERROR
;
563 struct duration bench
;
564 duration_start(&bench
);
566 struct flash_bank
*p
;
567 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
568 if (ERROR_OK
!= retval
)
571 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], offset
);
573 if (fileio_open(&fileio
, CMD_ARGV
[1], FILEIO_READ
, FILEIO_BINARY
) != ERROR_OK
)
577 retval
= fileio_size(&fileio
, &filesize
);
578 if (retval
!= ERROR_OK
) {
579 fileio_close(&fileio
);
583 buffer
= malloc(filesize
);
584 if (buffer
== NULL
) {
585 fileio_close(&fileio
);
586 LOG_ERROR("Out of memory");
590 if (fileio_read(&fileio
, filesize
, buffer
, &buf_cnt
) != ERROR_OK
) {
592 fileio_close(&fileio
);
596 retval
= flash_driver_write(p
, buffer
, offset
, buf_cnt
);
601 if ((ERROR_OK
== retval
) && (duration_measure(&bench
) == ERROR_OK
)) {
602 command_print(CMD_CTX
, "wrote %ld bytes from file %s to flash bank %u"
603 " at offset 0x%8.8" PRIx32
" in %fs (%0.3f KiB/s)",
604 (long)filesize
, CMD_ARGV
[1], p
->bank_number
, offset
,
605 duration_elapsed(&bench
), duration_kbps(&bench
, filesize
));
608 fileio_close(&fileio
);
613 void flash_set_dirty(void)
615 struct flash_bank
*c
;
618 /* set all flash to require erasing */
619 for (c
= flash_bank_list(); c
; c
= c
->next
) {
620 for (i
= 0; i
< c
->num_sectors
; i
++)
621 c
->sectors
[i
].is_erased
= 0;
625 COMMAND_HANDLER(handle_flash_padded_value_command
)
628 return ERROR_COMMAND_SYNTAX_ERROR
;
630 struct flash_bank
*p
;
631 int retval
= CALL_COMMAND_HANDLER(flash_command_get_bank
, 0, &p
);
632 if (ERROR_OK
!= retval
)
635 COMMAND_PARSE_NUMBER(u8
, CMD_ARGV
[1], p
->default_padded_value
);
637 command_print(CMD_CTX
, "Default padded value set to 0x%" PRIx8
" for flash bank %u", \
638 p
->default_padded_value
, p
->bank_number
);
643 static const struct command_registration flash_exec_command_handlers
[] = {
646 .handler
= handle_flash_probe_command
,
647 .mode
= COMMAND_EXEC
,
649 .help
= "Identify a flash bank.",
653 .handler
= handle_flash_info_command
,
654 .mode
= COMMAND_EXEC
,
656 .help
= "Print information about a flash bank.",
659 .name
= "erase_check",
660 .handler
= handle_flash_erase_check_command
,
661 .mode
= COMMAND_EXEC
,
663 .help
= "Check erase state of all blocks in a "
667 .name
= "erase_sector",
668 .handler
= handle_flash_erase_command
,
669 .mode
= COMMAND_EXEC
,
670 .usage
= "bank_id first_sector_num last_sector_num",
671 .help
= "Erase a range of sectors in a flash bank.",
674 .name
= "erase_address",
675 .handler
= handle_flash_erase_address_command
,
676 .mode
= COMMAND_EXEC
,
677 .usage
= "['pad'] ['unlock'] address length",
678 .help
= "Erase flash sectors starting at address and "
679 "continuing for length bytes. If 'pad' is specified, "
680 "data outside that range may also be erased: the start "
681 "address may be decreased, and length increased, so "
682 "that all of the first and last sectors are erased. "
683 "If 'unlock' is specified, then the flash is unprotected "
689 .handler
= handle_flash_fill_command
,
690 .mode
= COMMAND_EXEC
,
691 .usage
= "address value n",
692 .help
= "Fill n words with 32-bit value, starting at "
693 "word address. (No autoerase.)",
697 .handler
= handle_flash_fill_command
,
698 .mode
= COMMAND_EXEC
,
699 .usage
= "address value n",
700 .help
= "Fill n halfwords with 16-bit value, starting at "
701 "word address. (No autoerase.)",
705 .handler
= handle_flash_fill_command
,
706 .mode
= COMMAND_EXEC
,
707 .usage
= "address value n",
708 .help
= "Fill n bytes with 8-bit value, starting at "
709 "word address. (No autoerase.)",
712 .name
= "write_bank",
713 .handler
= handle_flash_write_bank_command
,
714 .mode
= COMMAND_EXEC
,
715 .usage
= "bank_id filename offset",
716 .help
= "Write binary data from file to flash bank, "
717 "starting at specified byte offset from the "
718 "beginning of the bank.",
721 .name
= "write_image",
722 .handler
= handle_flash_write_image_command
,
723 .mode
= COMMAND_EXEC
,
724 .usage
= "[erase] [unlock] filename [offset [file_type]]",
725 .help
= "Write an image to flash. Optionally first unprotect "
726 "and/or erase the region to be used. Allow optional "
727 "offset from beginning of bank (defaults to zero)",
731 .handler
= handle_flash_protect_command
,
732 .mode
= COMMAND_EXEC
,
733 .usage
= "bank_id first_sector [last_sector|'last'] "
735 .help
= "Turn protection on or off for a range of sectors "
736 "in a given flash bank.",
739 .name
= "padded_value",
740 .handler
= handle_flash_padded_value_command
,
741 .mode
= COMMAND_EXEC
,
742 .usage
= "bank_id value",
743 .help
= "Set default flash padded value",
745 COMMAND_REGISTRATION_DONE
748 static int flash_init_drivers(struct command_context
*cmd_ctx
)
750 if (!flash_bank_list())
753 struct command
*parent
= command_find_in_context(cmd_ctx
, "flash");
754 return register_commands(cmd_ctx
, parent
, flash_exec_command_handlers
);
757 COMMAND_HANDLER(handle_flash_bank_command
)
760 LOG_ERROR("usage: flash bank <name> <driver> "
761 "<base> <size> <chip_width> <bus_width> <target>");
762 return ERROR_COMMAND_SYNTAX_ERROR
;
764 /* save bank name and advance arguments for compatibility */
765 const char *bank_name
= *CMD_ARGV
++;
768 struct target
*target
= get_target(CMD_ARGV
[5]);
769 if (target
== NULL
) {
770 LOG_ERROR("target '%s' not defined", CMD_ARGV
[5]);
774 const char *driver_name
= CMD_ARGV
[0];
775 struct flash_driver
*driver
= flash_driver_find_by_name(driver_name
);
776 if (NULL
== driver
) {
777 /* no matching flash driver found */
778 LOG_ERROR("flash driver '%s' not found", driver_name
);
782 /* check the flash bank name is unique */
783 if (get_flash_bank_by_name_noprobe(bank_name
) != NULL
) {
784 /* flash bank name already exists */
785 LOG_ERROR("flash bank name '%s' already exists", bank_name
);
789 /* register flash specific commands */
790 if (NULL
!= driver
->commands
) {
791 int retval
= register_commands(CMD_CTX
, NULL
,
793 if (ERROR_OK
!= retval
) {
794 LOG_ERROR("couldn't register '%s' commands",
800 struct flash_bank
*c
= malloc(sizeof(*c
));
801 c
->name
= strdup(bank_name
);
804 c
->driver_priv
= NULL
;
805 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], c
->base
);
806 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[2], c
->size
);
807 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[3], c
->chip_width
);
808 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[4], c
->bus_width
);
809 c
->default_padded_value
= 0xff;
815 retval
= CALL_COMMAND_HANDLER(driver
->flash_bank_command
, c
);
816 if (ERROR_OK
!= retval
) {
817 LOG_ERROR("'%s' driver rejected flash bank at 0x%8.8" PRIx32
"; usage: %s",
818 driver_name
, c
->base
, driver
->usage
);
823 if (driver
->usage
== NULL
)
824 LOG_DEBUG("'%s' driver usage field missing", driver_name
);
831 COMMAND_HANDLER(handle_flash_banks_command
)
834 return ERROR_COMMAND_SYNTAX_ERROR
;
837 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
, n
++) {
838 LOG_USER("#%d : %s (%s) at 0x%8.8" PRIx32
", size 0x%8.8" PRIx32
", "
839 "buswidth %u, chipwidth %u", p
->bank_number
,
840 p
->name
, p
->driver
->name
, p
->base
, p
->size
,
841 p
->bus_width
, p
->chip_width
);
846 static int jim_flash_list(Jim_Interp
*interp
, int argc
, Jim_Obj
* const *argv
)
849 Jim_WrongNumArgs(interp
, 1, argv
,
850 "no arguments to 'flash list' command");
854 Jim_Obj
*list
= Jim_NewListObj(interp
, NULL
, 0);
856 for (struct flash_bank
*p
= flash_bank_list(); p
; p
= p
->next
) {
857 Jim_Obj
*elem
= Jim_NewListObj(interp
, NULL
, 0);
859 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "name", -1));
860 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, p
->driver
->name
, -1));
861 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "base", -1));
862 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->base
));
863 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "size", -1));
864 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->size
));
865 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "bus_width", -1));
866 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->bus_width
));
867 Jim_ListAppendElement(interp
, elem
, Jim_NewStringObj(interp
, "chip_width", -1));
868 Jim_ListAppendElement(interp
, elem
, Jim_NewIntObj(interp
, p
->chip_width
));
870 Jim_ListAppendElement(interp
, list
, elem
);
873 Jim_SetResult(interp
, list
);
878 COMMAND_HANDLER(handle_flash_init_command
)
881 return ERROR_COMMAND_SYNTAX_ERROR
;
883 static bool flash_initialized
;
884 if (flash_initialized
) {
885 LOG_INFO("'flash init' has already been called");
888 flash_initialized
= true;
890 LOG_DEBUG("Initializing flash devices...");
891 return flash_init_drivers(CMD_CTX
);
894 static const struct command_registration flash_config_command_handlers
[] = {
897 .handler
= handle_flash_bank_command
,
898 .mode
= COMMAND_CONFIG
,
899 .usage
= "bank_id driver_name base_address size_bytes "
900 "chip_width_bytes bus_width_bytes target "
901 "[driver_options ...]",
902 .help
= "Define a new bank with the given name, "
903 "using the specified NOR flash driver.",
907 .mode
= COMMAND_CONFIG
,
908 .handler
= handle_flash_init_command
,
909 .help
= "Initialize flash devices.",
914 .handler
= handle_flash_banks_command
,
915 .help
= "Display table with information about flash banks.",
920 .jim_handler
= jim_flash_list
,
921 .help
= "Returns a list of details about the flash banks.",
923 COMMAND_REGISTRATION_DONE
925 static const struct command_registration flash_command_handlers
[] = {
929 .help
= "NOR flash command group",
930 .chain
= flash_config_command_handlers
,
932 COMMAND_REGISTRATION_DONE
935 int flash_register_commands(struct command_context
*cmd_ctx
)
937 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)