129 发出命令0x90 NFCMMD=0X90 mw.b 0x4E000008 0x90
130 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
131 读出数据得到0XEC val=NFDATA md.b 0x4E000010 1
132 读数据得到device code val=NFDATA md.b 0x4E000010 1
133 退出读ID状态 NFCMMD=0xff mw.b 0x4E000008 0xff
134
135 2.读内容 读0地址的数据
136 输入命令: nand dump 0 得到nand
137
138 选中 NFCONT的bit1设为0 md.1 0x4E000004 1; mw.1 0x4e000004 1
139 发出命令0x00 NFCMMD=0X00 mw.b 0x4E000008 0x00
140
141 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
142 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
143 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
144 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
145 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
146
147 发出命令0x30 NFCMMD=0X00 mw.b 0x4E000008 0x30
148
149 //接下来就是从0地址开始一个字节一个字节的读出数据,和前面nand dump 0 的数据一样
150 读出数据得到0x17 val=NFDATA md.b 0x4E000010 1
151 读出数据得到0x00 val=NFDATA md.b 0x4E000010 1
152 读出数据得到0x00 val=NFDATA md.b 0x4E000010 1
153
154 退出读状态 NFCMMD=0xff mw.b 0x4E000008 0xff
155
156 3.NAND flash 驱动层次 Atmel_nand.c Mtdchar.c
157 块设备: 知道怎么优化
158 NAND Flash协议:知道发什么来读写,擦除,识别
159 硬件相关: 知道怎样发命令/地址,读写数据
160
161 硬件相关:
162 ①分配nand_chip 结构体
163 ②设置nand_chip
164 ③硬件相关设备
165 ④使用 nand_scan / add_mtd_partitions
166
167
168 4.ECC校验码 64byte的OOB内存
169 flash每一页都有64B不参与编址,被称为OOB(out of bank)
170 原因是,nand flash的内存中,数据很容易发生位反转,为了防止数据出错,引入了ECC校验,
171 解决:①写一页的数据 ②用这一页的内容生成ECC校验码 ③把ECC校验码写入OOB中
172 读取:①读page ②读OOB里的ECC ③根据page的内容算ECC
173 ④将算的ECC校验码和读取OOB中的校验码进行校验和校准,可以算出哪一位发生错误。
174 ECC校验码生成:可以硬件也可以软件
175
176 */
四、增加分区挂接
要增加分区的话,首先要定义mtd_partition结构体,里面定义了分区的名字,起始地址,以及分区的大小等参数。
1 //定义nand flash的分区
2 static struct mtd_partition lhy_nand_part[] = {
3 [0] = {
4 .name = 'bootloader',
5 .size = 0x40000,
6 .offset = 0,
7 },
8 [1] = {
9 .name = 'params',
10 .offset = MTDPART_OFS_APPEND, //大小紧跟真前面这个分区
11 .size = 0x20000,
12 },
13 [2] = {
14 .name = 'kernel',
15 .offset = MTDPART_OFS_APPEND, //大小紧跟真前面这个分区
16 .size = 0x200000,
17 },
18 [3] = {
19 .name = 'root',
20 .offset = MTDPART_OFS_APPEND,
21 .size = MTDPART_SIZ_FULL, //剩余的所有大小
22 },
23 };
接着就是在init函数中添加分区结构体。
1 /* 5.add_mtd_partitions 添加分区 */
2 //如果想整块flash只作为一个分区,使用add_mtd_device就够了
3 //add_mtd_device(lhy_mtd);
4 //如果要创建多个分区的话,那么就要使用add_mtd_partitions
5 add_mtd_partitions(lhy_nand_mtd, lhy_nand_part, 3);
附上驱动程序nand_flash4.c
1 /*
2 * 参考:linux-2.6.31driversmtdnands3c2410.c atmel_nand.c
3 */
4
5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 17 //寄存器结构体 18 struct lhy_nand_regs{ 19 unsigned long NFCONF ; //偏移地址: S3C2410_NFREG(0x00) 20 unsigned long NFCONT ; //偏移地址: S3C2410_NFREG(0x04) 21 unsigned long NFCMD ; //偏移地址: S3C2410_NFREG(0x08) 22 unsigned long NFADDR ; //偏移地址: S3C2410_NFREG(0x0C) 23 unsigned long NFDATA ; //偏移地址: S3C2410_NFREG(0x10) 24 unsigned long NFECCD0 ; //偏移地址: S3C2410_NFREG(0x14) 25 unsigned long NFECCD1 ; //偏移地址: S3C2410_NFREG(0x18) 26 unsigned long NFECCD ; //偏移地址: S3C2410_NFREG(0x1C) 27 unsigned long NFSTAT ; //偏移地址: S3C2410_NFREG(0x20) 28 unsigned long NFESTAT0 ; //偏移地址: S3C2410_NFREG(0x24) 29 unsigned long NFESTAT1 ; //偏移地址: S3C2410_NFREG(0x28) 30 unsigned long NFMECC0 ; //偏移地址: S3C2410_NFREG(0x2C) 31 unsigned long NFMECC1 ; //偏移地址: S3C2410_NFREG(0x30) 32 unsigned long NFSECC ; //偏移地址: S3C2410_NFREG(0x34) 33 unsigned long NFSBLK ; //偏移地址: S3C2410_NFREG(0x38) 34 unsigned long NFEBLK ; //偏移地址: S3C2410_NFREG(0x3C) 35 }; 36 37 static struct nand_chip *lhy_nand; 38 static struct mtd_info *lhy_mtd; //定义一个mtd_info结构体 39 static struct lhy_nand_regs *lhy_nand_res; //定义寄存器的结构体指针 40 41 //定义nand flash的分区 42 static struct mtd_partition lhy_nand_part[] = { 43 [0] = { 44 .name = 'bootloader', 45 .size = 0x40000, 46 .offset = 0, 47 }, 48 [1] = { 49 .name = 'params', 50 .offset = MTDPART_OFS_APPEND, //大小紧跟真前面这个分区 51 .size = 0x20000, 52 }, 53 [2] = { 54 .name = 'kernel', 55 .offset = MTDPART_OFS_APPEND, //大小紧跟真前面这个分区 56 .size = 0x200000, 57 }, 58 [3] = { 59 .name = 'root', 60 .offset = MTDPART_OFS_APPEND, 61 .size = MTDPART_SIZ_FULL, //剩余的所有大小 62 }, 63 }; 64 65 /* 芯片选择 */ 66 static void lhy_select_chip(struct mtd_info *mtd,int chipnr) 67 { 68 if(chipnr == -1){ 69 /* 取消选中,NFCONT[1]设为0 */ 70 lhy_nand_regs->NFCONT |= (1<<1); 71 }else{ 72 /* 选中:NFCONT[1]设为1 */ 73 lhy_nand_regs->NFCONT &= ~(1<<1); 74 } 75 } 76 //发送命令,地址,数据 77 static void lhy_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) 78 { 79 if (ctrl & NAND_CLE){ 80 /* 发命令 : NFCMMD=dat*/ 81 lhy_nand_regs->NFCMD = cmd; 82 }else{ 83 writeb(cmd, host->io_base + (1 << host->board->ale)); 84 lhy_nand_regs->NFADDR = cmd; 85 } 86 } 87 //判断状态 88 static int lhy_dev_ready(struct mtd_info *mtd) 89 { 90 return (lhy_nand_regs->NFSTAT & (1<<0)); 91 } 92 93 static int lhy_nand_init(void){ 94 95 /* 1.分配一个nand_chip结构体 */ 96 lhy_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); 97 98 lhy_nand_regs = ioremap(0x4E000000,sizeof(struct lhy_nand_regs)); //映射寄存器 99 /* 2.设置 */ 100 /* 2.1设置nand_chip是给nand_scan函数用的,如果不知道怎么设置,先看nand_scan怎么用 101 * 它应该提供:选中,发命令,发地址,发数据,读数据,判断状态等功能 102 */ 103 lhy_nand->select_chip = lhy_select_chip; //选中,芯片选择函数
上一篇:S3C实现DMA驱动程序编写
下一篇:GNU μC/OS-II 在 S3C2440 上中断的实现
推荐阅读最新更新时间:2026-03-23 08:59
- LDK120M12R 1.2V低压降稳压器典型应用(可调版)电路
- EVB-UTC2000-DFP、EVK-UTC2000 评估套件基于 UTC2000 USB 3.0/2.0 Type-A,即插即用 Type-C DFP
- LTC3219 演示板、250mA 通用九通道 LED 驱动器
- DC919A-D,LTC2204 CMOS 输出演示板,直流输入,40Msps 16 位 ADC,DC
- AD8618ARZ-REEL 二阶低通滤波器运算放大器的典型应用电路
- 使用 NXP Semiconductors 的 PCA9511A 的参考设计
- LT3091MPDE 恒流恒压实验室电源的典型应用
- ADR392B 4.096 Vout 微功率、低噪声精密电压基准的典型应用
- LT3470HDDB 5V 降压转换器的典型应用电路
- 使用 Diodes Incorporated 的 AZ7042ZTR-E1 的参考设计



Linux技术手册
智能机械臂
非常经典的关于LLC的杨波博士论文
XC6406PP60DL






京公网安备 11010802033920号