S3C2440 nand_flash驱动程序

发布者:快乐的旅程最新更新时间:2024-08-05 来源: cnblogs关键字:S3C2440  nand_flash  驱动程序 手机看文章 扫描二维码
随时随地手机看文章

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

[1] [2] [3] [4] [5]
关键字:S3C2440  nand_flash  驱动程序 引用地址:S3C2440 nand_flash驱动程序

上一篇:S3C实现DMA驱动程序编写
下一篇:GNU μC/OS-II 在 S3C2440 上中断的实现

小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved