nor flash函数分析

分析nor  flash代码来自韦东山的uboot1.1.6

在这里主要分析函数:

ulong flash_init (void);
void flash_print_info (flash_info_t * info);
int flash_erase (flash_info_t * info, int s_first, int s_last);
volatile static int write_hword (flash_info_t * info, ulong dest, ushort data);
int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)


一、ulong flash_init (void)

首先介绍一下nor flash的结构体变量:

typedef struct {
	ulong	size;			/* total bank size in bytes		*/
	ushort	sector_count;		/* number of erase units		*/
	ulong	flash_id;		/* combined device & manufacturer code	*/
	ulong	start[CFG_MAX_FLASH_SECT];   /* physical sector start addresses */
	uchar	protect[CFG_MAX_FLASH_SECT]; /* sector protection status	*/
#ifdef CFG_FLASH_CFI
	uchar	portwidth;		/* the width of the port		*/
	uchar	chipwidth;		/* the width of the chip		*/
	ushort	buffer_size;		/* # of bytes in write buffer		*/
	ulong	erase_blk_tout;		/* maximum block erase timeout		*/
	ulong	write_tout;		/* maximum write timeout		*/
	ulong	buffer_write_tout;	/* maximum buffer write timeout		*/
	ushort	vendor;			/* the primary vendor id		*/
	ushort	cmd_reset;		/* Vendor specific reset command	*/
	ushort	interface;		/* used for x8/x16 adjustments		*/
	ushort	legacy_unlock;		/* support Intel legacy (un)locking	*/
#endif
} flash_info_t;
nor  flash的结构体如上:

定义flash的大小、块数、ID、每块的的起始地址、每块保护状态标记位;接着定义适用于CFI的标准接口,我们这里没有采用。


ulong flash_init (void)
{
	int i, j;
	ulong size = 0;

	for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) {
		ulong flashbase = 0;

		flash_info[i].flash_id =
#if defined(CONFIG_AMD_LV400)
			(AMD_MANUFACT & FLASH_VENDMASK) |
			(AMD_ID_LV400B & FLASH_TYPEMASK);
#elif defined(CONFIG_AMD_LV800)
			(AMD_MANUFACT & FLASH_VENDMASK) |
			(AMD_ID_LV800B & FLASH_TYPEMASK);
#else
#error "Unknown flash configured"
#endif
			flash_info[i].size = FLASH_BANK_SIZE;
		flash_info[i].sector_count = CFG_MAX_FLASH_SECT;
		memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT);
		if (i == 0)
			flashbase = PHYS_FLASH_1;
		else
			panic ("configured too many flash banks!\n");
		for (j = 0; j < flash_info[i].sector_count; j++) {
			if (j <= 3) {
				/* 1st one is 16 KB */
				if (j == 0) {
					flash_info[i].start[j] =
						flashbase + 0;
				}

				/* 2nd and 3rd are both 8 KB */
				if ((j == 1) || (j == 2)) {
					flash_info[i].start[j] =
						flashbase + 0x4000 + (j -
								      1) *
						0x2000;
				}

				/* 4th 32 KB */
				if (j == 3) {
					flash_info[i].start[j] =
						flashbase + 0x8000;
				}
			} else {
				flash_info[i].start[j] =
					flashbase + (j - 3) * MAIN_SECT_SIZE;
			}
		}
		size += flash_info[i].size;
	}

	flash_protect (FLAG_PROTECT_SET,
		       CFG_FLASH_BASE,
		       CFG_FLASH_BASE + monitor_flash_len - 1,
		       &flash_info[0]);

	flash_protect (FLAG_PROTECT_SET,
		       CFG_ENV_ADDR,
		       CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]);

	return size;
}

第6行的for循环运行一次,原因:nor flash只有一块

7行:定义变量存储flash的大小。

9-18行:写nor flash的ID,对flash结构体中的变量ID进行初始化

19-53: 对flash的结构体进行初始化,考虑flash的块有小块

54-62:对uboot的代码、环境变量进行保护


二:void flash_print_info (flash_info_t * info)

函数的打印信息

三:int flash_erase (flash_info_t * info, int s_first, int s_last)

nor flash的擦除。

