127 发出命令0x90 NFCMMD=0X90 mw.b 0x4E000008 0x90
128 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
129 读出数据得到0XEC val=NFDATA md.b 0x4E000010 1
130 读数据得到device code val=NFDATA md.b 0x4E000010 1
131 退出读ID状态 NFCMMD=0xff mw.b 0x4E000008 0xff
132
133 2.读内容 读0地址的数据
134 输入命令: nand dump 0 得到nand
135
136 选中 NFCONT的bit1设为0 md.1 0x4E000004 1; mw.1 0x4e000004 1
137 发出命令0x00 NFCMMD=0X00 mw.b 0x4E000008 0x00
138
139 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
140 发出地址0x00 NFADD=0X00 mw.b 0x4E00000c 0x00
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
145 发出命令0x30 NFCMMD=0X00 mw.b 0x4E000008 0x30
146
147 //接下来就是从0地址开始一个字节一个字节的读出数据,和前面nand dump 0 的数据一样
148 读出数据得到0x17 val=NFDATA md.b 0x4E000010 1
149 读出数据得到0x00 val=NFDATA md.b 0x4E000010 1
150 读出数据得到0x00 val=NFDATA md.b 0x4E000010 1
151
152 退出读状态 NFCMMD=0xff mw.b 0x4E000008 0xff
153
154 3.NAND flash 驱动层次 Atmel_nand.c Mtdchar.c
155 块设备: 知道怎么优化
156 NAND Flash协议:知道发什么来读写,擦除,识别
157 硬件相关: 知道怎样发命令/地址,读写数据
158
159 硬件相关:
160 ①分配nand_chip 结构体
161 ②设置nand_chip
162 ③硬件相关设备
163 ④使用 nand_scan / add_mtd_partitions
164
165
166 */
三、增加ECC校验码
前面的程序是可以直接用的,但是加载驱动时会报ECC校验错误。
在flash设备中,每一页都有64b是不参与编址的,这一块是不参与统一编址OBB(out of bank)。
原因:nand flash内存中,数据很容易发生位反转,为了防止数据发生错误,引入了ECC校验。
解决方案:写一页数据时,这一页的数据生成ECC校验码,然后把ECC校验码写入OBB中。
读取数据时:首先读取page,读OOB里的ECC,根据page的内容实时计算ECC,看是否与OOB中的
ECC相同,若是相同则说明数据没有错误,否则通过ECC校验码也可以算出是哪一位发生错误。
实现方法:可以设置为软件实现或者硬件实现,只要在nand_chip中的ECC结构体的mode中设置为NAND_ECC_SOFT,就是开启了软件ECC校验。
nand_chip->ecc.mode = NAND_ECC_SOFT; /*使能ECC校验码 enable ECC */
附上驱动程序nand_flash3.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 /* 芯片选择 */ 42 static void lhy_select_chip(struct mtd_info *mtd,int chipnr) 43 { 44 if(chipnr == -1){ 45 /* 取消选中,NFCONT[1]设为0 */ 46 lhy_nand_regs->NFCONT |= (1<<1); 47 }else{ 48 /* 选中:NFCONT[1]设为1 */ 49 lhy_nand_regs->NFCONT &= ~(1<<1); 50 } 51 } 52 //发送命令,地址,数据 53 static void lhy_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) 54 { 55 if (ctrl & NAND_CLE){ 56 /* 发命令 : NFCMMD=dat*/ 57 lhy_nand_regs->NFCMD = cmd; 58 }else{ 59 writeb(cmd, host->io_base + (1 << host->board->ale)); 60 lhy_nand_regs->NFADDR = cmd; 61 } 62 } 63 //判断状态 64 static int lhy_dev_ready(struct mtd_info *mtd) 65 { 66 return (lhy_nand_regs->NFSTAT & (1<<0)); 67 } 68 69 static int lhy_nand_init(void){ 70 71 /* 1.分配一个nand_chip结构体 */ 72 lhy_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL); 73 74 lhy_nand_regs = ioremap(0x4E000000,sizeof(struct lhy_nand_regs)); //映射寄存器 75 /* 2.设置 */ 76 /* 2.1设置nand_chip是给nand_scan函数用的,如果不知道怎么设置,先看nand_scan怎么用 77 * 它应该提供:选中,发命令,发地址,发数据,读数据,判断状态等功能 78 */ 79 lhy_nand->select_chip = lhy_select_chip; //选中,芯片选择函数 80 lhy_nand->cmd_ctrl = lhy_nand_cmd_ctrl; //负责发送地址,命令 81 lhy_nand->IO_ADDR_R = lhy_nand_regs->NFDATA; //读寄存器 82 lhy_nand->IO_ADDR_W = lhy_nand_regs->NFDATA; //写寄存器 83 lhy_nand->dev_ready = lhy_dev_ready; //判断状态 84 nand_chip->ecc.mode = NAND_ECC_SOFT; /*使能ECC校验码 enable ECC */ 85 86 /* 3.硬件相关的操作 根据nand flash的手册设置时间参数 87 * HCLK = 100MHz 88 * TACLS: 发出CLE/ALE之后多长时间发出nWE信号,从NAND手册可知CLE/ALE与nWE可以同时发出,所以TACLS=0 89 * TWRPH0: nWE的信号的脉冲宽度,HCLK *(TWPRH0 + 1),从NAND手册可知它要>=12ns,所以TWRPH0>=1 90 * TWRPH1:表示nWE信号变为高电平后,CLE/ALE多长时间才能变为低电平,从手册可知他要>=5ns,所以TWRPH1>=0 91 */ 92 #define TACLS 0 93 #define TWRPH0 1 94 #define TWRPH1 0 95 lhy_nand_regs->NFCONF |= (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4); 96 97 /* NFCONT的bit1设为1,表示片 选 */ 98 lhy_nand_regs->NFCONT = (1<<1) | (1<<0); 99 /* 4.使用nand_scan */ 100 lhy_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); 101 lhy_mtd->priv = lhy_nand; //私有数据为我们的nand_chip结构体 102 lhy_mtd->owner = THIS_MODULE; 103 104 nand_scan(lhy_mtd,1); //扫描识别nand flash,并且构造mtd,最大芯片个数为1 105 /* 5.add_mtd_partitions 添加分区 */ 106 //add_mtd_partitions(tiny_nand_mtd, tiny_nand_part, 3); 107 return 0; 108 } 109 110 static void lhy_nand_exit(void){ 111 if(lhy_nand) 112 kfree(lhy_nand); 113 if(lhy_mtd) 114 kfree(lhy_mtd); 115 if(lhy_nand_regs) 116 iounmap(lhy_nand_regs); 117 } 118 119 module_init(lhy_nand_init); 120 module_exit(lhy_nand_exit); 121 MODULE_LICENSE('GPL'); 122 123 124 /* 125 S3C2440 U-BOOT 的NAND操作 126 127 1.读取ID 128 选中 NFCONT的bit1设为0 md.1 0x4E000004 1; mw.1 0x4e000004 1
上一篇:S3C实现DMA驱动程序编写
下一篇:GNU μC/OS-II 在 S3C2440 上中断的实现
- 热门资源推荐
- 热门放大器推荐
- 用于有线网络的 400V 交流转直流单输出电源
- 具有集成升压和捕捉二极管的 LT3470ITS8 微功率降压稳压器的典型应用电路
- LT6656BIDC-2.048、2.048V ADC 电压基准和桥式励磁电源的典型应用
- LT6656BIDC-2.048、2.048V 低功率精密高压电源监视器的典型应用
- 具有 BFU730F 应用电路的 2.4 - 5.9GHz 宽带 Wi-Fi LNA
- AD5302 双路 8 位缓冲数模转换器的典型应用
- TWR-KV46F150M,用于 MKV46F256 Kinetis KV4x 系列 MCU 的塔式系统模块
- LTC3622IMSE 5V/3.3V Vout 突发模式操作应用同步降压稳压器的典型应用电路
- S8VS-09024A 24V/90W AC/DC电源典型应用
- 使用 ON Semiconductor 的 KA7809E 的参考设计



非常经典的关于LLC的杨波博士论文
6884-700

XC6406PP60DL






京公网安备 11010802033920号