说实话这一节课的实例我是没有亲自写代码来练习的,因为我看了一下,操作方式还是很熟悉的。有过单片机开发经验的人应该很熟悉这种操作方式,比如12864的液晶控制等等。
首先看NANDFLASH和S3C2440的连接方式,和SDRAM有很大的不同:没有地址线。但是存储器内部的访问肯定是需要地址的,操作Flash就像快递的取件寄件,没有个地址怎么玩得转呢?除了数据线以外,可以看到还有额外的几根控制线,CLE是命令所存使能,ALE是地址锁存使能,CE是芯片使能,RE是读使能,WE是写使能,WP是写保护,R/B是就绪/忙输出信号。至于数据线的数据到底是数据还是地址还是命令,都是根据CLE和ALE来区分的。
操作NANDFLASH时,先传输命令,然后传输地址,最后读/写数据,期间要检查Flash的状态。NANDFLASH K9F1208U0M的命令字如下图:
S3C2440内部提供了NANDFLASH的控制器,也就是说有些事情是硬件来完成的,比如写命令直接往命令寄存器写命令,那些控制线该高还是以及时序问题都是硬件来完成的,所以控制NANDFLASH还是很方便的。下面以读操作为例进行简要的介绍:
假设地址是addr
1>设置NFCONF,NFCONT
这两个是配置NANDFLASH控制器的,也就是初始化控制器,可以根据自己想要的功能和查阅手册来设置它。这里需要注意的是控制器的时钟设置要满足外部芯片的要求,芯片的读写对时间有要求,不能太快的,不然会出错的。
2>在第一次操作NANDFLASH前,通常复位一下NANDFLASH
NFCONT
&=~(1<<1) 发出片选信号
NFCMD
= 0XFF RESET命令,这个可以在芯片的手册中查到
然后循环查询NFSTAT的0位,直到等到它为1,也就是复位操作已经完成了,这样才能进行下一步操作,最后禁止片选信号,在实际使用的过程中再使能。
NFCONF |=0X2。
3>发出读命令
先使能NANDFLASH,然后发出读命令。
NFCONF &=~(1<<1) 发出片选信号
NFCDM =0或者1 读命令,其实这个命令的值还被用作地址线的A8
4>发出地址信号
这一步需要注意,发出的地址中的A8并没有用到,它的值是多少根据读命令的值来确定,用来确定是在某一页的上半部分寻址还是下半部分寻址。
NFADDR
= addr & 0XFF 先写地位地址,然后高位地址
NFADDR = (addr>>9)
& 0XFF 这里需要注意右移的是9位,不是8位,原因刚刚已经说明
NFADDR = (addr>>17)
& 0XFF这里需要注意右移的是17位,不是16位
NFADDR = (addr>>25)
& 0XFF这里需要注意右移的是25位,不是24位
5>循环查询NFSTAT的0位,直到它等于1,这是可以读取数据了
6>连续读NANDFLASH寄存器512次,可以读取一页数据
7>最后,禁止片选信号
NFCONT
|= (1<<1)
另外写个小插曲:连接脚本。就是在连接的时候根据这个脚本来作指示,原来我们编译的时候不是有个-Ttext的选项可以指定代码段的地址吗,这里如果是-Tnand.lds,就是根据nand.lds这个连接脚本来连接。
SECTIONS{
first
0X00000000:{head.o init.o nand.o}
second 0X30000000:AT(4096) {main.o}
}
first和second就是连接的时候分成了两部分,head.o和init.o和nand.o连接成为一部分,main.o自己为一部分,连接基址就是0X00000000和0X30000000,而后面的AT(4096)就是在控制main.o在最后生成的连接文件的哪个地方,也就是4096个字节的地方开始存放main.o,这样整个bin文件烧入Flash后,第4096的字节开始存放的就是main.o里面的程序指令。
|