Nand Flash驱动(实现初始化以及读操作)

本节来学习裸机下的Nand Flash驱动,本节学完后,再来学习Linux下如何使用Nand Flash驱动

Linux中的Nand Flash驱动,链接如下:

(分析MTD层以及制作Nand Flash驱动链接:http://www.cnblogs.com/lifexy/p/7701181.html)

本节简单制作一个Nand Flash驱动(只需要初始化Flash以及读Flash)

打开2440芯片手册,K9F2G08U0M芯片手册(因为2440中Nand Flash是用的256MB(2Gb)内存,8个数据引脚)

在芯片手册中得到K9F2G08U0M=2048块Block=128K页Pages=256MB=2Gb            

1个设备=2048块Block

1块Block=64页Pages

1页=(2K+64)B            (因为每个地址里都存放了一个字节,所以用B表示)

其中64B是存放ECC的OOB地址,(ECC:存放判断位反转的校验码)

Nand Flash 缺点:

读数据容易位反转

可以通过ECC编码器值来判断读数据是否位反转,若位反转则重新读数据

过程:

写:写页数据,生成ECC,ECC写入到OBB页地址里

读:读出页数据,然后判断OOB页地址里的ECC来比较是否出现位反转,是否重新读数据

读OOB方法:

读整个Nand Flash时,是读不出页里面的OBB地址,比如读2049这个地址数据时,是读的第二页上的第2个地址:

只有读某一页时,才能读出这个页里面的OOB地址, 比如读第0页的2049这个地址数据时,才是读的第0页OOB的第2个地址:

Nand Flash芯片硬件引脚图:

RnB:就绪(ready)/忙(busy)输出信号,(1:表示写入数据成功,0:表示正在写入)

CLE:命令(command)锁存(latch)使能,(1:表示当前传的是命令值)

ALE:地址锁存使能,(1:表示当前传的是地址值,当CLE=0和ALE=0,表示传的是数据)

nCE:芯片使能(低电平使能)               (n:表示低电平有效)

nWE:写使能(低电平使能)

nRE:读使能(低电平使能)

nWP:写保护(protect) (1:不保护,0:只能读不能写),默认接高电平.

1.编写nand_init()函数

1.1设置通信时序 

 图1(nandflash时序表):

图2(nandflash时序图):

通过图2和图1可以看出:

tCS是等待芯片使能CE的时间, tCS=20nS

tCLS和tALS是等待WE(写信号)结束的时间, tCLS=tALS=15nS

tWP是WE(写信号)维持时间,  tWP=15nS

 tALH是等待命令写入成功的时间, tALH=5nS

tCLH是等待地址写入成功的时间, tCLH=5nS

图3(2440-nandflash时序图):

首先查看2440芯片手册里nandflash时序图,如上图,可以看出需要设置TACLS,TWRPH0和TWRPH1,这三个参数

TACLS:属于等待WE(写信号)就绪的时间,对比图2得出TACLS= tCLS- tWP=0nS

TWRPH0:属于WE(写信号)的时间, 对比图2得出TWRPH0= tWP=15nS

TWRPH1:属于等待命令写入成功的时间,对比图2得出TWRPH1=tALH=tCLH=5nS

最后,在NFCONF寄存器中设置这三个参数

TACLS[13:12] 

表示Duration(持续时间)=HCLK*TACLS,由于Duration=0nS,所以TACLS=0

TWRPH0 [10:8] 

表示Duration(持续时间)=HCLK*( TWRPH0+1),由于Duration=15nS,HCLK=10nS(100Mhz),所以TWRPH0 =1.

TWRPH1 [6:4] 

表示Duration(持续时间)= HCLK*( TWRPH1 +1),由于Duration=5nS,HCLK=10nS(100Mhz),所以TWRPH1 =0

1.2然后定义全局变量,并实现nand_init()初始化:

/* nand flash  时序 */#define TACLS      0
#define TWRPH0     1
#define TWRPH1     0

 
/*     nand  flash  寄存器       */
#define   NFCONF     *((unsigend int *)0X4E000000); //配置寄存器(用来设置时序)
#define   NFCONT     *((unsigend int *)0X4E000000); //控制寄存器(用来使能nandflash控制器以及ECC编码器,还有控制芯片使能CE脚)
#define   NFCMMD    *((unsigend char *)0X4E000000);//发送命令寄存器(命令只有8位)
#define   NFADDR     *((unsigend char *)0X4E000000);//发送地址寄存器(地址只有8位)
#define   NFDATA      *((unsigend int *)0X4E000000);//读/写数据寄存器(数据只有8位)
#define   NFSTAT      *((unsigend int *)0X4E000000);//运行状态寄存器(用于判断RnB脚)

/*因为Nand Flash只有8位I/O脚,所以NFCMMD/ NFADDR/ NFDATA三个寄存器值都是unsigend char型  */

1.3 nand_init()函数初始化

void nand_init(void)
{

 /* 设置时序 */
NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);

/* bit4=1:初始化ECC,  bit1=1:禁止片选  bit0=1:启动nandflash控制器*/    
NFCONT = (1<<4)|(1<<1)|(1<<0);

}

