天天看点

NandFlash控制器

NandFlash控制器

本文以MT29F4G08ABADA 型号为例

MT29F4G08ABADA容量为4Gbit

1page=(2K+64)byte

1block=(2K+64)64page=(128K+4K)byte

1plane=(128K+4K)2048block=2112Mbit

1device=2112Mbit2

地址序列如下

NandFlash控制器

CAx为列地址; PAx =页地址; BAx = block地址

命令,地址,数据都通过8个IO口输入/输出。写入命令、数据、地址时,都需要将WE#、CE#信号同时拉低。数据在WE#信号的上升沿被NAND Flash锁存。命令锁存信号CLE和地址锁存信号ALE用于分辨、锁存命令或地址。MT89F4G08ABADA需要34位地址。读写命令需要发送5个地址序列。具体命令可以参考MT29F4G08ABADA数据手册。接下来将会对nand flash的ECC校验做个简要讲解,NandFlash的ECC校验分为软件ECC校验和硬件ECC校验,由于该芯片自带OndieECC校验,因此我们对ondie ecc校验做个代码分析,以xilinx uboot为例,在上电过程中,完成对nandflash的初始化和Ondie ecc的校验。

Xilinx的启动主要为一下几个步骤:

1.根据器件的MIO[2…8]确定从那个设备启动

2.加载FSBL,FSBL主要完成以下几件事:

1.初始化PS

2.将bitstream写入PL

3.跳转到SSBL,即UBOOT阶段

start.s->cpu_init_crit->lowlevel_init->s_init->board_init_f->board_init_r->main_loop

nandflash的初始化处在board_init_r阶段,通过nand_init初始化nand flash芯片:

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_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

}

通过nand_init函数实现初始化,nand_init()调用board_nand_init函数,接着调用zynq_nand_init完成最终的nandflash的初始化,以及ECC校验,现在就ECC校验做详细说明,首先建立标记坏块的结构体,nand_oob_64表示每一页OOBSize为64Bytes,其中用来标记坏块的大小诶32Bytes,存放的位置为eccpos,偏移值为oobfree,

static struct nand_ecclayout ondie_nand_oob_64 = {

.eccbytes = 32,

.eccpos = {

8, 9, 10, 11, 12, 13, 14, 15,

24, 25, 26, 27, 28, 29, 30, 31,

40, 41, 42, 43, 44, 45, 46, 47,

56, 57, 58, 59, 60, 61, 62, 63

},

.oobfree = {

{ .offset = 4, .length = 4 },

{ .offset = 20, .length = 4 },

{ .offset = 36, .length = 4 },

{ .offset = 52, .length = 4 }

}

};

通过if (get_feature[0] & 0x08) {

debug("%s: OnDie ECC flash\n", func);

ondie_ecc_enabled = 1;

} else {

printf("%s: Unable to detect OnDie ECC\n", func);

}判断是否支持硬件ECC,这里是支持的,然后进入

if (ondie_ecc_enabled) {

nand_chip->bbt_td = &bbt_main_descr;

nand_chip->bbt_md = &bbt_mirror_descr;

}

}接着通过调用nand_scan_tail函数查询并记录本次的ECC校验结果