📄 flash.c
字号:
// Set load address/top
load_address = mem_addr;
load_address_end = (unsigned long)p->out_buf;
// Reload fis directory
flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
} else // dangling block
#endif
{
flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);
// Set load address/top
load_address = mem_addr;
load_address_end = mem_addr + img->data_length;
}
entry_address = (unsigned long)img->entry_point;
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length);
if (show_cksum) {
diag_printf("Checksum: 0x%08lx\n", cksum);
}
// When decompressing, leave CRC checking to decompressor
if (!decompress && img->file_cksum) {
if (cksum != img->file_cksum) {
diag_printf("** Warning - checksum failure. stored: 0x%08lx, computed: 0x%08lx\n",
img->file_cksum, cksum);
entry_address = NO_MEMORY;
}
}
#endif
}
#endif // CYGOPT_REDBOOT_FIS
static void
fis_write(int argc, char *argv[])
{
int stat;
unsigned long length;
CYG_ADDRESS mem_addr, flash_addr;
bool mem_addr_set = false;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[3];
bool prog_ok;
init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,
(void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");
init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,
(void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,
(void *)&length, (bool *)&length_set, "image length [in FLASH]");
if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0))
{
fis_usage("invalid arguments");
return;
}
if (!mem_addr_set || !flash_addr_set || !length_set) {
fis_usage("required parameter missing");
return;
}
// Round up length to FLASH block size
#ifndef CYGPKG_HAL_MIPS // FIXME: compiler is b0rken
length = ((length + flash_block_size - 1) / flash_block_size) * flash_block_size;
#endif
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
_show_invalid_flash_address(flash_addr, stat);
return;
}
if (flash_addr_set && flash_addr & (flash_block_size-1)) {
diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
diag_printf(" must be 0x%x aligned\n", flash_block_size);
return;
}
if ((mem_addr < (CYG_ADDRESS)ram_start) ||
((mem_addr+length) >= (CYG_ADDRESS)ram_end)) {
diag_printf("** WARNING: RAM address: %p may be invalid\n", (void *)mem_addr);
diag_printf(" valid range is %p-%p\n", (void *)ram_start, (void *)ram_end);
}
// Safety check - make sure the address range is not within the code we're running
if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
diag_printf("Can't program this region - contains code in use!\n");
return;
}
if (!verify_action("* CAUTION * about to program FLASH\n at %p..%p from %p",
(void *)flash_addr, (void *)(flash_addr+length-1),
(void *)mem_addr)) {
return; // The guy gave up
}
prog_ok = true;
if (prog_ok) {
// Erase area to be programmed
if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
diag_printf("Can't erase region at %p: %s\n", err_addr, flash_errmsg(stat));
prog_ok = false;
}
}
if (prog_ok) {
// Now program it
if ((stat = flash_program((void *)flash_addr, (void *)mem_addr, length, (void **)&err_addr)) != 0) {
diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));
prog_ok = false;
}
}
}
static void
fis_erase(int argc, char *argv[])
{
int stat;
unsigned long length;
CYG_ADDRESS flash_addr;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[2];
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
(void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
(void *)&length, (bool *)&length_set, "length");
if (!scan_opts(argc, argv, 2, opts, 2, (void **)0, 0, ""))
{
fis_usage("invalid arguments");
return;
}
if (!flash_addr_set || !length_set) {
fis_usage("missing argument");
return;
}
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
_show_invalid_flash_address(flash_addr, stat);
return;
}
if (flash_addr_set && flash_addr & (flash_block_size-1)) {
diag_printf("Invalid FLASH address: %p\n", (void *)flash_addr);
diag_printf(" must be 0x%x aligned\n", flash_block_size);
return;
}
// Safety check - make sure the address range is not within the code we're running
if (flash_code_overlaps((void *)flash_addr, (void *)(flash_addr+length-1))) {
diag_printf("Can't erase this region - contains code in use!\n");
return;
}
if ((stat = flash_erase((void *)flash_addr, length, (void **)&err_addr)) != 0) {
diag_printf("Error erasing at %p: %s\n", err_addr, flash_errmsg(stat));
}
}
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
static void
fis_lock(int argc, char *argv[])
{
char *name;
int stat;
unsigned long length;
CYG_ADDRESS flash_addr;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[2];
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
(void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
(void *)&length, (bool *)&length_set, "length");
if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
/* Get parameters from image if specified */
if (name) {
struct fis_image_desc *img;
if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
diag_printf("No image '%s' found\n", name);
return;
}
flash_addr = img->flash_base;
length = img->size;
} else if (!flash_addr_set || !length_set) {
fis_usage("missing argument");
return;
}
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
_show_invalid_flash_address(flash_addr, stat);
return;
}
if ((stat = flash_lock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
diag_printf("Error locking at %p: %s\n", err_addr, flash_errmsg(stat));
}
}
static void
fis_unlock(int argc, char *argv[])
{
char *name;
int stat;
unsigned long length;
CYG_ADDRESS flash_addr;
bool flash_addr_set = false;
bool length_set = false;
void *err_addr;
struct option_info opts[2];
init_opts(&opts[0], 'f', true, OPTION_ARG_TYPE_NUM,
(void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");
init_opts(&opts[1], 'l', true, OPTION_ARG_TYPE_NUM,
(void *)&length, (bool *)&length_set, "length");
if (!scan_opts(argc, argv, 2, opts, 2, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
if (name) {
struct fis_image_desc *img;
if ((img = fis_lookup(name, NULL)) == (struct fis_image_desc *)0) {
diag_printf("No image '%s' found\n", name);
return;
}
flash_addr = img->flash_base;
length = img->size;
} else if (!flash_addr_set || !length_set) {
fis_usage("missing argument");
return;
}
if (flash_addr_set &&
((stat = flash_verify_addr((void *)flash_addr)) ||
(stat = flash_verify_addr((void *)(flash_addr+length-1))))) {
_show_invalid_flash_address(flash_addr, stat);
return;
}
if ((stat = flash_unlock((void *)flash_addr, length, (void **)&err_addr)) != 0) {
diag_printf("Error unlocking at %p: %s\n", err_addr, flash_errmsg(stat));
}
}
#endif
// This is set non-zero if the FLASH subsystem has successfully been initialized
int __flash_init = 0;
void
_flash_info(void)
{
if (!__flash_init) return;
diag_printf("FLASH: %p - %p, %d blocks of %p bytes each.\n",
flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
}
bool
do_flash_init(void)
{
int stat;
void *err_addr;
if (!__flash_init) {
__flash_init = 1;
if ((stat = flash_init(diag_printf)) != 0) {
diag_printf("FLASH: driver init failed: %s\n", flash_errmsg(stat));
return false;
}
flash_get_limits((void *)0, (void **)&flash_start, (void **)&flash_end);
// Keep 'end' address as last valid location, to avoid wrap around problems
flash_end = (void *)((CYG_ADDRESS)flash_end - 1);
flash_get_block_info(&flash_block_size, &flash_num_blocks);
#ifdef CYGOPT_REDBOOT_FIS
fisdir_size = CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_COUNT * CYGNUM_REDBOOT_FIS_DIRECTORY_ENTRY_SIZE;
fisdir_size = ((fisdir_size + flash_block_size - 1) / flash_block_size) * flash_block_size;
# if defined(CYGPRI_REDBOOT_ZLIB_FLASH) && defined(CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER)
fis_work_block = fis_zlib_common_buffer;
if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < fisdir_size) {
diag_printf("FLASH: common buffer too small\n");
return false;
}
# else
workspace_end = (unsigned char *)(workspace_end-fisdir_size);
fis_work_block = workspace_end;
# endif
if (CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK < 0) {
fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
} else {
fis_addr = (void *)((CYG_ADDRESS)flash_start +
(CYGNUM_REDBOOT_FIS_DIRECTORY_BLOCK*flash_block_size));
}
if (((CYG_ADDRESS)fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
diag_printf("FIS directory doesn't fit\n");
return false;
}
flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
#endif
}
return true;
}
// Wrapper to avoid compiler warnings
static void
_do_flash_init(void)
{
static int init_done = 0;
if (init_done) return;
init_done = 1;
do_flash_init();
}
RedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);
static void
do_fis(int argc, char *argv[])
{
struct cmd *cmd;
if (argc < 2) {
fis_usage("too few arguments");
return;
}
if (!do_flash_init()) {
diag_printf("Sorry, no FLASH memory is available\n");
return;
}
if ((cmd = cmd_search(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__,
argv[1])) != (struct cmd *)0) {
(cmd->fun)(argc, argv);
return;
}
fis_usage("unrecognized command");
}
// EOF flash.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -