-
..xuexi
-
学习一下
-
最后的文件操作是擦除nand第0块,把里面的内容全部变为0xff。再用批量读取函数Nand_readskipbad()读取到缓冲区域(即数组b),再以16进制打印数组b的内容。用串口调试软件印证,得到0xff。说明正确。批量读取函数里的坏块跳过部分挺有意思的,可以仔细分析下
-
结尾一下,把nand某一地址起的length长度读取到缓冲区域。刚刚调好了。传一下工程文件{:1_138:}有兴趣的看看吧,明天开始看sdram部分,把这部分初始化好。再把缓冲区域的数据写入,就能实现代码从外部rom到内存的过程啦!
-
另外有没有谁教我下字符串输出函数怎么整:Sad:我一个个字符打的累
-
:)把代码搬移到sdram这个还得再弄弄,明天再说吧
-
void Nand_IsBadBlock(uint block)
{
uchar Data;
nand_Ramdomread(block, 0, 2054, 1, &Data);
if (Data != 0xff) {
putc('b');
putc('a');
putc('d');
putc('b');
putc('l');
putc('o');
putc('c');
putc('k'); // 坏块
}
}
坏块识别,没什么难点。每个block第一页spare(即64bytes)区第6字节非0xff标记为好坏。所以读出第2048+6个存储单元的值,判断是否等于0xff。
这里有一个很有意思的地方,我们都知道,nandearse会把擦除后的单元恢复为0xff。
这就印证一点,nandearse擦除的只有main区(2k)
-
再次打开helper2416原理图
找到nand接口,再次注意!!! 很重要的一点,nand接口只有地址总线的接口,和存储控制器接口不同,nand接口并没有数据总线接口。
地址总线A0-A28这29根地址总线用来进行nand寻址
如图片所示
因为2416板子上所用的是大页nand,每页容量为2k+64bytes
所有需要A0-A11这12根地址线来寻址(2的12次方是2k),这就是列地址,即在一页中的地址,请回头找一下我在前面nand.c中对NFADDR的定义。这个数据缓冲寄存器是一个8位寄存器,所以,在发送页内地址时。需要2次。第一次发送地址的低8位,再发送高4位,当然,此时要记得屏蔽掉地址的后面几位。
同理,整个nand有2k块,每块64页,一块nand就有128k个页面,需要A12-A28这17根地址线。发送5次地址
。可能看到这里有一个疑问,对整个nand来说,地址是28位,寻址不应该只需要发送地址4次就足够?
这其中涉及到行地址与列地址的不同。请看我的附图,前两次发送了页内地址(即列地址)
后3次才是行地址,第二次发送地址时。并没有全部使用8个位。
这个比较抽象,有疑问可以提出来,我再和你说。
-
void nand_Ramdomread(uint block,uint page,uint add,uint length,uchar *buf)
{
uint i;
page+=(block8)&0xff);
nand_write_addr((page>>16&0xff));
nand_write_com(0x30);
nand_check_busy();
nand_write_com(0x05);
nand_write_addr((char)add&0xff);
nand_write_addr((char)(add>>8)&0x0f);
nand_write_com(0xe0);
nand_check_busy();
for(i=0;i
-
void nand_Ramdomwrite(uint block,uint page,uint add,uint length,uchar *dat)
{
uint i;
page +=(block8)&0xff);
nand_write_addr((page>>16)&0xff);
nand_write_com(0x85);
nand_write_addr((char)add&0xff);
nand_write_addr((char)(add>>8)&0x0f);
for(i=0;i
-
放假拖更了==现在说一下页内读写
-
对裸机有一定认识,初看了您的书,实在无从下手。可能跨度比较大
-
{:1_137:}剩下的nand随机操作,坏块识别,复制代码到sdram。。明天再说
-
读id函数,void nand_read_id(uchar *buf)
{
int i;
nand_enable();
nand_enable_rb();
nand_write_com(0x90);
nand_write_addr(0x0);
for(i=0;i
-
爆炸,写了一大段没发出来。
-
其他的页读,页写函数大同小异,自行分析吧==
关于读id函数,这里介绍一下id。
直白的说就是nand的身份证,通过读取id,可以得知nand的一些信息。恰好工程文件我最后留下的就是这个函数,直接make后下载到sdcard里,启动,连接串口0(注意是串口0,要用串口1的话修改代码里的uart_init函数)
串口就会打印出EC DA 10 95 44
第一位是制造商码,不管
第二位是产品码 ,不管
其他3位则是产品的细节,对应nand的datesheet,可以得知nand的基本属性(uboot和内核都是通过这个方法来得到nand的信息并进行相应操作的)。
补充一下。nand。c里的主函数control,,,你把我注释掉的程序去掉注释,可以打印循环0-0xff的数,
也就是先页写,再把这一页读出来。算是印证了操作的正确性吧。
-
下面我们就用这些基础的nand函数,来组成对nand的页操作,块操作。
int nand_erase(uint block)
{
uint blocknum=block8)&0xff);
nand_write_addr((blocknum>>16)&0xff);
nand_write_com(0xD0);
nand_check_busy();
nand_disable();
return 1;
}
无非就是使能nand,开启忙检。发送第一个命令(可以注意到,发送了两次不同的命令。)
为什么是两次?应该考虑到nand是一个高速工作状态下的设备。在nand_init函数里,可以看到NFCONF函数的3个时序参数均被设置为20ns左右。所以,nand是非常讲究工作的效率的。并非是你说要开始nand擦除操作,cpu就会马上操作。它需要一个更确定的时机,比如你已经把地址写进控制器了,它才开始做事。
然后,更重要的!!!! 发送了3次地址,按照常理,不是发送一次就行了吗?
只能说,接口电路很重要,请回头去板子的nand接口,你会发现,2416的nand接口的数据线和地址线是复用的
而nand的地址是28位的,因此不能一次发送完。(好像没人看。。就简单点写了)
-
主要有这么几个函数
#define nand_write_com(cmd) {NFCMMD=(cmd);}发送命令给nand,通过操作nand控制器的NFCMMD寄存器
#define nand_write_addr(addr) {NFADDR=(addr);}
#define nand_write_dat(dat) {NFDATA8=(dat);}类似的数据和地址发送函数。
#define nand_enable() {NFCONT &= ~(1
-
nand的容量=块的数目*每块包含的页数*每页的容量
板子上用的nand属于大页nand,2k块*64页*(2k+64)=容量
这里可以注意一下,每页的容量是2k+64字节,2k指的是可以存储信息的存储单元,在未写入状态下是1,所以擦除nand,就是往存储单元写1.64bytes,指的是这一页的控制信息。包括支持随机读写,ecc的校验值,都在这64字节里。
打开control.c @vi control.c
关于nand的基础操作函数都是以宏定义方式存在的。
-
上课=-=,晚上接着分享吧。