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