一、数据手册相关内容

1.地址传输周期

2.命令表

3.在寄存器中,会涉及TACLS,TWRPH0,TWRPH1的设定

这里我们就去看nandflash的数据手册

在这里我们可以清楚的看到,TACLS=TCLS-TWP,TWRPH0=TWP,TWRPH1=TCLH,从下表可以查到时间,并根据主频转换成CPU周期数

二、寄存器

1.NFCONF

这个寄存器的0-3位是硬件控制的,TACLS,TWRPH0,TWRPH1的值也可以怎么设定上面有讲

2.NFCONT

这个寄存器我们先只关心这两位,一个是使能nandflash控制器,一个是使能chip

3.NFCMMD,NFADDR,NFDATA

命令寄存器,地址寄存器,数据寄存器,往里面读取值就行了

4.NFSTAT

这个寄存器第0位表示nandflash是否在忙,1表示不忙可以操作

第2位表示往里面写1就是清除RnB标识位

三、裸机驱动

这个驱动主要实现简单的往nandflash里面进行初始化,擦除,写,读操作,其中第0块是保证不是坏块的,所以我们以此来测试,因为我没有JTAG线,在中间要监测某些值得话我是改成了Linux下面的驱动,用ioremap来操作nandflash,用printk来监测调试的,没有JLINK线确实挺蛋疼的,下面是在ADS下的代码

init.s

     AREA init, CODE, READONLY
ENTRY
IMPORT rNF_init
IMPORT rNF_ReadID
IMPORT rNF_Erase
IMPORT rNF_WritePage
IMPORT rNF_ReadPage
start
bl rNF_init
bl rNF_ReadID
mov r0,#
bl rNF_Erase  //擦除第0块
mov r0,#
bl rNF_WritePage  //写
mov r0,#
bl rNF_ReadPage  //读
loop    
b loop
END

nandflash.c

 #define rNFCONF  (*(volatile unsigned long *)0x4e000000)
#define rNFCONT (*(volatile unsigned long *)0x4e000004)
#define rNFCMMD (*(volatile unsigned long *)0x4e000008)
#define rNFADDR (*(volatile unsigned long *)0x4e00000c)
#define rNFDATA (*(volatile unsigned long *)0x4e000010)
#define rNFDATA8 (*(volatile unsigned char *)0x4e000010)
#define rNFSTAT (*(volatile unsigned long *)0x4e000020) #define CMD_READ_CYCLE1 0x00
#define CMD_READ_CYCLE2 0x30
#define CMD_READID 0x90
#define CMD_WRITE_CYCLE1 0x80
#define CMD_WRITE_CYCLE2 0x10
#define CMD_ERASE_CYCLE1 0x60
#define CMD_ERASE_CYCLE2 0xd0
#define CMD_STATUS 0x70
#define CMD_RESET 0xff  //这些命令都可以查表得到 #define NF_Chip_En() {rNFCONT &= ~(1<<1);} //Enable chip select
#define NF_Chip_Ds() {rNFCONT |= (1<<1);} //Disable chip select #define Wr_NF_Cmd(cmd) {rNFCMMD = (cmd);}  
#define Wr_NF_Addr(addr) {rNFADDR = (addr);} #define Wait_NF_Busy() {while(!(rNFSTAT & 1));} //等待系统不忙
#define DETECT_RB() {while(!(rNFSTAT & (1<<2)))} //RB位被检测到
#define NF_Clear_RB() {rNFSTAT |= (1<<2);} //清除RB位 #define NF_READ_DATA() (rNFDATA)  
#define NF_READ_DATA8() (rNFDATA8)  //读取一字节的数据 #define NF_WRITE_DATA(data) {rNFDATA = data;}
#define NF_WRITE_DATA8(data) {rNFDATA8 = data;} #define TACLS 1
#define TWRPH0 3
#define TWRPH1 0 #define U32 unsigned int
#define U16 unsigned short
#define U8 unsigned char

初始化:

 static void rNF_Reset()
{
NF_Chip_En();
NF_Clear_RB();
Wr_NF_Cmd(CMD_RESET);
Wait_NF_Busy();
NF_Chip_Ds();
} void rNF_init(void)
{
rNFCONF = (TACLS<<)|(TWRPH0<<)|(TWRPH1<<);
rNFCONT = (<<)|(<<)|(<<)|(<<)|(<<);
rNF_Reset();
}

