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 + -
显示快捷键?