flash.c

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

C
1,912
字号
        unsigned long erase_size;        CYG_ADDRESS erase_start;        // Erase everything except default RedBoot images, fis block,         // and config block.        // First deal with the possible first part, before RedBoot images:#if (CYGBLD_REDBOOT_FLASH_BOOT_OFFSET > CYGNUM_REDBOOT_FLASH_RESERVED_BASE)        erase_start = (CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE;        erase_size =  (CYG_ADDRESS)flash_start + CYGBLD_REDBOOT_FLASH_BOOT_OFFSET;        if ( erase_size > erase_start ) {            erase_size -= erase_start;            if ((stat = flash_erase((void *)erase_start, erase_size,                                    (void **)&err_addr)) != 0) {                diag_printf("   initialization failed at %p: %s\n",                            err_addr, flash_errmsg(stat));            }        }#endif        // second deal with the larger part in the main:        erase_start = redboot_flash_start; // high water of created images        // Now the empty bits between the end of Redboot and the cfg and dir         // blocks. #if defined(CYGSEM_REDBOOT_FLASH_CONFIG) && !defined(CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG)        if (fis_addr > cfg_base) {          erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between HWM and config data        } else {          erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data        }        if ((stat = flash_erase((void *)erase_start, erase_size,                                (void **)&err_addr)) != 0) {          diag_printf("   initialization failed %p: %s\n",                 err_addr, flash_errmsg(stat));        }        erase_start += (erase_size + flash_block_size);        if (fis_addr > cfg_base) {          erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between config and fis data        } else {          erase_size = (CYG_ADDRESS)cfg_base - erase_start; // the gap between fis and config data        }        if ((stat = flash_erase((void *)erase_start, erase_size,                                (void **)&err_addr)) != 0) {          diag_printf("   initialization failed %p: %s\n",                 err_addr, flash_errmsg(stat));        }        erase_start += (erase_size + flash_block_size);#else  // !CYGSEM_REDBOOT_FLASH_CONFIG                erase_size = (CYG_ADDRESS)fis_addr - erase_start; // the gap between HWM and fis data        if ((stat = flash_erase((void *)erase_start, erase_size,                                (void **)&err_addr)) != 0) {          diag_printf("   initialization failed %p: %s\n",                 err_addr, flash_errmsg(stat));        }        erase_start += (erase_size + flash_block_size);          #endif        // Lastly, anything at the end        erase_size = ((CYG_ADDRESS)flash_end - erase_start) + 1;        if ((stat = flash_erase((void *)erase_start, erase_size,                                (void **)&err_addr)) != 0) {            diag_printf("   initialization failed at %p: %s\n",                        err_addr, flash_errmsg(stat));        }    } else {        diag_printf("    Warning: device contents not erased, some blocks may not be usable\n");    }    fis_update_directory();}static voidfis_list(int argc, char *argv[]){    struct fis_image_desc *img;    int i;    bool show_cksums = false;    bool show_datalen = false;    struct option_info opts[2];#ifdef CYGHWR_REDBOOT_ARM_FLASH_SIB    // FIXME: this is somewhat half-baked    extern void arm_fis_list(void);    arm_fis_list();    return;#endif    init_opts(&opts[0], 'd', false, OPTION_ARG_TYPE_FLG,               (void **)&show_datalen, (bool *)0, "display data length");#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK    init_opts(&opts[1], 'c', false, OPTION_ARG_TYPE_FLG,               (void **)&show_cksums, (bool *)0, "display checksums");    i = 2;#else    i = 1;#endif    if (!scan_opts(argc, argv, 2, opts, i, 0, 0, ""))    {        return;    }    img = (struct fis_image_desc *) fis_addr;    // Let diag_printf do the formatting in both cases, rather than counting    // cols by hand....    diag_printf("%-16s  %-10s  %-10s  %-10s  %-s\n",                "Name","FLASH addr",                show_cksums ? "Checksum" : "Mem addr",                show_datalen ? "Datalen" : "Length",                "Entry point" );    for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {        if (img->name[0] != (unsigned char)0xFF) {            diag_printf("%-16s  0x%08lX  0x%08lX  0x%08lX  0x%08lX\n", img->name,                         img->flash_base, #ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK                        show_cksums ? img->file_cksum : img->mem_base,                         show_datalen ? img->data_length : img->size, #else                        img->mem_base,                         img->size, #endif                        img->entry_point);        }    }}static voidfis_free(int argc, char *argv[]){    unsigned long *fis_ptr, *fis_end;    unsigned long *area_start;    // Do not search the area reserved for pre-RedBoot systems:    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;    area_start = fis_ptr;    while (fis_ptr < fis_end) {        if (*fis_ptr != (unsigned long)0xFFFFFFFF) {            if (area_start != fis_ptr) {                // Assume that this is something                diag_printf("  0x%08lX .. 0x%08lX\n",                            (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);            }            // Find next blank block            area_start = fis_ptr;            while (area_start < fis_end) {                if (*area_start == (unsigned long)0xFFFFFFFF) {                    break;                }                area_start += flash_block_size / sizeof(CYG_ADDRESS);            }            fis_ptr = area_start;        } else {            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);        }    }    if (area_start != fis_ptr) {        diag_printf("  0x%08lX .. 0x%08lX\n",                     (CYG_ADDRESS)area_start, (CYG_ADDRESS)fis_ptr);    }}// Find the first unused area of flash which is long enoughstatic boolfis_find_free(CYG_ADDRESS *addr, unsigned long length){    unsigned long *fis_ptr, *fis_end;    unsigned long *area_start;    // Do not search the area reserved for pre-RedBoot systems:    fis_ptr = (unsigned long *)((CYG_ADDRESS)flash_start + CYGNUM_REDBOOT_FLASH_RESERVED_BASE);    fis_end = (unsigned long *)(CYG_ADDRESS)flash_end;    area_start = fis_ptr;    while (fis_ptr < fis_end) {        if (*fis_ptr != (unsigned long)0xFFFFFFFF) {            if (area_start != fis_ptr) {                // Assume that this is something                if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {                    *addr = (CYG_ADDRESS)area_start;                    return true;                }            }            // Find next blank block            area_start = fis_ptr;            while (area_start < fis_end) {                if (*area_start == (unsigned long)0xFFFFFFFF) {                    break;                }                area_start += flash_block_size / sizeof(CYG_ADDRESS);            }            fis_ptr = area_start;        } else {            fis_ptr += flash_block_size / sizeof(CYG_ADDRESS);        }    }    if (area_start != fis_ptr) {        if ((fis_ptr-area_start) >= (length/sizeof(unsigned))) {            *addr = (CYG_ADDRESS)area_start;            return true;        }    }    return false;}static voidfis_create(int argc, char *argv[]){    int i, stat;    unsigned long length, img_size;    CYG_ADDRESS mem_addr, exec_addr, flash_addr, entry_addr;    char *name;    bool mem_addr_set = false;    bool exec_addr_set = false;    bool entry_addr_set = false;    bool flash_addr_set = false;    bool length_set = false;    bool img_size_set = false;    bool no_copy = false;    void *err_addr;    struct fis_image_desc *img = NULL;    bool defaults_assumed;    struct option_info opts[7];    bool prog_ok = true;    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,               (void **)&mem_addr, (bool *)&mem_addr_set, "memory base address");    init_opts(&opts[1], 'r', true, OPTION_ARG_TYPE_NUM,               (void **)&exec_addr, (bool *)&exec_addr_set, "ram base address");    init_opts(&opts[2], 'e', true, OPTION_ARG_TYPE_NUM,               (void **)&entry_addr, (bool *)&entry_addr_set, "entry point address");    init_opts(&opts[3], 'f', true, OPTION_ARG_TYPE_NUM,               (void **)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");    init_opts(&opts[4], 'l', true, OPTION_ARG_TYPE_NUM,               (void **)&length, (bool *)&length_set, "image length [in FLASH]");    init_opts(&opts[5], 's', true, OPTION_ARG_TYPE_NUM,               (void **)&img_size, (bool *)&img_size_set, "image size [actual data]");    init_opts(&opts[6], 'n', false, OPTION_ARG_TYPE_FLG,               (void **)&no_copy, (bool *)0, "don't copy from RAM to FLASH, just update directory");    if (!scan_opts(argc, argv, 2, opts, 7, (void *)&name, OPTION_ARG_TYPE_STR, "file name"))    {        fis_usage("invalid arguments");        return;    }    memcpy(fis_work_block, fis_addr, fisdir_size);    defaults_assumed = false;    if (name) {        // Search existing files to acquire defaults for params not specified:        img = fis_lookup(name, NULL);        if (img) {            // Found it, so get image size from there            if (!length_set) {                length_set = true;                length = img->size;                defaults_assumed = true;            }        }    }    if (!mem_addr_set && (load_address >= (CYG_ADDRESS)ram_start) &&	(load_address_end) < (CYG_ADDRESS)ram_end) {	mem_addr = load_address;	mem_addr_set = true;        defaults_assumed = true;        // Get entry address from loader, unless overridden        if (!entry_addr_set)            entry_addr = entry_address;	if (!length_set) {	    length = load_address_end - load_address;	    length_set = true;	} else if (defaults_assumed && !img_size_set) {	    /* We got length from the FIS table, so the size of the	       actual loaded image becomes img_size */	    img_size = load_address_end - load_address;	    img_size_set = true;	}    }    // Get the remaining fall-back values from the fis    if (img) {        if (!exec_addr_set) {            // Preserve "normal" behaviour            exec_addr_set = true;            exec_addr = flash_addr_set ? flash_addr : mem_addr;        }        if (!flash_addr_set) {            flash_addr_set = true;            flash_addr = img->flash_base;            defaults_assumed = true;        }    }    if ((!no_copy && !mem_addr_set) || (no_copy && !flash_addr_set) ||        !length_set || !name) {        fis_usage("required parameter missing");        return;    }    if (!img_size_set) {        img_size = length;    }    // 'length' is size of FLASH image, 'img_size' is actual data size    // 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;    if (length < img_size) {        diag_printf("Invalid FLASH image size/length combination\n");        return;    }#endif    if (flash_addr_set &&        ((stat = flash_verify_addr((void *)flash_addr)) ||         (stat = flash_verify_addr((void *)(flash_addr+img_size-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 (strlen(name) >= sizeof(img->name)) {        diag_printf("Name is too long, must be less than %d chars\n", (int)sizeof(img->name));        return;    }    if (!no_copy) {        if ((mem_addr < (CYG_ADDRESS)ram_start) ||            ((mem_addr+img_size) >= (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);        }        if (!flash_addr_set && !fis_find_free(&flash_addr, length)) {            diag_printf("Can't locate %lx(%ld) bytes free in FLASH\n", length, length);            return;        }    }    // First, see if the image by this name has agreable properties    if (img) {        if (flash_addr_set && (img->flash_base != flash_addr)) {            diag_printf("Image found, but flash address (%p)\n"                        "             is incorrect (present image location %p)\n",                        flash_addr, img->flash_base);                        return;        }        if (img->size != length) {            diag_printf("Image found, but length (0x%lx, necessitating image size 0x%lx)\n"                        "             is incorrect (present image size 0x%lx)\n",                        img_size, length, img->size);            return;        }        if (!verify_action("An image named '%s' exists", name)) {            return;        } else {                            if (defaults_assumed) {                if (no_copy &&                    !verify_action("* CAUTION * about to program '%s'\n            at %p..%p from %p",                                    name, (void *)flash_addr, (void *)(flash_addr+img_size-1),                                   (void *)mem_addr)) {                    return;  // The guy gave up                }            }        }    } else {        // If not image by that name, try and find an empty slot        img = (struct fis_image_desc *)fis_work_block;        for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {            if (img->name[0] == (unsigned char)0xFF) {                break;            }        }    }    if (!no_copy) {        // 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+img_size-1))) {            diag_printf("Can't program this region - contains code in use!\n");            return;        }        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, img_size, (void **)&err_addr)) != 0) {                diag_printf("Can't program region at %p: %s\n", err_addr, flash_errmsg(stat));                prog_ok = false;            }        }

⌨️ 快捷键说明

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