flash.c

来自「ecos实时嵌入式操作系统」· C语言 代码 · 共 1,912 行 · 第 1/5 页

C
1,912
字号
//// Manage configuration information with the FLASH//static intconfig_length(int type){    switch (type) {    case CONFIG_BOOL:        return sizeof(bool);    case CONFIG_INT:        return sizeof(unsigned long);#ifdef CYGPKG_REDBOOT_NETWORKING    case CONFIG_IP:        return sizeof(in_addr_t);    case CONFIG_ESA:        // Would like this to be sizeof(enet_addr_t), but that causes much        // pain since it fouls the alignment of data which follows.        return 8;#endif    case CONFIG_STRING:        return MAX_STRING_LENGTH;    case CONFIG_SCRIPT:        return MAX_SCRIPT_LENGTH;    default:        return 0;    }}static cmd_fun do_flash_config;RedBoot_cmd("fconfig",            "Manage configuration kept in FLASH memory",            "[-i] [-l] [-n] [-f] [-d] | [-d] nickname [value]",            do_flash_config    );static voiddo_flash_config(int argc, char *argv[]){    bool need_update = false;    struct config_option *optend = __CONFIG_options_TAB_END__;    struct config_option *opt = __CONFIG_options_TAB__;    struct option_info opts[5];    bool list_only;    bool nicknames;    bool fullnames;    bool dumbterminal;    int list_opt = 0;    unsigned char *dp;    int len, ret;    char *title;    char *onlyone = NULL;    char *onevalue = NULL;    bool doneone = false;    bool init = false;    if (!__flash_init) {        diag_printf("Sorry, no FLASH memory is available\n");        return;    }    memcpy(backup_config, config, sizeof(struct _config));    script = (unsigned char *)0;    init_opts(&opts[0], 'l', false, OPTION_ARG_TYPE_FLG,               (void **)&list_only, (bool *)0, "list configuration only");    init_opts(&opts[1], 'n', false, OPTION_ARG_TYPE_FLG,               (void **)&nicknames, (bool *)0, "show nicknames");    init_opts(&opts[2], 'f', false, OPTION_ARG_TYPE_FLG,               (void **)&fullnames, (bool *)0, "show full names");    init_opts(&opts[3], 'i', false, OPTION_ARG_TYPE_FLG,               (void **)&init, (bool *)0, "initialize configuration database");    init_opts(&opts[4], 'd', false, OPTION_ARG_TYPE_FLG,               (void **)&dumbterminal, (bool *)0, "dumb terminal: no clever edits");    // First look to see if we are setting or getting a single option    // by just quoting its nickname    if ( (2 == argc && '-' != argv[1][0]) ||         (3 == argc && '-' != argv[1][0] && '-' != argv[2][0])) {        // then the command was "fconfig foo [value]"        onlyone = argv[1];        onevalue = (3 == argc) ? argv[2] : NULL;        list_opt = LIST_OPT_NICKNAMES;    }    // Next see if we are setting or getting a single option with a dumb    // terminal invoked, ie. no line editing.    else if (3 == argc &&             '-' == argv[1][0] && 'd' == argv[1][1] && 0 == argv[1][2] &&              '-' != argv[2][0]) {        // then the command was "fconfig -d foo"        onlyone = argv[2];        onevalue = NULL;        list_opt = LIST_OPT_NICKNAMES | LIST_OPT_DUMBTERM;    }    else {        if (!scan_opts(argc, argv, 1, opts, 5, 0, 0, ""))            return;        list_opt |= list_only ? LIST_OPT_LIST_ONLY : 0;        list_opt |= nicknames ? LIST_OPT_NICKNAMES : LIST_OPT_FULLNAMES;        list_opt |= fullnames ? LIST_OPT_FULLNAMES : 0;        list_opt |= dumbterminal ? LIST_OPT_DUMBTERM : 0;    }    if (init && verify_action("Initialize non-volatile configuration")) {        config_init();        need_update = true;    }    dp = &config->config_data[0];    while (dp < &config->config_data[sizeof(config->config_data)]) {        if (CONFIG_OBJECT_TYPE(dp) == CONFIG_EMPTY) {            break;        }        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +             config_length(CONFIG_OBJECT_TYPE(dp));        // Provide a title for well known [i.e. builtin] objects        title = (char *)NULL;        opt = __CONFIG_options_TAB__;        while (opt != optend) {            if (strcmp(opt->key, CONFIG_OBJECT_KEY(dp)) == 0) {                title = opt->title;                break;            }            opt++;        }        if ( onlyone && 0 != strcmp(CONFIG_OBJECT_KEY(dp), onlyone) )            ret = CONFIG_OK; // skip this entry        else {            doneone = true;            ret = get_config(dp, title, list_opt, onevalue); // do this opt        }        switch (ret) {        case CONFIG_DONE:            goto done;        case CONFIG_ABORT:            memcpy(config, backup_config, sizeof(struct _config));            return;        case CONFIG_CHANGED:            need_update = true;        case CONFIG_OK:            dp += len;            break;        case CONFIG_BACK:            dp = &config->config_data[0];            continue;        case CONFIG_BAD:            // Nothing - make him do it again            diag_printf ("** invalid entry\n");            onevalue = NULL; // request a good value be typed in - or abort/whatever        }    } done:    if (NULL != onlyone && !doneone) {#ifdef CYGSEM_REDBOOT_ALLOW_DYNAMIC_FLASH_CONFIG_DATA        if (verify_action("** entry '%s' not found - add", onlyone)) {            struct config_option opt;            diag_printf("Trying to add value\n");        }#else        diag_printf("** entry '%s' not found", onlyone);#endif    }    if (!need_update)        return;    flash_write_config();}#ifdef CYGSEM_REDBOOT_FLASH_ALIASESstatic cmd_fun do_alias;RedBoot_cmd("alias",            "Manage aliases kept in FLASH memory",            "name [value]",            do_alias    );static voidmake_alias(char *alias, char *name){    diag_sprintf(alias, "alias/%s", name);}static voiddo_alias(int argc, char *argv[]){    char name[80];    char *val;    struct config_option opt;    switch (argc) {    case 2:        make_alias(name, argv[1]);        if (flash_get_config(name, &val, CONFIG_STRING)) {            diag_printf("'%s' = '%s'\n", argv[1], val);        } else {            diag_printf("'%s' not found\n", argv[1]);        }        break;    case 3:        if (strlen(argv[2]) >= MAX_STRING_LENGTH) {            diag_printf("Sorry, value is too long\n");            break;        }        make_alias(name, argv[1]);        opt.type = CONFIG_STRING;        opt.enable = (char *)0;        opt.enable_sense = 1;        opt.key = name;        opt.dflt = (CYG_ADDRESS)argv[2];        flash_add_config(&opt, true);        break;    default:        diag_printf("usage: alias name [value]\n");    }}// Lookup an alias. First try plain string aliases. If that fails try// other types so allowing access to all configured values. This allows// for alias (macro) expansion of normal 'fconfig' data, such as the// board IP address.char *flash_lookup_alias(char *alias, char *alias_buf){    char name[80];    char *val;    unsigned char * dp;    void *val_ptr;    int type;    bool hold_bool_val;    long hold_long_val;#ifdef CYGPKG_REDBOOT_NETWORKING    int esa_ptr;#endif    make_alias(name, alias);    if (flash_get_config(name, &val, CONFIG_STRING)) {        return val;    } else {        dp = flash_lookup_config(alias);        if (dp) {            val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);            switch (type = CONFIG_OBJECT_TYPE(dp)) {            case CONFIG_BOOL:                memcpy(&hold_bool_val, val_ptr, sizeof(bool));                diag_sprintf(alias_buf, "%s", hold_bool_val ? "true" : "false");                break;            case CONFIG_INT:                memcpy(&hold_long_val, val_ptr, sizeof(unsigned long));                diag_sprintf(alias_buf,"%ld", hold_long_val);                break;#ifdef CYGPKG_REDBOOT_NETWORKING            case CONFIG_IP:                diag_sprintf(alias_buf,"%s", inet_ntoa((in_addr_t *)val_ptr));                break;            case CONFIG_ESA:                for (esa_ptr = 0;  esa_ptr < sizeof(enet_addr_t);  esa_ptr++) {                    diag_sprintf(alias_buf+(3*esa_ptr), "0x%02X", ((unsigned char *)val_ptr)[esa_ptr]);                    if (esa_ptr < (sizeof(enet_addr_t)-1)) diag_printf(":");                }                break;#endif            case CONFIG_SCRIPT:                return (char *) val_ptr;                break;            default:                return (char *)NULL;            }            return alias_buf;        }         return (char *)NULL;    }}#endif //  CYGSEM_REDBOOT_FLASH_ALIASES//// Write the in-memory copy of the configuration data to the flash device.//voidflash_write_config(void){#ifndef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG    int stat;    void *err_addr;#endif    config->len = sizeof(struct _config);    config->key1 = CONFIG_KEY1;      config->key2 = CONFIG_KEY2;    config->cksum = cyg_crc32((unsigned char *)config, sizeof(struct _config)-sizeof(config->cksum));    if (verify_action("Update RedBoot non-volatile configuration")) {#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG        memcpy(fis_work_block, fis_addr, fisdir_size);        fis_update_directory();#else //  CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL        // Insure [quietly] that the config page is unlocked before trying to update        flash_unlock((void *)cfg_base, cfg_size, (void **)&err_addr);#endif        if ((stat = flash_erase(cfg_base, cfg_size, (void **)&err_addr)) != 0) {            diag_printf("   initialization failed at %p: %s\n", err_addr, flash_errmsg(stat));        } else {            if ((stat = flash_program(cfg_base, (void *)config, sizeof(struct _config),                                       (void **)&err_addr)) != 0) {                diag_printf("Error writing config data at %p: %s\n",                             err_addr, flash_errmsg(stat));            }        }#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL        // Insure [quietly] that the config data is locked after the update        flash_lock((void *)cfg_base, cfg_size, (void **)&err_addr);#endif#endif    }}//// Find the configuration entry for a particular key//static unsigned char *flash_lookup_config(char *key){    unsigned char *dp;    int len;    if (!config_ok) return (unsigned char *)NULL;    dp = &config->config_data[0];    while (dp < &config->config_data[sizeof(config->config_data)]) {        len = 4 + CONFIG_OBJECT_KEYLEN(dp) + CONFIG_OBJECT_ENABLE_KEYLEN(dp) +            config_length(CONFIG_OBJECT_TYPE(dp));        if (strcmp(key, CONFIG_OBJECT_KEY(dp)) == 0) {            return dp;        }        dp += len;    }//    diag_printf("Can't find config data for '%s'\n", key);    return false;}//// Retrieve a data object from the data base (in memory copy)//boolflash_get_config(char *key, void *val, int type){    unsigned char *dp;    void *val_ptr;#ifdef CYGSEM_REDBOOT_FLASH_CONFIG_READONLY_FALLBACK    struct _config *save_config = 0;#endif    if (!config_ok) return false;    if ((dp = flash_lookup_config(key)) != (unsigned char *)NULL) {        if (CONFIG_OBJECT_TYPE(dp) == type) {            val_ptr = (void *)CONFIG_OBJECT_VALUE(dp);            switch (type) {                // Note: the data may be unaligned in the configuration data            case CONFIG_BOOL:                memcpy(val, val_ptr, sizeof(bool));                break;            case CONFIG_INT:                memcpy(val, val_ptr, sizeof(unsigned long));                break;#ifdef CYGPKG_REDBOOT_NETWORKING            case CONFIG_IP:                memcpy(val, val_ptr, sizeof(in_addr_t));                break;            case CONFIG_ESA:                memcpy(val, val_ptr, sizeof(enet_addr_t));                break;#endif            case CONFIG_STRING:            case CONFIG_SCRIPT:                // Just return a pointer to the script/line                *(unsigned char **)val = (unsigned char *)val_ptr;                break;            }  

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?