9.NandFlash的驱动_读操作2440
9.NandFlash的驱动_读操作
在Makefile里添加nand.o,然后新建一个nand.c来实现NandFlash的读操作。
对NandFlash的读方式有两种:
-
按页读(需要提供页地址,也就是行地址)。
-
随机读(就是读取页里的某一列,需要提供页地址,也就是行地址和列地址)。
实现页读需要两个操作,一个是页地址,另一个是存放读出的数据的变量。所以定义的函数的原型:
void NF_PageRead(unsigned long addr,unsigned char* buff)
该函数根据NandFlash的手册:K9F2G08U0A.pdf中读的操作流程:
上面是TQ2440NandFlash读的操作流程,最下面的I/Ox是I/O pin角的输入输出信号。首先是发送命令:00h。接着是发送5个周期的地址Address(5Cycle):三个周期的行地址和两个周期的列地址。
发送完地址后,紧接着就是发送命令30h。接着就是等待R/B信号变为高电平。从上图可以看到,当我们发送完30h命令后,信号从高电平变成低电平,进入忙的状态。这是CPU开始处理前面发送的命令和地址。等待完后就可以读取数据了。
上面是页读的流程,但是这里需要补充一些公共的步骤:
首先你要操作NandFlash,必须要先选中。接着是清除R/B信号。接着才是上面的操作。操作完,最后还得加上:取消选中NandFlash芯片。操作步骤如下:
从上面的步骤可以看到,首先是要选中NandFlash芯片,是通过NFCONT这个寄存器的[1]位来操作的:
从上面的说明看到,如果要Enable chip select,就是把[1]位置为0即可。然后习惯在操作NandFlash前要使能片选,操作完会禁止片选。一般写入0是采用与操作,写入1是采用或操作。所以代码实现:
选中NandFlash芯片:
上面,我们把[1]位先置为1,再取反变为0,最后与NFCONT相与,是NFCONT的[1]位为0.实现片选NandFlash。
上面是取消片选,情况跟使能片选相反。
接着是R/B信号的处理,它是在NFSTAT寄存器里的:
之所以需要先清除R/B信号,这是因为在进行一次NandFlash的操作前要确保上一次的操作已经被清除了,不会影响到这一次的操作。就是要先把这一位变为0,即是清除。然后后面我们只要检查这一位如果是1即可认为NandFlash处于可读写状态。然后注意到跟前面的中断一样,要把某一位变为0,就是往对应的位写入1.
实现代码:
清除完后就是发送命令00h了。
命令00h作为参数,通过send_cmd传递给NFCMD寄存器。
发送完命令就是发送地址了。
首先是发送列地址,但是这里采用按页读的,所以列地址都是0,由于每一次发送0位,所以是0x00,由下面的时序图知道,需要发送两次列地址。
实现代码:
发送完列地址,接着就是发送行地址。行地址是按照从低位到高位的顺序来发送,每次发送8位。三个周期的行地址的方式如下:
按照时序图,接下来是发送0x30命令,
发送完命令后进入等待,等待前面的操作完成。完成的标识是R/B信号变为高电平:
等待完R/B信号后,根据时序图,我们就可以实现信号的读取了。
读取是从NFDATA寄存器里面读取的。
每个页的大小在2440里是2K,根据型号不同,值可能不同。最后按页读的操作:
这里实现了NandFlash读的基本操作,但是在前面的学习知道,在操作一个硬件之前必须对该硬件进行初始化操作。
NandFlash初始化的操作流程:
NandFlash初始化要配置NandFlash的配置寄存器NFCONF和寄存器NFCONT
三个时序图的关系:
上面三个参数的取值运算:
我们的nandflash使用的HCLK,频率是100MHz的。那么他每震动一次对应的时间是10ns(1/100MHz).
上面有算TACLS>0ns
TWFPH0>12ns
TWFPH1>5ns的公式。
要实现duration=HCLK*TACLS=10ns*TACLS>0,只需要取TACLS=1,即可。
要实现duration=HCLK*(TWRPH0+1)=10ns*(TWRPH0+1)>12ns,只需要TWRPH0=2即可
要实现duration=HCLK*(TWRPH1+1)=10ns*(TWRPH1+1)>5ns,只需要TWRPH1=1,即可。
上面就是配置NandFlash配置寄存器的参数。
下面是NandFlash的控制寄存器
接下来是初始化我们的NFCONT。
先使能控制器,然后让取消片选:
操作完成还需要第三步是复位操作:
可以看到复位的操作很简单,就是发送FFh命令,然后等待R/B信号,等待从低变高表示完成了。
上面的学习知道,要操作NandFlash,首先要选中NandFlash,然后清除R/B信号。接着才是发送ffh命令来复位NandFlash,等待R/B信号复位完成。最后要取消选中NandFlash。
实现:
最后的NandFlash的初始化流程代码:
到这里我们才完成了NandFlash读的全部操作。
前面的学习知道:
从上面知道,当系统上电后,会拷贝NandFlash里的4KB代码到Stepping Stone去运行。而实际运行stepping stone里代码的是拷贝到内存里去运行的,最大是4KB。所以如果当我们的uboot的代码大于4KB的时候,就会拷贝不全,导致运行出错。
前面之所以要这样做是因为当初没有学习NandFlash的知识,不会直接从NandFlash拷贝代码到内存去运行,而是通过垫脚石。所以下面就直接从NandFlash拷贝代码到内存去运行,这样的程序就完整了。
要实现按页拷贝NandFlash里的内容,首先需要知道页的首地址。
这里地址的0-11位是列地址,即是页内偏移量。我们要的是页地址,所以需要把低12位去掉。按页拷贝的代码:
最后是修改start.S文件:
在内存初始化:
完成之后,由于我们的NandFlash的初始化是用C实现的,所以在调用NandFlash初始化的函数前需要对堆栈进行初始化。所以跳转如下:
最后是跳转到copy_to_ram,即是从iRam拷贝到内存运行的,此时我们是直接把NandFlash的代码拷贝到内存去运行了,所以此处的代码也需要修改。
上面就完成了所有的操作,make编译。
上面是2440和6410的操作步骤,但是210的还需要修改一个寄存器MPLLCON.