2440裸机学习心得(下)
12、NORFLASH操作
norflash为EN29LV160AB
对norflash的操作主要就是读、写、擦除和识别
EN29LV160AB的数据宽度可以是8位字节型,也可以是16位的字型,它由某一引脚配置实现的。在这里我们选择字型
BYTE#位置硬件接地,直接默认为Word Mode(16位)
写操作只能使“1”变为“0”,而只有擦除才能使“0”变为“1”。因此在写之前一定要先擦除
对norflash另一个比较常用的操作是读取芯片的ID
NorFlash启动,nGCS0接NorFlash,起始地址为0x0。0x0000 0000–0x0800 0000为NorFlash
注意几个地方:
1、#defineCMD_ADDR0*((volatile U16 *)(0x555<<1+flash_base))
之所以又把norflash中的地址向左移一位(即乘以2),是因为我们是把s3c2440的ADDR1连接到了norflash的A0上的缘故,(自己看原理图),容易理解,等于本来最低位的数被推后没了,要左移拉回来。
2、check_toggle函数(校验函数)中
oldtoggle = *((volatile U16 *)0x0);newtoggle = *((volatile U16 *)0x0);
表示两次读值
if((oldtoggle & 0x40)==(newtoggle & 0x40)) //表示两次的DQ6是否相同
if(newtoggle & 0x20)//DQ5是否为1
几个常用的函数:
读函数: read_en29lv160ab(U32 addr)
return *((volatile U16 *)(addr));//数据要转为16位
写函数: en29lv160ab_program(U32 addr, U16 dat)
第一个周期是把命令0xAA写入地址为0x555的命令寄存器中,
第二个周期是把命令0x55写入地址为0x2AA命令寄存器中,
第三个周期是把命令0xA0再写入地址为0x555命令寄存器中,
第四个周期为真正地把要写入的数据写入到norflash的地址中。
复位函数: reset_en29lv160ab(void)
是向任一地址写入复位命令0xF0
擦除函数: en29lv160ab_sector_erase(U32 section_addr)
第一个周期是把命令0xAA写入地址为0x555的命令寄存器中,
第二个周期是把命令0x55写入地址为0x2AA命令寄存器中,
第三个周期是把命令0x80再写入地址为0x555命令寄存器中,
第四个周期是把命令0xAA写入地址为0x555的命令寄存器中,
第五个周期是把命令0x55再写入地址为0x2AA命令寄存器中,
第六个周期是把命令0x30写入要擦除块的首地址内
验证函数: check_toggle()
连续两次读取数据总线上的数据,判断数据总线上的第6位数值(DQ6)是否翻转,如果没有翻转则正确,否则还要判断第5位(DQ5),以确定是否是因为超时而引起的翻转。
读ID函数:get_en29lv160ab_id()
第一个周期是把命令0xAA写入地址为0x555的命令寄存器中,
第二个周期是把命令0x55写入地址为0x2AA命令寄存器中,
第三个周期是把命令0x90再写入地址为0x555命令寄存器中,
第四个周期为读取地址为0x100中的内容,即厂商ID(0x1C)。
读取设备ID的过程的前三个周期与读取厂商ID相同,第四个周期是读取地址为0x01中的内容,即设备ID(0x2249)
问题1:
原来真的是写得块地址问题,写到前面的0x400就行,写后一点如0xf0000就读不出来了,0x0000 0000–0x0800 0000为NorFlash,为什么后面的不行呢?
问题2:
本来擦除后写完能读出写的内容,但再复位后不写,只读回上次地址,发现读出不同的数据
而且好像擦除后就算返回return 1也没用,擦后读回那地址,也不是全部数据为0的,也是有值的
13、NANDFLASH操作
nandflash为K9F2G08U0A,它是8位的nandflash
一个劣势是很容易产生坏块,因此在使用nandflash时,往往要利用校验算法发现坏块并标注出来
K9F2G08U0A的一页为(2K+64)字节(加号前面的2K表示的是main区容量,加号后面的64表示的是spare区容量),它的一块为64页,而整个设备包括了2048个块
内存容量大小计算:
要实现用8个IO口来要访问这么大的容量,K9F2G08U0A规定了用5个周期来实现。
列地址是用于寻址页内空间,行地址用于寻址页,如果要直接访问块,则需要从地址A18开始。
CMD_STATUS读状态命令可以实现读取设备内的状态寄存器,通过该命令可以获知写操作或擦除操作是否完成(判断第6位),以及是否成功完成(判断第0位)。
自己编写NANDFLASH的步骤:(进行块擦除,页写,页读)
1、在头文件中列出相关的固量 和 函数 宏
常用的各种命令集;一些基于NANDFLASH控制器的基本函数
ECC应用和使能nandflash片选;NFSTAT寄存器
一些返回判断值的宏定义
2、写出几个基本的初始化函数:
管脚,寄存器初始化函数 ; 复位函数 ; 读NANDID号函数
3、相关的检测判断函数:
A、检测是否写擦除成功函数NF_toggle:通过NF_CMD(CMD_STATUS)状态位
B、测试是否坏块函数NF_testBadBlock:读取2054处坏块标志位
C、写坏块标志函数NF_MarkBadBlock:写标志到 2054处
4、读、写、擦除函数:
具体自己看代码了,有两点要注意了:
A、读操作 检测正确性是通过ECC检验码,而写和擦除是通过toggle函数
B、随机读写是 在读页,写页的基础上 加上列的部分
注意区别两个东西:
1、ECC检验码的判断
读操作来说,我们还要继续读取spare区的相应地址内容,已得到上次写操作时所存储的main区和spare区的ECC,并把这些数据分别放入NFMECCD0/1和NFSECCD的相应位置中。最后我们就可以通过读取NFESTAT0/1(因为K9F2G08U0A是8位IO口,因此这里只用到了NFESTAT0)中的低4位来判断读取的数据是否正确,其中第0位和第1位为main区指示错误,第2位和第3位为spare区指示错误。
2、坏块的判断
对于写页和擦除操作来说,通过toggle函数检测:
NF_CMD(CMD_STATUS); //读状态命令
//判断状态值的第6位是否为1,即是否在忙
//判断状态值的第0位是否为0,为0则写操作正确,否则错误
若第0位操作错误,则该块为 坏块
3、main区和spare区的解锁只为了产生ECC码,一旦产生后,就要锁上,打开另外区的,不要影响互相顺序的ECC码产生
扩展:从NANDFLASH启动程序
当检测到是由nandflash启动时,系统会自动把nandflash中的前4k字节的数据加载到Steppingstone中,然后把该Steppingstone映射为Bank0,因此系统会从Steppingstone开始运行程序,从而实现了s3c2440的nandflash自启动的功能
通过在Steppingstone中,把程序的其余部分复制到RAM中,程序运行时由Steppingstone转移到该RAM中,SRAM起始地址0x30000000
RdNF2SDRAM是C语言编写的一段把nandflash中的数据复制到SRAM的程序
看看这函数,了解一下就行了
附加:nandflash、norflash、SDRAM的区别:
ROM在系统停止供电的时候仍然可以保持数据,
RAM通常都是在掉电之后就丢失数据,典型的RAM就是计算机的内存。
SRAM速度非常快,是目前读写最快的存储设备了,但是它也非常昂贵,所以只在要求很苛刻的地方使用,譬如CPU的一级缓冲,二级缓冲
动态RAM(Dynamic RAM/DRAM),DRAM保留数据的时间很短,速度也比SRAM慢,不过它还是比任何的ROM都要快,但从价格上来说DRAM相比SRAM要便宜很多,计算机内存就是DRAM的。本文引用地址:https://www.eepw.com.cn/article/201611/323342.htm
RAM |
SRAM |
DRAM |
SDRAM,DDR RAM等 |
ROM |
EROM,E2PROM等 |
NANDFLASH、NORFALSH等 |
关键词:
2440v裸机学
评论