flash.c

来自「eCos操作系统源码」· C语言 代码 · 共 1,397 行 · 第 1/4 页

C
1,397
字号
        // Set load address/top        load_address = mem_addr;        load_address_end = (unsigned long)p->out_buf;    	// Reload fis directory        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);    } else // dangling block#endif    {        flash_read((void *)img->flash_base, (void *)mem_addr, img->data_length, (void **)&err_addr);        // Set load address/top        load_address = mem_addr;        load_address_end = mem_addr + img->data_length;    }    entry_address = (unsigned long)img->entry_point;#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK    cksum = cyg_crc32((unsigned char *)mem_addr, img->data_length);    if (show_cksum) {        diag_printf("Checksum: 0x%08lx\n", cksum);    }    // When decompressing, leave CRC checking to decompressor    if (!decompress && img->file_cksum) {        if (cksum != img->file_cksum) {            diag_printf("** Warning - checksum failure.  stored: 0x%08lx, computed: 0x%08lx\n",                        img->file_cksum, cksum);            entry_address = NO_MEMORY;        }    }#endif}#endif // CYGOPT_REDBOOT_FISstatic voidfis_write(int argc, char *argv[]){    int stat;    unsigned long length;    CYG_ADDRESS mem_addr, flash_addr;    bool mem_addr_set = false;    bool flash_addr_set = false;    bool length_set = false;    void *err_addr;    struct option_info opts[3];    bool prog_ok;    init_opts(&opts[0], 'b', true, OPTION_ARG_TYPE_NUM,               (void *)&mem_addr, (bool *)&mem_addr_set, "memory base address");    init_opts(&opts[1], 'f', true, OPTION_ARG_TYPE_NUM,               (void *)&flash_addr, (bool *)&flash_addr_set, "FLASH memory base address");    init_opts(&opts[2], 'l', true, OPTION_ARG_TYPE_NUM,               (void *)&length, (bool *)&length_set, "image length [in FLASH]");    if (!scan_opts(argc, argv, 2, opts, 3, 0, 0, 0))    {        fis_usage("invalid arguments");        return;    }    if (!mem_addr_set || !flash_addr_set || !length_set) {        fis_usage("required parameter missing");        return;    }    // 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;#endif    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;    }    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 voidfis_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_LOCKINGstatic voidfis_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, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))    {        fis_usage("invalid arguments");        return;    }    /* 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 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 voidfis_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, (void **)&name, OPTION_ARG_TYPE_STR, "image name"))    {        fis_usage("invalid arguments");        return;    }    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  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 initializedint __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);}booldo_flash_init(void){    int stat;    void *err_addr;    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 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);#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 false;	}# 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 false;        }        flash_read(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);#endif    }    return true;}// Wrapper to avoid compiler warningsstatic 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 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");}// EOF flash.c

⌨️ 快捷键说明

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