⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 flash.c

📁 pxa270 的bootloader源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	/* erase */	report(" erase flash [0x%08lx ~ 0x%08lx]\n", addr, addr+size-1);	if (size) do {		bool res;		report("\r erase at 0x%08lx", addr);		res =  iflash_erase_block((void *)addr);		if (!res){ failed("\n error : failed to erase block. check lock.\n"); return false; }		addr += flash->blksize;		size -= flash->blksize;	} while (size > 0);	report("\r erase at 0x%08lx : done\n", addr);	return true;invalid :	erase_usage();	return false;}static void erase_usage(void){	usage_format("erase {loader/kernel/root/ramdisk}", "erase flash blocks of area");	//usage_format("erase addr [size]", "erase one flash block");	return;}static bool do_lock(int argc, char **argv){	bool res;	ulong addr, size, tmp;	if (argc == 2){		struct map *mp;		if (!strcmp(argv[1], "all")){				/* lock all */			addr = flash->base;			size = flash->size;		} else if ((mp = find_map(argv[1]))){		/* lock {loader/kernel/ramdisk/root} */			addr = mp->sramb;			size = mp->maxs;		} else if (strtoul(argv[1], &tmp, 16)){		/* lock address */			addr = tmp;			size = flash->blksize;		} else goto invalid;	} else if (argc == 3){		res = strtoul(argv[1], &tmp, 16);		if (!res) goto invalid;		addr = tmp;		res = strtoul(argv[2], &tmp, 16);		if (!res) goto invalid;		size = tmp;	} else goto invalid;	/* check address and size */	if (addr % flash->blksize){		failed(" error : address is not base of flash block.(blksize=%lx)\n", flash->blksize);		return false;	}	if (size % flash->blksize){		failed(" error : size is not multifly of block size.(blksize=%lx)\n", flash->blksize);		return false;	}	/* lock */	report(" lock flash [0x%08lx ~ 0x%08lx]\n", addr, addr+size-1);	if (size) do {		bool res;		res =  iflash_lock_block((void *)addr);		if (!res){ failed(" error : lock block.[0x%08lx]\n", addr); return false; }		addr += flash->blksize;		size -= flash->blksize;	} while (size);	return true;invalid :	lock_usage();	return false;}static void lock_usage(void){	usage_format("lock {all/loader/kernel/root/ramdisk}", "set flash lock-bit of area");	usage_format("lock addr [size]", "set flash lock-bit of one block");	return;}static bool do_unlock(int argc, char **argv){	bool res;	ulong addr, size, tmp;	if (argc == 2){		struct map *mp;		if (!strcmp(argv[1], "all")){				/* unlock all */			addr = flash->base;			size = flash->size;		} else if ((mp = find_map(argv[1]))){		/* unlock {loader/kernel/ramdisk/root} */			addr = mp->sramb;			size = mp->maxs;		} else if (strtoul(argv[1], &tmp, 16)){		/* unlock address */			addr = tmp;			size = flash->blksize;		} else goto invalid;	} else if (argc == 3){		res = strtoul(argv[1], &tmp, 16);		if (!res) goto invalid;		addr = tmp;		res = strtoul(argv[2], &tmp, 16);		if (!res) goto invalid;		size = tmp;	} else goto invalid;	/* check address and size */	if (addr % flash->blksize){		failed(" error : address is not base of flash block.(blksize=%lx)\n", flash->blksize);		return false;	}	if (size % flash->blksize){		failed(" error : size is not multifly of block size.(blksize=%lx)\n", flash->blksize);		return false;	}	/* unlock */	report(" unlock flash [0x%08lx ~ 0x%08lx]\n", addr, addr+size-1);	if (size) do {		bool res;		res = iflash_unlock_block((void *)addr);		if (!res){ failed(" error : unlock block.[0x%08lx]\n", addr); return false; }		addr += flash->blksize;		size -= flash->blksize;	} while (size);	return true;invalid :	unlock_usage();	return false;}static void unlock_usage(void){	usage_format("unlock addr [size]", "clear lock-bit of one block");	return;}extern bool flash_write(void *dest, const void *src, uint cnt){	bool res;	uchar buff_base[flash->blksize];	ulong buff_offset;	ulong write_cnt;	void *block_base;	const void *copyfrom;	res = true;	while (cnt > 0){		block_base = (void *)((ulong)dest & ~(flash->blksize-1));			/* block base in flash */		buff_offset = (ulong)dest & (flash->blksize-1);						/* offset */		write_cnt = (buff_offset + cnt <= flash->blksize ? cnt : flash->blksize - buff_offset);		if (!buff_offset && write_cnt == flash->blksize){			copyfrom = src;		} else {			memcpy(buff_base, block_base, flash->blksize);					/* backup to buff_base */			memcpy(buff_base+buff_offset, src, write_cnt);					/* overwrite will be changed */			copyfrom = buff_base;		}		res = iflash_erase_block(block_base);								/* erase block */		if (!res) break;		res = iflash_write_block(block_base, copyfrom);						/* write to flash block */		if (!res) break;		res = blkcmp(block_base, copyfrom, flash->blksize) ? false : true;		if (!res) break; 		dest += write_cnt;													/* for next */		src += write_cnt;		cnt -= write_cnt;	}	return res;}static inline void write_data(void *dest, const void *src, int count){	if (flash->buswidth == 1){		uint8 *d=dest;		const uint8 *s=src;		while (count--) *d++ = *s++;	} else if (flash->buswidth == 2){		uint16 *d=dest;		const uint16 *s=src;		while (count--) *d++ = *s++;	} else if (flash->buswidth == 4){		uint32 *d=dest;		const uint32 *s=src;		while (count--) *d++ = *s++;	}	return;}static bool iflash_write_block(void *dest, const void *src){	bool res;	int i, count;	/* unlock block */	res = iflash_unlock_block(dest);	if (!res) return false;	/* write block */	count = flash->buff_size / flash->buswidth;	for (i=0; i < flash->blksize/flash->buff_size; i++){		iflash_write_cmd(dest, flash->buswidth, WRITE_BUF);		wait_while_busy(dest);		iflash_write_cmd(dest, flash->buswidth, count - 1);		write_data(dest, src, count);		iflash_write_cmd(dest, flash->buswidth, WRITE_BUF_COMFIRM);		res = iflash_status_check(dest, ACT_WRITE_BUF);		if (!res) return false;		dest = (uchar *)dest + flash->buff_size;		src  = (uchar *)src  + flash->buff_size;	}	return true;}static inline bool check_erased(void *addr){	int count;	uint32 *p = addr;	count = flash->blksize / sizeof(uint32) / 4;	do {		if (*p++ != 0xFFFFFFFF) return false;		if (*p++ != 0xFFFFFFFF) return false;		if (*p++ != 0xFFFFFFFF) return false;		if (*p++ != 0xFFFFFFFF) return false;	} while (--count);	return true;}static bool iflash_erase_block(void *addr){	bool res;	if ((ulong)addr & (flash->blksize-1))		return false;	/* unlock block */	res = iflash_unlock_block(addr);	if (!res) return false;	res = check_erased(addr);	if (res) return true;	/* erase block */	iflash_write_cmd(addr, flash->buswidth, ERASE_SETUP);	iflash_write_cmd(addr, flash->buswidth, ERASE_CONFIRM);	return iflash_status_check(addr, ACT_ERASE);}static bool iflash_lock_block(void *addr){	if ((ulong)addr % flash->blksize) return false;	iflash_write_cmd(addr, flash->buswidth, FLASH_SETUP);	iflash_write_cmd(addr, flash->buswidth, BLOCK_LOCK_BIT_SET);	return iflash_status_check(addr, ACT_LOCK);}static bool iflash_unlock_block(void *addr){	iflash_write_cmd(addr, flash->buswidth, FLASH_SETUP);	iflash_write_cmd(addr, flash->buswidth, BLOCK_LOCK_BIT_CLEAR);	return iflash_status_check(addr, ACT_UNLOCK);}static void iflash_write_cmd(void *addr, int buswidth, int c){	if (buswidth == 1)		*(uint8 *)addr = (uint8)c;	else if (buswidth == 2)		*(uint16 *)addr = (uint16)c;	else if (buswidth == 4)		*(uint32 *)addr = (uint32)c | ((uint32)c << 16);	return;}static bool iflash_status_check(void *addr, enum action which){	uint32 status=0, busy;	iflash_write_cmd(addr, flash->buswidth, STATUS_READ);	if (flash->buswidth == 2){		busy = (uint16)STATUS_BUSY;		while (1){			status = readw(addr);			if ((status & busy) == busy) break;		}	} else if (flash->buswidth == 4){		busy = (uint32)STATUS_BUSY;		while (1){			status = readl(addr);			if ((status & busy) == busy) break;		}	} else return false;	status &= ~STATUS_BUSY;	if (status) iflash_write_cmd(addr, flash->buswidth, STATUS_CLEAR);	iflash_write_cmd(addr, flash->buswidth, READ_ARRAY);	return status ? false : true;}static void wait_while_busy(void *addr){	uint32 busy;	if (flash->buswidth == 2){		busy = (uint16)STATUS_BUSY;		while ((readw(addr) & busy) != busy);	} else if (flash->buswidth == 4){		busy = (uint32)STATUS_BUSY;		while ((readl(addr) & busy) != busy);	}	return;}

⌨️ 快捷键说明

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