ReadID:

 void delay(int num)
{
int i;
for(i=;i<num;i++);
} U8 rNF_ReadID()
{
U8 PMID,PDID,CYCLE3,CYCLE4,CYCLE5; NF_Chip_En();
NF_Clear_RB();
Wr_NF_Cmd(CMD_READID);
Wr_NF_Addr(0x0);
delay();
PMID = NF_READ_DATA8();
PDID = NF_READ_DATA8();
CYCLE3 = NF_READ_DATA8();
CYCLE4 = NF_READ_DATA8();
CYCLE5 = NF_READ_DATA8();
NF_Chip_Ds(); return PDID;
}

我们关心的是PDID,如果返回的PDID和数据手册一致,就表示nandflash设置没有什么问题了

擦除操作:

 U8 rNF_Erase(U32 block_num)
{
char state; NF_Chip_En();
NF_Clear_RB();
Wr_NF_Cmd(CMD_ERASE_CYCLE1);
Wr_NF_Addr((block_num<<) & 0xff);
Wr_NF_Addr((block_num>>) & 0xff);
Wr_NF_Addr((block_num>>) & 0xff);  //A18到A25,一次读取8位,注意移位
Wr_NF_Cmd(CMD_ERASE_CYCLE2);
delay();
Wr_NF_Cmd(CMD_STATUS); do
{
state = NF_READ_DATA8();
}while(!(state & 0x40)); NF_Chip_Ds();
return 0x66;  //0x66表示擦除成功了
}

写操作:

 U8 rNF_WritePage(U32 page_num)
{
int i;
char state; NF_Chip_En();
NF_Clear_RB();
Wr_NF_Cmd(CMD_WRITE_CYCLE1);
Wr_NF_Addr(0x00);
Wr_NF_Addr(0x00);          
Wr_NF_Addr(page_num & 0xff);
Wr_NF_Addr((page_num>>) & 0xff);
Wr_NF_Addr((page_num>>) & 0xff); for(i=;i<;i++)  //一页大小2KB
{
NF_WRITE_DATA8((char)(i+));
} Wr_NF_Cmd(CMD_WRITE_CYCLE2);
delay();
Wr_NF_Cmd(CMD_STATUS); do
{
state = NF_READ_DATA8();
}while(!(state & 0x40)); NF_Chip_Ds();
return 0x66;
}

读操作:

 void rNF_ReadPage(U32 page_num)
{
int i;
U8 buf[]; NF_Chip_En();
NF_Clear_RB();
Wr_NF_Cmd(CMD_READ_CYCLE1);
Wr_NF_Addr(0x00);
Wr_NF_Addr(0x00);
Wr_NF_Addr(page_num & 0xff);
Wr_NF_Addr((page_num>>) & 0xff);
Wr_NF_Addr((page_num>>) & 0xff);
Wr_NF_Cmd(CMD_READ_CYCLE2);
Wait_NF_Busy(); for(i=;i<;i++)
{
buf[i] = NF_READ_DATA8();
} NF_Chip_Ds();
}

