flash.c
来自「ecos实时嵌入式操作系统」· C语言 代码 · 共 1,912 行 · 第 1/5 页
C
1,912 行
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 initializedstatic 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);}static booldo_flash_init(void){ int stat; if (!__flash_init) { if ((stat = flash_init((void *)(workspace_end-FLASH_MIN_WORKSPACE), FLASH_MIN_WORKSPACE, 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); workspace_end = (unsigned char *)(workspace_end-FLASH_MIN_WORKSPACE);#ifdef CYGOPT_REDBOOT_FIS# ifdef CYGOPT_REDBOOT_FIS_ZLIB_COMMON_BUFFER fis_work_block = fis_zlib_common_buffer; if(CYGNUM_REDBOOT_FIS_ZLIB_COMMON_BUFFER_SIZE < flash_block_size) { diag_printf("FLASH: common buffer too small\n"); workspace_end += FLASH_MIN_WORKSPACE; return false; }# else workspace_end = (unsigned char *)(workspace_end-flash_block_size); fis_work_block = workspace_end;# endif fisdir_size = flash_block_size; 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)); }#endif __flash_init = 1; } return true;}// Wrapper to avoid compiler warningsstatic void_do_flash_init(void){ do_flash_init();}#ifndef CYGOPT_REDBOOT_FLASH_CONFIGRedBoot_init(_do_flash_init, RedBoot_INIT_FIRST);#endifstatic voiddo_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");}#ifdef CYGSEM_REDBOOT_FLASH_CONFIGstatic bool config_ok;#define CONFIG_KEY1 0x0BADFACE#define CONFIG_KEY2 0xDEADDEAD#define CONFIG_DONE 0#define CONFIG_ABORT -1#define CONFIG_CHANGED 1#define CONFIG_OK 2#define CONFIG_BACK 3#define CONFIG_BAD 4// Note: the following options are related. If 'boot_script' is false, then// the other values are used in the configuration. Because of the way// that configuration tables are generated, they should have names which// are related. The configuration options will show up lexicographically// ordered, thus the peculiar naming.RedBoot_config_option("Run script at boot", boot_script, ALWAYS_ENABLED, true, CONFIG_BOOL, false );RedBoot_config_option("Boot script", boot_script_data, "boot_script", true, CONFIG_SCRIPT, "" );// Some preprocessor magic for building the [constant] prompt string#define __cat(s1,c2,s3) s1 #c2 s3#define _cat(s1,c2,s3) __cat(s1,c2,s3)RedBoot_config_option(_cat("Boot script timeout (", CYGNUM_REDBOOT_BOOT_SCRIPT_TIMEOUT_RESOLUTION, "ms resolution)"), boot_script_timeout, "boot_script", true, CONFIG_INT, 0 );#undef __cat#undef _cat#ifdef CYGSEM_REDBOOT_VARIABLE_BAUD_RATERedBoot_config_option("Console baud rate", console_baud_rate, ALWAYS_ENABLED, true, CONFIG_INT, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD );#endifCYG_HAL_TABLE_BEGIN( __CONFIG_options_TAB__, RedBoot_config_options);CYG_HAL_TABLE_END( __CONFIG_options_TAB_END__, RedBoot_config_options);extern struct config_option __CONFIG_options_TAB__[], __CONFIG_options_TAB_END__[];// // Layout of config data// Each data item is variable length, with the name, type and dependencies// encoded into the object.// offset contents// 0 data type// 1 length of name (N)// 2 enable sense// 3 length of enable key (M)// 4 key name// N+4 enable key// M+N+4 data value//#define CONFIG_OBJECT_TYPE(dp) (dp)[0]#define CONFIG_OBJECT_KEYLEN(dp) (dp)[1]#define CONFIG_OBJECT_ENABLE_SENSE(dp) (dp)[2]#define CONFIG_OBJECT_ENABLE_KEYLEN(dp) (dp)[3]#define CONFIG_OBJECT_KEY(dp) ((dp)+4)#define CONFIG_OBJECT_ENABLE_KEY(dp) ((dp)+4+CONFIG_OBJECT_KEYLEN(dp))#define CONFIG_OBJECT_VALUE(dp) ((dp)+4+CONFIG_OBJECT_KEYLEN(dp)+CONFIG_OBJECT_ENABLE_KEYLEN(dp))#define LIST_OPT_LIST_ONLY (1)#define LIST_OPT_NICKNAMES (2)#define LIST_OPT_FULLNAMES (4)#define LIST_OPT_DUMBTERM (8)static void config_init(void);static intget_config(unsigned char *dp, char *title, int list_opt, char *newvalue ){ char line[256], hold_line[256], *sp, *lp; int ret; bool hold_bool_val, new_bool_val, enable; unsigned long hold_int_val, new_int_val;#ifdef CYGPKG_REDBOOT_NETWORKING in_addr_t hold_ip_val, new_ip_val; enet_addr_t hold_esa_val; int esa_ptr; char *esp;#endif void *val_ptr; int type; if (CONFIG_OBJECT_ENABLE_KEYLEN(dp)) { flash_get_config(CONFIG_OBJECT_ENABLE_KEY(dp), &enable, CONFIG_BOOL); if (((bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && !enable) || (!(bool)CONFIG_OBJECT_ENABLE_SENSE(dp) && enable)) { return CONFIG_OK; // Disabled field } } lp = line; *lp = '\0'; val_ptr = (void *)CONFIG_OBJECT_VALUE(dp); if (LIST_OPT_NICKNAMES & list_opt) diag_printf("%s: ", CONFIG_OBJECT_KEY(dp)); if (LIST_OPT_FULLNAMES & list_opt) { if (title != (char *)NULL) { diag_printf("%s: ", title); } else { diag_printf("%s: ", CONFIG_OBJECT_KEY(dp)); } } switch (type = CONFIG_OBJECT_TYPE(dp)) { case CONFIG_BOOL: memcpy(&hold_bool_val, val_ptr, sizeof(bool)); lp += diag_sprintf(lp, "%s", hold_bool_val ? "true" : "false"); break; case CONFIG_INT: memcpy(&hold_int_val, val_ptr, sizeof(unsigned long)); lp += diag_sprintf(lp, "%ld", hold_int_val); break;#ifdef CYGPKG_REDBOOT_NETWORKING case CONFIG_IP: lp += diag_sprintf(lp, "%s", inet_ntoa((in_addr_t *)val_ptr)); if (0 == strcmp("0.0.0.0", line) && !(LIST_OPT_LIST_ONLY & list_opt)) { // then we have a deeply unhelpful starting text - kill it off // (unless we are just listing all values) lp = line; *lp = '\0'; } break; case CONFIG_ESA: for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) { lp += diag_sprintf(lp, "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]); if (esa_ptr < (sizeof(enet_addr_t)-1)) lp += diag_sprintf(lp, ":"); } break;#endif case CONFIG_STRING: lp += diag_sprintf(lp, "%s", (unsigned char *)val_ptr); break; case CONFIG_SCRIPT: diag_printf("\n"); sp = lp = (unsigned char *)val_ptr; while (*sp) { while (*lp != '\n') lp++; *lp = '\0'; diag_printf(".. %s\n", sp); *lp++ = '\n'; sp = lp; } break; } if (LIST_OPT_LIST_ONLY & list_opt) { diag_printf("%s\n", line); return CONFIG_OK; } if (type != CONFIG_SCRIPT) { if (NULL != newvalue) { ret = strlen(newvalue); if (ret > sizeof(line)) return CONFIG_BAD; strcpy(hold_line, line); // Hold the old value for comparison strcpy(line, newvalue); diag_printf("Setting to %s\n", newvalue); } else { // read from terminal strcpy(hold_line, line); if (LIST_OPT_DUMBTERM & list_opt) { diag_printf( (CONFIG_STRING == type ? "%s > " : "%s ? " ), line); *line = '\0'; } ret = _rb_gets_preloaded(line, sizeof(line), 0); } if (ret < 0) return CONFIG_ABORT; // empty input - leave value untouched (else DNS goes away for a // minute to try to look it up) but we must accept empty value for strings. if (0 == line[0] && CONFIG_STRING != type) return CONFIG_OK; if (strcmp(line, hold_line) == 0) return CONFIG_OK; // Just a CR - leave value untouched lp = &line[strlen(line)-1]; if (*lp == '.') return CONFIG_DONE; if (*lp == '^') return CONFIG_BACK; } switch (type) { case CONFIG_BOOL: memcpy(&hold_bool_val, val_ptr, sizeof(bool)); if (!parse_bool(line, &new_bool_val)) { return CONFIG_BAD; } if (hold_bool_val != new_bool_val) { memcpy(val_ptr, &new_bool_val, sizeof(bool)); return CONFIG_CHANGED; } else { return CONFIG_OK; } break; case CONFIG_INT: memcpy(&hold_int_val, val_ptr, sizeof(unsigned long)); if (!parse_num(line, &new_int_val, 0, 0)) { return CONFIG_BAD; } if (hold_int_val != new_int_val) { memcpy(val_ptr, &new_int_val, sizeof(unsigned long)); return CONFIG_CHANGED; } else { return CONFIG_OK; } break;#ifdef CYGPKG_REDBOOT_NETWORKING case CONFIG_IP: memcpy(&hold_ip_val.s_addr, &((in_addr_t *)val_ptr)->s_addr, sizeof(in_addr_t)); if (!_gethostbyname(line, &new_ip_val)) { return CONFIG_BAD; } if (hold_ip_val.s_addr != new_ip_val.s_addr) { memcpy(val_ptr, &new_ip_val, sizeof(in_addr_t)); return CONFIG_CHANGED; } else { return CONFIG_OK; } break; case CONFIG_ESA: memcpy(&hold_esa_val, val_ptr, sizeof(enet_addr_t)); esp = line; for (esa_ptr = 0; esa_ptr < sizeof(enet_addr_t); esa_ptr++) { unsigned long esa_byte; if (!parse_num(esp, &esa_byte, &esp, ":")) { memcpy(val_ptr, &hold_esa_val, sizeof(enet_addr_t)); return CONFIG_BAD; } ((unsigned char *)val_ptr)[esa_ptr] = esa_byte; } return CONFIG_CHANGED; break;#endif case CONFIG_SCRIPT: // Assume it always changes sp = (unsigned char *)val_ptr; diag_printf("Enter script, terminate with empty line\n"); while (true) { *sp = '\0'; diag_printf(">> "); ret = _rb_gets(line, sizeof(line), 0); if (ret < 0) return CONFIG_ABORT; if (strlen(line) == 0) break; lp = line; while (*lp) { *sp++ = *lp++; } *sp++ = '\n'; } break; case CONFIG_STRING: if (strlen(line) >= MAX_STRING_LENGTH) { diag_printf("Sorry, value is too long\n"); return CONFIG_BAD; } strcpy((unsigned char *)val_ptr, line); break; } return CONFIG_CHANGED;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?