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

📄 flash_intel.c

📁 Hermit-at-1.1.3,一款bootloader
💻 C
字号:
/* * Copyright (c) 2001 Atmark Techno, Inc.  All Rights Reserved. */#include <target/buffer.h>#include <target/io.h>#include <target/herrno.h>#include <target/scan.h>#include <target/flash.h>#include <target/str.h>#include "../flash_memcpy.h"#define FLASH_TIMEOUT 0x40000000/* Device Command */#define CMD_READ		(0xFF)#define CMD_READ_ID		(0x90)#define CMD_CFI			(0x98)#define CMD_READ_STATUS		(0x70)#define CMD_CLEAR_STATUS	(0x50)#define CMD_WORD_PROGRAM	(0x40)#define CMD_BUFFER_PROGRAM	(0xe8)#define CMD_ERASE		(0x20)#define CMD_CONFIRM		(0xD0)#define CMD_LOCK_SETUP		(0x60)#define CMD_LOCKED		(0x01)#define CMD_UNLOCKED		(0xD0)#define CMD_LOCKDOWN		(0x2F)/* Status Description */#define SR_BWS  (1<<0) /* BEFP Status */#define SR_BLS  (1<<1) /* Block Locked Status */#define SR_PSS  (1<<2) /* Program Suspend Status */#define SR_VPPS (1<<3) /* VPP Status */#define SR_PS   (1<<4) /* Program Status */#define SR_ES   (1<<5) /* Erase Status */#define SR_ESS  (1<<6) /* Erase Suspend Status */#define SR_DWS  (1<<7) /* Device Write Status */#define INTEL_BUFFER_PROGRAM_ALIGNED_MASK (0x1f)#if defined(FLASH_INTEL_DEBUG)#define DEBUG_FUNC() hprintf("%s\n", __FUNCTION__)#else#define DEBUG_FUNC()#endif#define flash_read8(addr)        read8((addr))#if defined(BIG_ENDIAN)#define flash_read(addr)         cpu_to_le16(read16((addr)))#define flash_write(addr, b)     write16((addr), cpu_to_le16((b)))#else /* LITTLE_ENDIAN */#define flash_read(addr)         read16((addr))#define flash_write(addr, b)     write16((addr), (b))#endifstatic int (*flash_intel_program_func)(u32, u32, u32);static flash_cfi cfi_info;/* * Loop until both write state machines complete. */static unsigned short flash_status_wait(addr_t addr){	unsigned short status;	long timeout = FLASH_TIMEOUT;	DEBUG_FUNC();	do {		status = flash_read(addr);	} while ((!(status & SR_DWS)) &&  timeout-- > 0);	if (status & ~SR_DWS) {		hprintf("error status: %x\n", status);		flash_write((addr & FLASH_BASE_MASK), CMD_CLEAR_STATUS);		return -H_EIO;	}	return 0;}/* * Loop until the Write State machine is ready, then do a full error * check.  Clear status and leave the flash in Read Array mode; return * 0 for no error, -1 for error. */static int flash_status_full_check(addr_t addr){	unsigned short status;	DEBUG_FUNC();	flash_write((addr & FLASH_BASE_MASK), CMD_READ_STATUS);	status = flash_read(addr);	flash_write((addr & FLASH_BASE_MASK), CMD_READ);	if (!(status & ~SR_DWS))		return 0;	flash_write((addr & FLASH_BASE_MASK), CMD_CLEAR_STATUS);	if (status & SR_VPPS)		hprintf("Flash Error: Vpp Range.\n");	if (status & SR_PS)		hprintf("Flash Error: Data Program.\n");	if (status & SR_ES)		hprintf("Flash Error: Block Erase.\n");	if (status & SR_BLS)		hprintf("Flash Error: Block Protect.\n");		return -H_EADDR;}static intflash_intel_block_unlock(const u32 block_addr){	unsigned long addr;	DEBUG_FUNC();	addr = (block_addr & ~UNALIGNED_MASK);	flash_write(addr, CMD_LOCK_SETUP);	flash_write(addr, CMD_UNLOCKED);	flash_write((addr & FLASH_BASE_MASK), CMD_READ);	return 0;}static int flash_intel_word_program(const u32 from, const u32 to, const u32 size){	int ret;	unsigned int loop;	unsigned short *ptr;	unsigned long addr;	DEBUG_FUNC();	if (from & UNALIGNED_MASK)		return -H_EALIGN;	if (to & UNALIGNED_MASK) 		return -H_EALIGN;		loop = (size >> BYTE_TO_WORD_SHIFT);	ptr = (unsigned short*)from;	addr = to;	flash_intel_block_unlock(addr);	for (; loop--; addr += (sizeof(short) * 2)) {		flash_write(addr, CMD_WORD_PROGRAM);		flash_write(addr, *ptr);		flash_status_wait(addr);		flash_write(addr + 2, CMD_WORD_PROGRAM);		flash_write(addr + 2, *(ptr + 1));		flash_status_wait(addr);		ret = flash_status_full_check(addr);		if (ret)		  return ret;		ptr += 2;	}	return 0;}static int flash_intel_buffer_program(const u32 from, const u32 to, const u32 size){	u16 *addr;	u16 *data;	u32 remain;	u32 max_program_size;	u32 program_size;	int i;	int ret;	if (from & UNALIGNED_MASK)		return -H_EALIGN;	if (to & INTEL_BUFFER_PROGRAM_ALIGNED_MASK)		return -H_EALIGN;	addr = (u16 *)to;	data = (u16 *)from;	remain = (size + 1) / 2;	if (cfi_info.max_buf_write_size < 2)		return -H_ENOCMD;	max_program_size = (1 << (cfi_info.max_buf_write_size - 1));	while (remain) {		u32 start = (u32)addr;		flash_intel_block_unlock(start);		flash_write(start, CMD_BUFFER_PROGRAM);		flash_status_wait(start);  		if (remain >= max_program_size)			program_size = max_program_size;		else			program_size = remain;		flash_write(start, program_size - 1);    		for (i=0; i<program_size; i++)			flash_write(addr++, *(data++));		flash_write(start, CMD_CONFIRM);		flash_status_wait(start);    		ret = flash_status_full_check(start);		if (ret)			return ret;    		remain -= program_size;	}  	return 0;}/* * Program the contents of the download buffer to flash at the given * address.  Size is also specified; we shouldn't have to track usage * of the download buffer, since the host side can easily do that. * * We write words without checking status between each; we only go * through the full status check procedure once, when the full buffer * has been written. * * Alignment problems are errors here; we don't automatically correct * them because in the context of this command they signify bugs, and * we want to be extra careful when writing flash. */int flash_intel_program(const u32 from, const u32 to, const u32 size){	if (to & INTEL_BUFFER_PROGRAM_ALIGNED_MASK)		return flash_intel_word_program(from, to, size);	else		return flash_intel_program_func(from, to, size);}/* * Erase a flash block.  Single argument is the first address in the * block (actually, it can be anywhere in the block, but the host-side * hermit downloader gives the first address). */int flash_intel_erase(const u32 erase_addr){	unsigned long addr;	DEBUG_FUNC();	addr = (erase_addr & ~UNALIGNED_MASK);	/* word align */		flash_intel_block_unlock(addr);	flash_write(addr, CMD_ERASE);	flash_write(addr, CMD_CONFIRM);	flash_status_wait(addr);	return flash_status_full_check(addr);}inline u8 flash_intel_read_byte(const u32 from){	return flash_read8(from);}u32 flash_intel_copy_to_dram(const u32 from, const u32 to, const u32 size){	flash_memcpy((u16 *)to, (u16 *)from,(u16 *)(to + size));	return size;}u32 flash_intel_get_id(const u32 base_addr){	u32 base;	u32 id;	base = (base_addr & FLASH_BASE_MASK);	flash_write(base, CMD_READ_ID);	id = (flash_read(base) << 16) | flash_read(base + 2);	flash_write(base, CMD_READ);	return id;}int flash_intel_get_size(const u32 base_addr){	return cfi_info.dev_size;}static intflash_intel_read_cfi(const u32 base_addr){	int i;	u32 base;	u8 *buf = (u8 *)&cfi_info;	base = (base_addr & FLASH_BASE_MASK);	flash_write(base, CMD_READ);        flash_write(base, CMD_CFI);	for (i=0; i<0x1c; i++)		*(buf++) = flash_read(base + ((0x10 + i) << 1)) & 0xff;	flash_write(base, CMD_READ);	if (strncmp(cfi_info.qry, "QRY", 3))		return -1;        return 0;}int flash_intel_initialize(const u32 base_addr){	int ret;	ret = flash_intel_read_cfi(base_addr);	if (cfi_info.buf_write_timeout_typ)		flash_intel_program_func = flash_intel_buffer_program;	else		flash_intel_program_func = flash_intel_word_program;	return ret;}intflash_intel_create_eraseblock_table(const u32 base_addr, flash_eb *eb){	int i, addr = 0x2c;	u32 base;	base = (base_addr & FLASH_BASE_MASK);	flash_write(base, CMD_READ);        flash_write(base, CMD_CFI);	eb->nr_eraseblock = flash_read(base + ((addr++) << 1)) & 0xff;	if (eb->nr_eraseblock > MAX_NR_ERASEBLOCK) {		flash_write(base, CMD_READ);		return -1;	}	for (i=0; i<eb->nr_eraseblock; i++) {		eb->eraseblock[i].num = 			(flash_read(base + ((addr++) << 1)) & 0xff);		eb->eraseblock[i].num |=			(flash_read(base + ((addr++) << 1)) & 0xff) << 8;		eb->eraseblock[i].size =			(flash_read(base + ((addr++) << 1)) & 0xff);		eb->eraseblock[i].size |=			(flash_read(base + ((addr++) << 1)) & 0xff) << 8;	}	flash_write(base, CMD_READ);	eb->base_addr = base_addr;#if defined(FLASH_INTEL_DEBUG)	for (i=0; i<eb->nr_eraseblock; i++) {		hprintf("eraseblock[%d]: %d x %d\n", i,			eb->eraseblock[i].num + 1, 			eb->eraseblock[i].size * 256);	}#endif        return 0;}

⌨️ 快捷键说明

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