2编写nand_read()函数

2.1编写nand_read()函数需要以下几个子函数:

2.1.1片选使能函数(在读写FLASH之前都要选中片选)

nand_select()               //使能片选
{
int i;
NFCONT&=~(1<<1);        // NFCONT控制器位1置0
for(i=0;i<10;i++);           //等待芯片使能成功
}

2.1.2取消片选函数(退出读写FLASH时需要取消片选)

nand_deselect()                 //取消片选
{
int i;
NFCONT&=~(1<<1);        // NFCONT控制器位1置0
for(i=0;i<10;i++);           //等待芯片使能成功
}

2.1.3读命令函数

nand_cmd(unsigned char cmd)                 
{
int i;
NFCMMD= cmd;        // 向NFCMMD寄存器写入命令
for(i=0;i<10;i++);        //等待写入命令成功
}

2.1.4判断RnB状态函数(在写入所有命令后都要判断RnB脚是否为高电平就绪)

nand_waite_idle()                 
{
int i;
while(!(NFSTAT&0X01))       // 等待NFSTAT寄存器位0置1
for(i=0;i<10;i++);         
}

2.1.5读数据函数

nand_read_data()                 
{
 unsigend char  p=NFDATA;    //读取NFDATA寄存器
 return p;                   //返回
}

2.1.6 编写写入地址函数 (分5个周期)

首先Nand Flash引脚只有8位,然而地址共有2048(块)*64(页)*2KB,为了读出多个地址,如下图,所以需要分5个周期来实现发送地址

如上图,其中  A10~A0对应页大小(列),由于nandflash每页2048B,所以只用到A10~A0

A28~A11对应页目录(行),表示共有2048块*64(每块有64页)个目录

例如,4097 地址就是:

  A10~A0=4097%2048= 1(A0=1,其余为0)

 A28~A11=4097/2048=2(A13=1,其余为0)

所以nand_write_nand()函数如下:

void nand_read_addr(unsigned int addr)
{

   unsigned int col  = addr % 2048;
   unsigned int page = addr / 2048;
volatile int i;

   NFADDR=(col>>0)&0xff;           //A7~A0,第1周期
for(i=0;i<10;i++);

   NFADDR=(col>>8)&0x0f;           //A10~A8,第2周期
   for(i=0;i<10;i++);

   NFADDR=(page>>0)&0xff;          //A18~A11,第3周期
   for(i=0;i<10;i++);

   NFADDR=(page>>8)&0xff;          //A26~A19,第4周期
   for(i=0;i<10;i++);

   NFADDR=(page>>16)&0xff;         //A27~A28,第5周期
   for(i=0;i<10;i++);  
}

2.2Nand Flash命令图:

如上图,例如:当要reset复位nand flash时

1)      使能片选nand_select();

2)      发送0X00复位命令nand_cmd(0x00);

3)      等待RnB状态是否就绪 nand_wait_idle();

4)      取消片选 nand_deselect();

2.3Nand Flash读数据时序图:

从上图可以看出nand flash 读数据分为了以下几个步骤:

(1)      使能片选nCE

(2)      发送读命令0X00

(3)      发送地址(分为5个周期)

(4)      发送读命令0X30

(5)     等待RnB信号为高电平

(6)     读数据

