NAND Flash驱动

Posted lilto

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NAND Flash驱动相关的知识,希望对你有一定的参考价值。

硬件原理及分析

管脚说明

技术图片

? ?

? ?

Pin Name

Pin Function

R/B(RnB)

The R/B output indicates the status of the device operation. When low, it indicates that a program, erase or random read

operation is in process and returns to high state upon completion. It is an open drain output and does not float to high-z condition when the chip is deselected or when outputs are disabled.

CLE(CLE)

The CLE input controls the activating path for commands sent to the command register. When active high, commands are

latched into the command register through the I/O ports on the rising edge of the WE signal.

CE(nFCE)

The CE input is the device selection control. When the device is in the Busy state, CE high is ignored, and the device does

not return to standby mode in program or erase operation.

ALE(ALE)

The ALE input controls the activating path for address to the internal address registers. Addresses are latched on the rising

edge of WE with ALE high.

WE(nFWE)

The WE input controls writes to the I/O port. Commands, address and data are latched on the rising edge of the WE pulse.

RE(nFRE)

The RE input is the serial data-out control, and when active drives the data onto the I/O bus. Data is valid tREA after the falling

edge of RE which also increments the internal column address counter by one.

I/O(LDATA0-LDATA7)

The I/O pins are used to input command, address and data, and to output data during read operations. The I/O pins float to

high-z when the chip is deselected or when the outputs are disabled.

? ?

在U-BOOT上操作Nand Flash

NAND FLASH S3C2440

发命令 选中芯片

CLE设为高电平 NFCMMD=命令值

在DATA0~DATA7上输出命令值

发出一个写脉冲

?

发地址 选中芯片 NFADDR=地址值

ALE设为高电平

在DATA0~DATA7上输出地址值

发出一个写脉冲

? ?

发数据 选中芯片 NFDATA=数据值

ALE,CLE设为低电平

在DATA0~DATA7上输出数据值

发出一个写脉冲

? ?

读数据 选中芯片 val=NFDATA

发出读脉冲

读DATA0~DATA7的数据

? ?

?

OpenJTAG> help md

