uboot nand flash 流程

本文详细介绍了U-Boot NAND Flash的启动流程,包括initr_nand、nand_init、nand_init_chip等函数的调用过程。还阐述了board_nand_init函数对开发板相关寄存器的初始化,以及nand_scan函数对NAND设备的扫描,涉及ECC校验、坏块表创建等关键操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

uboot nand flash 启动 流程

1、initr_nand

首先在board_r.c中,initr_nand函数正式进入nand flash的初始化等操作。

static int initr_nand(void)
{
   
	puts("NAND:  ");
	nand_init();
	return 0;
}

2、nand_init

之后进入nand_init函数,该函数位于drivers\mtd\nand文件中的nand.c文件中,由于CONFIG_SYS_NAND_SELF_INIT未定义,所以后续调用nand_init_chip函数。

void nand_init(void)
{
   
#ifdef CONFIG_SYS_NAND_SELF_INIT//未定义
	board_nand_init();
#else
	int i;

	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)//初始化板上nand flash
		nand_init_chip(i);
#endif

	printf("%lu MiB\n", total_nand_size / 1024);

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
	/*
	 * Select the chip in the board/cpu specific driver
	 */
	board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
#endif
}

3、nand_init_chip

而nand_init_chip同样位于drivers\mtd\nand文件中的nand.c文件中,该函数调用初始化函数,给mtd和nand两个结构体赋值,首先调用board_nand_init函数

#ifndef CONFIG_SYS_NAND_SELF_INIT
static void nand_init_chip(int i)
{
   
	struct mtd_info *mtd = &nand_info[i];//该结构体位于\include\linux\mtd文件中的mtd.h文件中
	struct nand_chip *nand = &nand_chip[i];//该结构体位于\include\linux\mtd文件中的nand.h文件中
	ulong base_addr = base_address[i];
	int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;

	if (maxchips < 1)
		maxchips = 1;

	mtd->priv = nand;
	nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;

	if (board_nand_init(nand))
		return;

	if (nand_scan(mtd, maxchips))
		return;

	nand_register(i);
}
#endif

4.1、board_nand_init

函数主要初始化开发板相关与nand_flash的寄存器,和绑定nand_chip结构体中的调用函数,由于不同开发板调用函数不同,所以该函数内部赋值会不一样,本次使用的是NXP MX6ULL开发板,调用的是mxs_nand.c中的函数,其中关于带有ECC的读写函数和ECC的模式,**这里使用的是硬件自带ECC,每512字节需要9字节的ECC数据,最大可纠正8bit数据。**而不同的flash,会规定不同的nand flash ECC,这里规定每最少需要纠正4bit数据,需要用512Byte数据+4Byte备用数据和8字节奇偶校验数据。所以uboot中的ECC符合nand flash 最低ECC 标准。
M69A ECC infomation

int board_nand_init(struct nand_chip *nand)
{
   
	struct mxs_nand_info *nand_info;
	int err;

	nand_info = malloc(sizeof(struct mxs_nand_info));
	if (!nand_info) {
   
		printf("MXS NAND: Failed to allocate private data\n");
		return -ENOMEM;
	}
	memset(nand_info, 0, sizeof(struct mxs_nand_info));

	err = mxs_nand_alloc_buffers(nand_info);
	if (err)
		goto err1;

	err = mxs_nand_init(nand_info);
	if (err)
		goto err2;

	memset(&fake_ecc_layout, 0, sizeof(fake_ecc_layout));

	nand->priv = nand_info;
	nand->options |= NAND_NO_SUBPAGE_WRITE;

	nand->cmd_ctrl		= mxs_nand_cmd_ctrl;

	nand->dev_ready		= mxs_nand_device_ready;
	nand->select_chip	= mxs_nand_select_chip;
	nand->block_bad		= mxs_nand_block_bad;
	nand->scan_bbt		= mxs_nand_scan_bbt;

	nand->read_byte		= mxs_nand_read_byte;

	nand->read_buf		= mxs_nand_read_buf;
	nand->write_buf		= mxs_nand_write_buf;

	nand->ecc.read_page	= mxs_nand_ecc_read_page;
	nand->ecc.write_page	= mxs_nand_ecc_write_page;
	nand->ecc.read_oob	= mxs_nand_ecc_read_oob;
	nand->ecc.write_oob	= mxs_nand_ecc_write_oob;
	
	nand->ecc.layout	= &fake_ecc_layout;
	nand->ecc.mode		= NAND_ECC_HW;
	nand->ecc.bytes		= 9;
	nand->ecc.size		= 512;
	nand->ecc.strength	= 8;

	return 0;

err2:
	free(nand_info->data_buf);
	free(nand_info->cmd_buf);
err1:
	free(nand_info);
	return err;
}

4.1.1 mxs_nand_init

其中mxs_nand_init主要配置nand flash相关的硬件寄存器,GMPI和BCH寄存器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值