(在同一页里,数据可以连续读,读下一页时,需要重新发送新的地址才行例如:读1000地址到2050地址时,

1.发出1000地址,到达页0的1000地址上,然后再连续读(2048-1000)次,直到读到页0的2047处.

2.再发出2048地址,到达页1的0地址上,然后连续读(2051-2048)次,直到读到2050为止)

(7)     取消片选nCE

2.4 所以nand_read()函数如下:

void nand_read(unsigned int  src,unsigned char  *dest,unsigned int  len)
/* src:源地址,为32位地址,所以用unsigend int表示
*dest:目的地址内容,由于这里是将数据读出到目的地址内容中,所以需要用到*指针,因为每个地址里存的是一个字节,所以用unsigend char 型    */
{

int col=src%2048;      //第一次读,可能不是读的页首地址,所以需要记录当前页的位置

int i=0;                //当前读了0次

nand_select();           //1使能片选nCE     

while(i<len)

 { nand_cmd(0X00);        //2发送读命令0X00  

   nand_write_addr(src);     // 3发送yuan地址(分为5个周期)

   nand_cmd(0X30);        //4发送读命令0X30    

   nand_wait_idle();       //5等待RnB信号为高电平

   for(;(col<2048)&&(i<len);col++)      //连续读页内数据

   {dest[i]=nand_read_data();            //6.读数据

    i++;                src++;}

    col=0;}

    nand_deselect();                // 取消片选nCE
 
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏比原链

剥开比原看代码17:比原是如何显示交易的详细信息的?

Gitee地址:https://gitee.com/BytomBlockchain/bytom

691
来自专栏崔庆才的专栏

JavaScript加密逻辑分析与Python模拟执行实现数据爬取

本节来说明一下 JavaScript 加密逻辑分析并利用 Python 模拟执行 JavaScript 实现数据爬取的过程。在这里以中国空气质量在线监测分析平台...

6166
来自专栏日常学python

如何爬取asp动态网页?搞定可恶的动态参数,这一文告诉你!

这个asp网站是我的学校的电费查询系统,需要学校的内网才能查询,所以这文说下思路和我遇到的一些坑。我搞这个网站主要是为了方便查电费而已,其实也方便不了多少。而且...

1873
来自专栏从零开始学自动化测试

python接口自动化21-规范的API接口文档示例

前言 接口文档到底长啥样?做接口测试最大的障碍在于没有接口文档,很多公司不注重接口文档的编写,导致测试小伙伴没见过接口文档。 运气好一点的测试小伙伴可能厚着脸皮...

1.1K8
来自专栏程序员的SOD蜜

单数据库,多数据库,单实例,多实例不同情况下的数据访问效率测试

最近公司的项目准备优化一下系统的性能,希望在数据库方面看有没有提升的空间,目前压力测试发现数据库服务器压力还不够大,Web服务器压力也不是很大的情况下,前台页面...

23510
来自专栏小樱的经验随笔

CTF---Web入门第五题 貌似有点难

貌似有点难分值:20 来源: 西普学院 难度:难 参与人数:7249人 Get Flag:2519人 答题人数:2690人 解题通过率:94% 不多说,去看题目...

2956
来自专栏FreeBuf

网站管理软件 – AspxSpy2014 Final

受bin牛委托修改并发布,版权归bin牛所有。 Bug/建议提交:zcgonvh@rootkit.net.cn 祝各位马年大吉,财源滚滚。 免责声明: 本程序只...

2859
来自专栏张戈的专栏

Linux运维基础技能: 接入层与网络基础

本系列文章一共三篇,分别为《脚本编程与 Linux 命令》、《接入层与网络基础》和《 MySQL 与 SQL 优化》,由腾讯高级工程师 luaruan(阮永顺)...

1052
来自专栏游戏开发那些事

【游戏开发】基于VS2017的OpenGL开发环境搭建

  最近,马三买了两本有关于“计算机图形学”的书籍,准备在工作之余鼓捣鼓捣图形学和OpenGL编程,提升自己的价值(奔着学完能涨一波工资去的)。俗话说得好,“工...

1563
来自专栏安恒网络空间安全讲武堂

MOCTF WEB 题解

0x00 MOCTF平台是CodeMonster和Mokirin这两支CTF战队所搭建的一个CTF在线答题系统。网址是http://www.moctf.com/...

7099

扫码关注云+社区