TQ2440--nandflash(K9F2G08U0A)驱动编写的更多相关文章

  1. liunx中字符驱动编写的简单模板

    下面是关于字符驱动两个程序,主要是说明驱动编写的思想,理解驱动是怎么一步一步被实现的. 驱动的第一个实现程序,是相对于裸机编程的,主要是体会一下驱动编程思想: cdev.h: 所包含的头文件 #ifn ...

  2. AM335x(TQ335x)学习笔记——触摸屏驱动编写

    前面几篇文章已经通过配置DTS的方式完成了多个驱动的移植,接下来我们解决TQ335x的触摸驱动问题.由于种种原因,TQ335x的触摸屏驱动是以模块方式提供的,且Linux官方内核中也没有带该触摸屏的驱 ...

  3. Tiny4412之串口(Uart)驱动编写

    一:tiny4412串口驱动编写 1.串口通信简介 串口通信指串口按位(bit)发送和接收字节,串口通信的概念非常简单,串口按位(bit)发送和接收字节.尽管比按字节(byte)的并行通信慢,但是串口 ...

  4. Linux驱动之按键驱动编写(中断方式)

    在Linux驱动之按键驱动编写(查询方式)已经写了一个查询方式的按键驱动,但是查询方式太占用CPU,接下来利用中断方式编写一个驱动程序,使得CPU占有率降低,在按键空闲时调用read系统调用的进程可以 ...

  5. Linux驱动之按键驱动编写(查询方式)

    在Linux驱动之LED驱动编写已经详细介绍了一个驱动的编写过程,接着来写一个按键驱动程序,主要是在file_operations结构中添加了一个read函数.还是分以下几步说明 1.查看原理图,确定 ...

  6. Linux驱动:I2C驱动编写要点

    继续上一篇博文没讲完的内容“针对 RepStart 型i2c设备的驱动模型”,其中涉及的内容有:i2c_client 的注册.i2c_driver 的注册.驱动程序的编写. 一.i2c 设备的注册分析 ...

  7. Linux驱动:SPI驱动编写要点

    题外话:面对成功和失败,一个人有没有“冠军之心”,直接影响他的表现. 几周前剖析了Linux SPI 驱动框架,算是明白个所以然,对于这么一个庞大的框架,并不是每一行代码都要自己去敲,因为前人已经把这 ...

  8. ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程

    ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程 原文地址:http://www.cnblogs.com/NickQ/p/9026545.html 一.开发板与ds18b20的入门 ...

  9. v4l2驱动编写篇【转】

    转自:http://blog.csdn.net/michaelcao1980/article/details/53008418 大部分所需的信息都在这里.作为一个驱动作者,当挖掘头文件的时候,你可能也 ...

  10. nand flash详解及驱动编写

    https://www.crifan.com/files/doc/docbook/linux_nand_driver/release/html/linux_nand_driver.html#nand_ ...

随机推荐

  1. 201521123044 《Java程序设计》第12周学习总结

    1. 本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  2. 201521123114 《Java程序设计》第13周学习总结

    1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2. 书面作业 1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu. ...

  3. 201521123014 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 异常(Exception)处理 异常(Exception)的概念:在程序运行的时候可能出错,Java中把程序出现的错 ...

  4. Eclipse rap 富客户端开发总结(10) : Rap不同系统间的差异和处理方式

    平常进行 rap 程序开发一般都是在 win 下面完成 , 然后在 tomcat 下面测试 , 但是程序最终发布一般都是在 linux  aix 上面 , 这个时候就有能会出现一下问题,下面 2 个问 ...

  5. POJ--3258 River Hopscotch (最小值最大化C++)

    River Hopscotch Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15273   Accepted: 6465 ...

  6. HTTP第一篇

    为什么要学HTTP? 我们绝大多数的Web应用都是基于HTTP来进行开发的.我们对Web的操作都是通过HTTP协议来进行传输数据的. HTTP的诞生主要是为了能够让文档之间相互关联,形成超文本可以互相 ...

  7. JavaScript 基本语法结构

    1 变量 JavaScript的变量是弱类型的,就是所有的对象都是使用var 来进行声明 2 变量的命名规则 1.由字母.数字.下划线组成,区分大小写 2.以字母开头 3.变量名不能有空格 4.不能使 ...

  8. JVM菜鸟进阶高手之路十一(eden survivor分配问题)

    转载请注明原创出处,谢谢! 问题 这个Xmn设置为1G,,我用jmap -heap 看,这个Eden From To怎么不是一个整8:1:1的关系呢? 我看内存分配还是没变,我Xmn1g,感觉From ...

  9. vue 2 使用Bus.js进行兄弟(非父子)组件通信 简单案例

    vue2中废弃了$dispatch和$broadcast广播和分发事件的方法.父子组件中可以用props和$emit().如何实现非父子组件间的通信,可以通过实例一个vue实例Bus作为媒介,要相互通 ...

  10. oracle 表查询(二)

    1.使用逻辑操作符号问题:查询工资高于500或者是岗位为manager的雇员,同时还要满足他们的姓名首字母为大写的J?select * from emp where (sal > 500 or ...