md [.b, .w, .l] address [# of objects]

- memory display

? ?

OpenJTAG> help mw

mw [.b, .w, .l] address value [count]

- write memory

?b????????1字节

?W????????2字节

?l????????4字节

?

? ?

1. 读ID

S3C2440

u-boot

选中 NFCONT的bit1设为0

md.l 0x4E000004 1; mw.l 0x4E000004 1

发出命令0x90 NFCMMD=0x90

mw.b 0x4E000008 0x90

发出地址0x00 NFADDR=0x00

mw.b 0x4E00000C 0x00

读数据得到0xEC val=NFDATA

md.b 0x4E000010 1

读数据得到device code val=NFDATA

md.b 0x4E000010 1

退出读ID的状态 NFCMMD=0xff

mw.b 0x4E000008 0xff

?

2. 读内容: 读0地址的数据

使用UBOOT命令:

nand dump 0

Page 00000000 dump:

17 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5

? ?

S3C2440

u-boot

选中 NFCONT的bit1设为0

md.l 0x4E000004 1; mw.l 0x4E000004 1

发出命令0x00 NFCMMD=0x00

mw.b 0x4E000008 0x00

发出地址0x00 NFADDR=0x00

mw.b 0x4E00000C 0x00

发出地址0x00 NFADDR=0x00

mw.b 0x4E00000C 0x00

发出地址0x00 NFADDR=0x00

mw.b 0x4E00000C 0x00

发出地址0x00 NFADDR=0x00

mw.b 0x4E00000C 0x00

发出地址0x00 NFADDR=0x00

mw.b 0x4E00000C 0x00

发出命令0x30 NFCMMD=0x30

mw.b 0x4E000008 0x30

读数据得到0x17 val=NFDATA

md.b 0x4E000010 1

读数据得到0x00 val=NFDATA

md.b 0x4E000010 1

读数据得到0x00 val=NFDATA

md.b 0x4E000010 1

读数据得到0xea val=NFDATA

md.b 0x4E000010 1

退出读状态 NFCMMD=0xff

mw.b 0x4E000008 0xff

? ?

ECC的作用

技术图片?

?技术图片

?

S3C2440-Nand Flash Controller Register

技术图片?

技术图片技术图片

技术图片技术图片技术图片技术图片技术图片技术图片技术图片技术图片

? ?

S3C2440-Nand Flash Memory Timing

技术图片

? ?

K9F2G08U0C-Key Characteristic

技术图片技术图片技术图片

? ?

K9F2G08U0C-Operation Timing

技术图片

技术图片技术图片

? ?

? ?

驱动程序

driver.c

1 /*
2 * SAMSUNG: K9F2G08U0C
3 * 参考:
4 * .linux-2.6.22.6driversmtd ands3c2410.c
5 * .linux-2.6.22.6driversmtd andat91_nand.c
6 */
7 #include <linux/module.h>
8 #include <linux/types.h>
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/string.h>
12 #include <linux/ioport.h>
13 #include <linux/platform_device.h>
14 #include <linux/delay.h>
15 #include <linux/err.h>
16 #include <linux/slab.h>
17 #include <linux/clk.h>
18 ????????
19 #include <linux/mtd/mtd.h>
20 #include <linux/mtd/nand.h>
21 #include <linux/mtd/nand_ecc.h>
22 #include <linux/mtd/partitions.h>
23 ????????
24 #include <asm/io.h>
25 ????????
26 #include <asm/arch/regs-nand.h>
27 #include <asm/arch/nand.h>
28
29 struct regs_nand {
30 ????????unsigned long ????????NFCONF;????????????????
31 ????????unsigned long????????NFCONT; ????????????????
32 ????????unsigned long????????NFCMMD; ????????????????
33 ????????unsigned long????????NFADDR; ????????????????
34 ????????unsigned long????????NFDATA;
35 ????????unsigned long????????NFMECCD0;
36 ????????unsigned long????????NFMECCD1;
37 ????????unsigned long????????NFSECCD;
38 ????????unsigned long????????NFSTAT;
39 ????????unsigned long????????NFESTAT0; ????????
40 ????????unsigned long????????NFESTAT1;
41 ????????unsigned long????????NFMECC0;????????????????
42 ????????unsigned long????????NFMECC1;????????????????????????
43 ????????unsigned long????????NFSECC; ????????????????
44 ????????unsigned long????????NFSBLK; ????????????????
45 ????????unsigned long????????NFEBLK;
46 };
47
48 static struct nand_chip *nand;
49 static struct mtd_info *mtd;
50 static struct regs_nand *regs_nand;
51
52 //分区信息
53 static struct mtd_partition nand_parts[] = {
54 ????????[0] = {
55 ????????????????.name ????????= "bootloader",????????????????????????
56 ????????????????.size ????????= 0x00040000,????????????????????????
57 ????????????????.offset = 0,????????????????????????????????????????/* offset within the master MTD space */
58 ????????},
59
60 ????????[1] = {
61 ????????????????.name ????????= "params",????????????????????????
62 ????????????????.offset = MTDPART_OFS_APPEND,????????//紧跟着上一个分区的大小
63 ????????????????.size ????????= 0x00020000,????????????????????????
64 ????????},
65
66 ????????[2] = {
67 ????????????????.name ????????= "kernel",????????????????????????????????
68 ????????????????.offset = MTDPART_OFS_APPEND,????????//紧跟着上一个分区的大小
69 ????????????????.size ????????= 0x00200000,????????????????????????
70 ????????},
71
72 ????????[3] = {
73 ????????????????.name ????????= "root",????????????????????????????????
74 ????????????????.offset = MTDPART_OFS_APPEND,????????//紧跟着上一个分区的大小
75 ????????????????.size ????????= MTDPART_SIZ_FULL,????????????????
76 ????????},
77 };
78
79 static void nand_select_chip(struct mtd_info *mtd, int chipnr)
80 {
81 ????????if (chipnr == -1)
82 ????????{
83 ????????????????//取消选中:NFCONT[1]:0
84 ????????????????regs_nand->NFCONT |= (1<<1);
85 ????????}
86 ????????else {
87 ????????????????//选中:NFCONT[1]:1
88 ????????????????regs_nand->NFCONT &= ~(1<<1);
89 ????????}
90 ????????return;
91 }
92
93 static void nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
94 {
95 ????????if (ctrl & NAND_CLE)
96 ????????{
97 ????????????????//发命令:NFCMMD=dat
98 ????????????????regs_nand->NFCMMD = dat;
99 ????????}
100 ????????else
101 ????????{
102 ????????????????//发地址:NFADDR=dat
103 ????????????????regs_nand->NFADDR = dat;
104 ????????}
105 ????????return;
106 }
107
108 static int nand_dev_ready(struct mtd_info *mtd)
109 {
110 ????????return (regs_nand->NFSTAT & (1<<0));
111 }
112
113
114 /* 1 出、入口函数 */
115 static int __init nand_init(void)
116 {
117 ????????struct clk *clk;
118
119 ????????/* 2 分配一个nand_chip结构体 */
120 ????????nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
121 ????????/******** 2 end ********/
122
123 ????????regs_nand = ioremap(0x4E000000, sizeof(struct regs_nand));
124
125 ????????/* 3 设置:nand_chip */
126 ????????//提供:选中、发命令、发地址、发数据、读数据、判断状态的功能
127 ????????nand->select_chip ????????= nand_select_chip;????????????????//片选
128 ????????nand->cmd_ctrl????????????????= nand_cmd_ctrl;????????????????//发命令
129 ????????nand->IO_ADDR_R????????????????= &regs_nand->NFDATA;????????//读
130 ????????nand->IO_ADDR_W????????????????= &regs_nand->NFDATA;????????//写
131 ????????nand->dev_ready????????????????= nand_dev_ready;????????????????//Flash 状态(忙/空闲)
132 ????????nand->ecc.mode????????????????= NAND_ECC_SOFT;????????????????//ecc软件校验
133 ????????/******** 3 end ********/
134
135 ????????/* 4 硬件相关的操作:时序 */
136 ????????//使能时钟
137 ????????clk = clk_get(NULL, "nand");
138 ????????clk_enable(clk);
139 ????????
140 #define TACLS????????0
141 #define TWRPH0????????1
142 #define TWRPH1????????0
143 ????????//时间参数设置
144 ????????regs_nand->NFCONF????????= (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
145
146 ????????//控制---使能nand flash控制器,取消片选
147 ????????regs_nand->NFCONT????????= (1<<0) | (1<<1);
148 ????????/******** 4 end ********/
149 ????????
150
151 ????????/* 5 使用:nand_scan */
152 ????????mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
153 ????????mtd->owner????????= THIS_MODULE;
154 ????????mtd->priv????????= nand;????????????????//私有数据
155 ????????
156 ????????nand_scan(mtd, 1);????????????????//识别nand_flash,构造mtd_info结构体
157 ????????/******** 5 end ********/
158
159
160 ????????/* 6 添加分区:add_mtd_partitions */
161 ????????add_mtd_partitions(mtd, nand_parts, 4);
162
163 ????????//不分区的情形
164 ????????//add_mtd_device(mtd);
165 ????????/******** 6 end ********/
166
167 ????????return 0;
168 }
169
170 static void __exit nand_exit(void)
171 {
172 ????????del_mtd_partitions(mtd);
173 ????????kfree(nand);
174 ????????kfree(mtd);
175 ????????iounmap(regs_nand);
176 ????????return;
177 }
178
179 module_init(nand_init);
180 module_exit(nand_exit);
181 MODULE_LICENSE("GPL");
182 /******** 1 end ********/

?

Makefile

1 KERN_DIR = /work/system/linux-2.6.22.6
2
3 all:
4 ????????make -C $(KERN_DIR) M=`pwd` modules
5

6 clean:
7 ????????make -C $(KERN_DIR) M=`pwd` modules clean
8
????????rm -rf modules.order

9
10 obj-m????????+= nand_drv.o

? ?

? ?

? ?

调试

pc-linux:

//格式化工具

tar xjf mtd-utils-05.07.23.tar.bz2

cd mtd-utils-05.07.23/util

修改Makefile:

#CROSS=arm-linux-

改为

CROSS=arm-linux-

make

cp flash_erase flash_eraseall /work/nfs_root/fs_mini/bin/

//格式化工具-----end

? ?

board-uboot:

nfs 30000000 192.168.0.103:/work/nfs_root/uImage_f

//使用NFS作为根文件系统

set bootargs console=ttySAC0 root=/dev/nfs nfsroot=192.168.0.103:/work/nfs_root/fs_mini ip=192.168.0.33:192.168.0.103:192.168.0.1:255.255.255.0::eth0:off

bootm 30000000

? ?

board-linux:

insmod nand_drv.ko

? ?

flash_eraseall /dev/mtd3 // yaffs //格式化

mount -t yaffs /dev/mtdblock3 /mnt //挂接

以上是关于NAND Flash驱动的主要内容,如果未能解决你的问题,请参考以下文章

Linux 下 Nand Flash 驱动说明

如何编写Linux下Nand Flash驱动

NAND Flash驱动

Linux-Nand Flash驱动(分析MTD层并制作NAND驱动)

Linux 下 Nand Flash 驱动主要数据结构说明

嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序