int flash_erase (flash_info_t * info, int s_first, int s_last)
{
	ushort result;
	int iflag, cflag, prot, sect;
	int rc = ERR_OK;
	int chip;

	/* first look for protection bits */

	if (info->flash_id == FLASH_UNKNOWN)
		return ERR_UNKNOWN_FLASH_TYPE;

	if ((s_first < 0) || (s_first > s_last)) {
		return ERR_INVAL;
	}

	if ((info->flash_id & FLASH_VENDMASK) !=
	    (AMD_MANUFACT & FLASH_VENDMASK)) {
		return ERR_UNKNOWN_FLASH_VENDOR;
	}

	prot = 0;
	for (sect = s_first; sect <= s_last; ++sect) {
		if (info->protect[sect]) {
			prot++;
		}
	}
	if (prot)
		return ERR_PROTECTED;

	/*
	 * Disable interrupts which might cause a timeout
	 * here. Remember that our exception vectors are
	 * at address 0 in the flash, and we don't want a
	 * (ticker) exception to happen while the flash
	 * chip is in programming mode.
	 */
	cflag = icache_status ();
	icache_disable ();
	iflag = disable_interrupts ();

	/* Start erase on unprotected sectors */
	for (sect = s_first; sect <= s_last && !ctrlc (); sect++) {
		printf ("Erasing sector %2d ... ", sect);

		/* arm simple, non interrupt dependent timer */
		reset_timer_masked ();

		if (info->protect[sect] == 0) {	/* not protected */
			vu_short *addr = (vu_short *) (info->start[sect]);

			MEM_FLASH_ADDR1 = CMD_UNLOCK1;
			MEM_FLASH_ADDR2 = CMD_UNLOCK2;
			MEM_FLASH_ADDR1 = CMD_ERASE_SETUP;

			MEM_FLASH_ADDR1 = CMD_UNLOCK1;
			MEM_FLASH_ADDR2 = CMD_UNLOCK2;
			*addr = CMD_ERASE_CONFIRM;

			/* wait until flash is ready */
			chip = 0;

			do {
				result = *addr;

				/* check timeout */
				if (get_timer_masked () >
				    CFG_FLASH_ERASE_TOUT) {
					MEM_FLASH_ADDR1 = CMD_READ_ARRAY;
					chip = TMO;
					break;
				}

				if (!chip
				    && (result & 0xFFFF) & BIT_ERASE_DONE)
					chip = READY;

				if (!chip
				    && (result & 0xFFFF) & BIT_PROGRAM_ERROR)
					chip = ERR;

			} while (!chip);

			MEM_FLASH_ADDR1 = CMD_READ_ARRAY;

			if (chip == ERR) {
				rc = ERR_PROG_ERROR;
				goto outahere;
			}
			if (chip == TMO) {
				rc = ERR_TIMOUT;
				goto outahere;
			}

			printf ("ok.\n");
		} else {	/* it was protected */

			printf ("protected!\n");
		}
	}

	if (ctrlc ())
		printf ("User Interrupt!\n");

      outahere:
	/* allow flash to settle - wait 10 ms */
	udelay_masked (10000);

	if (iflag)
		enable_interrupts ();

	if (cflag)
		icache_enable ();

	return rc;
}

10-11:检查flash的ID是否正确

13-14:检测flash的块设置是否正确

23-26:遍历所要擦除的块,如果有保护块,退出

38-41:关闭中断、代码缓存。防止在操作flash的过程中造成中断、擦除不成功。

43:遍历块循环

47:复位时间戳,用于统计擦除时间

49-58:进行擦除操作,6个循环

60-96:对擦除结果进行分析,如果延时时间到,退出;分析是否擦除完毕与擦除错误

最后:开中断、开代码缓存等



四:int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)

flash的写数据

int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt)
{
	ulong cp, wp;
	int l;
	int i, rc;
	ushort data;

	wp = (addr & ~1);	/* get lower word aligned address */

	/*
	 * handle unaligned start bytes
	 */
	if ((l = addr - wp) != 0) {
		data = 0;
		for (i = 0, cp = wp; i < l; ++i, ++cp) {
			data = (data >> 8) | (*(uchar *) cp << 8);
		}
		for (; i < 2 && cnt > 0; ++i) {
			data = (data >> 8) | (*src++ << 8);
			--cnt;
			++cp;
		}
		for (; cnt == 0 && i < 2; ++i, ++cp) {
			data = (data >> 8) | (*(uchar *) cp << 8);
		}

		if ((rc = write_hword (info, wp, data)) != 0) {
			return (rc);
		}
		wp += 2;
	}

	/*
	 * handle word aligned part
	 */
	while (cnt >= 2) {
		data = *((vu_short *) src);
		if ((rc = write_hword (info, wp, data)) != 0) {
			return (rc);
		}
		src += 2;
		wp += 2;
		cnt -= 2;
	}

	if (cnt == 0) {
		return ERR_OK;
	}

	/*
	 * handle unaligned tail bytes
	 */
	data = 0;
	for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) {
		data = (data >> 8) | (*src++ << 8);
		--cnt;
	}
	for (; i < 2; ++i, ++cp) {
		data = (data >> 8) | (*(uchar *) cp << 8);
	}

	return write_hword (info, wp, data);
}

此程序应该在开始时候进行保护位的校验。不校验在回来的写函数中也不能写成功,

13-30,判断开始地址是否为字对齐,如果不是进行调节。注意我们的是小端。高位为高字节

36-44,写操作

44-60,判断结束为止是否为字对齐,如果不是,进行调节



六、volatile static int write_hword (flash_info_t * info, ulong dest, ushort data)

写操作、可以参考擦除操作。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值