📄 flash.c
字号:
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, &name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
#ifdef CYGOPT_REDBOOT_FIS
/* 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
#endif
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, &name, OPTION_ARG_TYPE_STR, "image name"))
{
fis_usage("invalid arguments");
return;
}
#ifdef CYGOPT_REDBOOT_FIS
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
#endif
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 - 0x%x, %d blocks of %p bytes each.\n",
flash_start, (CYG_ADDRWORD)flash_end + 1, flash_num_blocks, (void *)flash_block_size);
}
/* Returns -1 on failure, 0 on success, 1 if it was successfull
but a failed fis update was detected */
int
do_flash_init(void)
{
int stat;
#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
struct fis_image_desc img0;
struct fis_image_desc img1;
int fis_update_was_interrupted=0;
void *err_addr;
//check the size of fis_valid_info
CYG_ASSERT((sizeof(struct fis_valid_info)<=sizeof(img0.u.name)), "fis_valid_info size mismatch");
//try to check the alignment of version_count
CYG_ASSERT((((unsigned long)&img0.u.valid_info.version_count - (unsigned long)&img0) % sizeof(unsigned long) == 0), "alignment problem");
#endif
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 -1;
}
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 -1;
}
# 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 -1;
}
#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
if (CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK < 0) {
redundant_fis_addr = (void *)((CYG_ADDRESS)flash_end + 1 +
(CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK*flash_block_size));
} else {
redundant_fis_addr = (void *)((CYG_ADDRESS)flash_start +
(CYGNUM_REDBOOT_FIS_REDUNDANT_DIRECTORY_BLOCK*flash_block_size));
}
if (((CYG_ADDRESS)redundant_fis_addr + fisdir_size - 1) > (CYG_ADDRESS)flash_end) {
diag_printf("Redundant FIS directory doesn't fit\n");
return -1;
}
FLASH_READ(fis_addr, &img0, sizeof(img0), (void **)&err_addr);
FLASH_READ(redundant_fis_addr, &img1, sizeof(img1), (void **)&err_addr);
if (strncmp(img0.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)
{
memset(&img0, 0, sizeof(img0));
}
if (strncmp(img1.u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH)!=0)
{
memset(&img1, 0, sizeof(img0));
}
#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
img0.u.valid_info.version_count = CYG_SWAP32(img0.u.valid_info.version_count);
img1.u.valid_info.version_count = CYG_SWAP32(img1.u.valid_info.version_count);
#endif
if (fis_get_valid_buf(&img0, &img1, &fis_update_was_interrupted)==1)
{
// Valid, so swap primary and secondary
void * tmp;
tmp = fis_addr;
fis_addr = redundant_fis_addr;
redundant_fis_addr = tmp;
}
#endif
fis_read_directory();
#endif
}
#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
if (fis_update_was_interrupted)
return 1;
else
return 0;
#else
return 0;
#endif
}
// 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()<0) {
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 + -