本节来学习裸机下的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编码器值来判断读数据是否位反转,若位反转则重新读数据

写过程:

  • 1)写页数据
  • 2)然后生成ECC
  • 3)将ECC写入到OBB页地址里(写数据是不会出现位反转)

读过程:

  • 1)读出页数据,然后生成临时ECC(此时ECC可能有错)
  • 2)然后读出OOB页地址里的ECC
  • 3)比较两个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:写使能 ,比如写命令时,当CLE=1,ALE=0时,当nWE来个上升沿,则会将IO数据写入flash中
  • nRE:读使能,和we类似
  • 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<<)|(TWRPH0<<)|(TWRPH1<<); /* bit4=1:初始化ECC, bit1=1:禁止片选 bit0=1:启动nandflash控制器*/
NFCONT = (<<)|(<<)|(<<); }

2编写nand_read()函数

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

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

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

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

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

2.1.3读命令函数

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

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

nand_waite_idle()
{
int i;
while(!(NFSTAT&0X01)) // 等待NFSTAT寄存器位0置1
for(i=;i<;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 % ;
unsigned int page = addr / ;
volatile int i; NFADDR=(col>>)&0xff; //A7~A0,第1周期
for(i=;i<;i++); NFADDR=(col>>)&0x0f; //A10~A8,第2周期
for(i=;i<;i++); NFADDR=(page>>)&0xff; //A18~A11,第3周期
for(i=;i<;i++); NFADDR=(page>>)&0xff; //A26~A19,第4周期
for(i=;i<;i++); NFADDR=(page>>)&0xff; //A27~A28,第5周期
for(i=;i<;i++);
}

2.2Nand Flash命令图:

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


1)      使能片选nand_select();

2)      发送0XFF复位命令nand_cmd(0xFF);

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

4)      取消片选 nand_deselect();


2.3Nand Flash读数据时序图:

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


(1)      使能片选CE,将CLE置1,等待发送命令

(2)      将WE置低,将IO置为0X00,然后拉高WE,触发一次上升沿,则将把0x00写入flash中

(3)      将CLE置0,表示发送地址(分为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%; //第一次读,可能不是读的页首地址,所以需要记录当前页的位置 int i=; //当前读了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<)&&(i<len);col++) //连续读页内数据 {dest[i]=nand_read_data(); //6.读数据 i++;
src++;} col=;} nand_deselect(); // 取消片选nCE }

Nand Flash驱动(实现初始化以及读操作)的更多相关文章

  1. 如何编写linux下nand flash驱动-4

    2.       软件方面 如果想要在Linux下编写Nand Flash驱动,那么就先要搞清楚Linux下,关于此部分的整个框架.弄明白,系统是如何管理你的nand flash的,以及,系统都帮你做 ...

  2. Linux 下 Nand Flash 驱动说明

    注册 driver_register 通过 module_init(s3c2410_nand_init);注册 Nand Flash 驱动. 在 s3c2410_nand_init ()中通过 dri ...

  3. NAND FLASH 驱动分析

    NAND FLASH是一个存储芯片 那么: 这样的操作很合理"读地址A的数据,把数据B写到地址A" 问1. 原理图上NAND FLASH和S3C2440之间只有数据线,       ...

  4. 如何编写linux下nand flash驱动-2

    [Nand Flash引脚(Pin)的说明] 图3.Nand Flash引脚功能说明 上图是常见的Nand Flash所拥有的引脚(Pin)所对应的功能,简单翻译如下: 1.       I/O0 ~ ...

  5. 十八、Nand Flash驱动和Nor Flash驱动

    在读者学习本章之前,最好了解Nand Flash读写过程和操作,可以参考:Nand Flash裸机操作. 一开始想在本章写eMMC框架和设备驱动,但是没有找到关于eMMC设备驱动具体写法,所以本章仍继 ...

  6. NAND FLASH驱动框架以及程序实现

    1.NAND FLASH的硬件连接: 实验用的NAND FLASH芯片为K9F2G08U0C,它是三星公司的存储芯片,它的大小为256M.它的接线图如下所示: 它的每个引脚的分别为LDATA0-LDA ...

  7. Smart210学习记录----nand flash驱动

    [详解]如何编写Linux下Nand Flash驱动  :http://www.cnblogs.com/linux-rookie/articles/3016990.html 当读写文件请求到来的时候, ...

  8. linux下Pl353 NAND Flash驱动分析

    linux的NAND Flash驱动位于drivers/mtd/nand子文件夹下: nand_base.c-->定义通用的nand flash基本操作函数,如读写page,可自己重写这些函数 ...

  9. 15.1 linux操作系统下nand flash驱动框架2

    当我们需要在操作系统上读写普通文件的时候,总是需要一层层往下,最终到达硬件相关操作,当然底层设备大多数都是块设备 NAND FLASH就作为一个最底层的块设备. 而写驱动,就是要构建硬件与操作系统之间 ...

随机推荐

  1. SpringBoot填坑系列---XML方式配置数据库

    本次只是简单的运用SpringBoot搭建框架,对其原理并不做深入的探究 1.POM文件 <?xml version="1.0" encoding="UTF-8&q ...

  2. HDU 6097---Mindis(二分)

    题目链接 Problem Description The center coordinate of the circle C is O, the coordinate of O is (0,0) , ...

  3. RocketMQ入门

    本文首先引出消息中间件通常需要解决哪些问题,在解决这些问题当中会遇到什么困难,Apache RocketMQ作为阿里开源的一款高性能.高吞吐量的分布式消息中间件否可以解决,规范中如何定义这些问题.然后 ...

  4. 前端到后台ThinkPHP开发整站(3)

    继续我的这个项目的第三晚的开发了,时间比较少,今晚写的代码不多,今晚仍然是造轮子写一个公共的控制器和一个公共的JS.直接上代码吧! 以下是一个公共的控制器,后台控制器都继承于它,构造函数中进行验证当前 ...

  5. .NET定位CPU使用率过高问题

    摘要: 当一个.net应用在生产环境CPU突然居高不下,如何快速准确的定位问题所在,并且对实时业务影响最小化?如何不抓Dump也不用live debug就可以知道你的应用在做什么?如何确认你的应用是由 ...

  6. android学习ViewPager的简单使用

    使用ViewPager需要引入android.support.v4.View.ViewPager这样的jar包,谷歌公司为解决当前版本碎片化的问题,提供的兼容的包.主要目的就是解决向下兼容问题. 1, ...

  7. adb不是内部或外部命令

    1.安卓环境没配好, 2.tools下面没有adb.exe这个程序 3.2.3以后,adb.exe这个程序在platform-tools下而不是在tools下,所有环境变量的tools改成platfo ...

  8. 再起航,我的学习笔记之JavaScript设计模式10(单例模式)

    单例模式 单例模式(Singleton) : 又被称为单体模式,是只允许实例化一次的对象类.一个类有且仅有一个实例,并且自行实例化向整个系统提供. 命名空间 单例模式可能是JavaScript中我们最 ...

  9. 一个基于JRTPLIB的轻量级RTSP客户端——myRTSPClient详解

    myRTSPClient是一个轻量级的RTSP客户端C++函数库. 支持多平台,支持H264,H265,MPA等音视频传输. 免费开源,接口易用,配套教程与代码解析(本博客). 适合RTSP入门学习. ...

  10. quartz学习笔记(一)简单入门

    前言 quartz是Java编写的一款开源的任务调度开发框架,在项目开发中很多场景都可以用到,比如订单超期自动收货. 所谓程序源于生活,生活中也有很多场景可以用quartz来模拟,比如工作日早上七点起 ...