S3C2440 nand_flash驱动程序

发布时间:2024-08-05  

一、一个简单的nand_flash驱动

1.定义nand_chip、mtd_info两个结构体

如上图所示:

nand_chip 结构体:是给nand_scan函数用的,而nand_scan函数提供了选中nand、发出命令、发出地址、发出数据、读取数据、判断状态等功能,所以nand_chip结构体上必须定义一系列实现上面功能能的函数,包括选中函数,负责发地址与命令的函数,以及判断状态的函数,最重要的就是io读取的虚拟地址。

mtd_info结构体:MTD(Memory Technology Device)即内存技术设在linux内核中,引入mtd层为NOR Flash和NAND Flash设备提供统一的接口,将文件系统于底层Flash存储设备进行了隔离。

MTD设备可以分为四层,从上到下依次为:设备节点层,MTD设备层,MTD原始设备层,Flash硬件驱动层。

Flash硬件驱动层:负责对Flash硬件的读、写和擦除操作。MTD设备的NAND flash芯片的驱动在drivers/mtd/nand目录下,nor flash芯片驱动位于drivers/mtd/chips目录下。

MTD原始设备层:用于描述MTD原始设备的数据结构体是mtd_info ,它定义了大量的关于MTD的数据和操作函数,其中mtdcore.c:实现原始设备接口的相关实现,mtdpart.c:实现mtd分区接口相关实现。

MTD设备层: 基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90),其中mtdchar.c实现mtd字符设备接口相关实现,mtdblock.c用于实现块设备接口相关实现。

设备节点层:通过mknode在/dev子目录下建立MTD块设备节点,通过此设备节点即可访问MTD字符设备和块设备。


2.在init函数中初始化结构体


 1 static int lhy_nand_init(void){

 2     

 3     /* 1.分配一个nand_chip结构体 */

 4     lhy_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);

 5     /* 2.设置 */

 6     /* 2.1设置nand_chip是给nand_scan函数用的,如果不知道怎么设置,先看nand_scan怎么用

 7      *         它应该提供:选中,发命令,发地址,发数据,读数据,判断状态等功能

 8      */

 9     lhy_nand->select_chip = lhy_select_chip;      //选中,芯片选择函数

10     lhy_nand->cmd_ctrl       = lhy_nand_cmd_ctrl;        //负责发送地址,命令

11     lhy_nand->IO_ADDR_R   = "NFDATA 的虚拟地址";

12     lhy_nand->IO_ADDR_R   = "NFDATA 的虚拟地址";

13     lhy_nand->dev_ready      = lhy_dev_ready;

14     /* 3.硬件相关的操作 */

15     

16     /* 4.使用nand_scan */

17     lhy_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);

18     lhy_mtd->priv = lhy_nand;            //私有数据为我们的nand_chip结构体

19     lhy_mtd->owner = THIS_MODULE;

20     

21     nand_scan(lhy_mtd,1);        //扫描识别nand flash,并且构造mtd,最大芯片个数为1

22     /* 5.add_mtd_partitions */

23     

24     

25     return 0;

26 }


3.实现上述方法:


 1 /* 芯片选择 */

 2 static void lhy_select_chip(struct mtd_info *mtd,int chipnr)

 3 {

 4     if(chipnr == -1){

 5         /* 取消选中,NFCONT[1]设为0 */

 6     }else{

 7         /* 选中:NFCONT[1]设为1 */

 8     }

 9 }

10 //发送命令,地址,数据

11 static void lhy_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)

12 {

13     if (ctrl & NAND_CLE){

14         /* 发命令 : NFCMMD=dat*/

15         writeb(cmd, host->io_base + (1 << host->board->cle));

16     }else{

17         writeb(cmd, host->io_base + (1 << host->board->ale));

18     }

19 }

20 //判断状态

21 static int lhy_dev_ready(struct mtd_info *mtd)

22 {

23     return "NFSTAT 的 bit[0]";

24 }


附上驱动程序nand_flash1:


  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 static struct nand_chip *lhy_nand;   

 18 static struct mtd_info *lhy_mtd;    //定义一个mtd_info结构体

 19 

 20 /* 芯片选择 */

 21 static void lhy_select_chip(struct mtd_info *mtd,int chipnr)

 22 {

 23     if(chipnr == -1){

 24         /* 取消选中,NFCONT[1]设为0 */

 25     }else{

 26         /* 选中:NFCONT[1]设为1 */

 27     }

 28 }

 29 //发送命令,地址,数据

 30 static void lhy_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)

 31 {

 32     if (ctrl & NAND_CLE){

 33         /* 发命令 : NFCMMD=dat*/

 34         writeb(cmd, host->io_base + (1 << host->board->cle));

 35     }else{

 36         writeb(cmd, host->io_base + (1 << host->board->ale));

 37     }

 38 }

 39 //判断状态

 40 static int lhy_dev_ready(struct mtd_info *mtd)

 41 {

 42     return "NFSTAT 的 bit[0]";

 43 }

 44 

 45 static int lhy_nand_init(void){

 46     

 47     /* 1.分配一个nand_chip结构体 */

 48     lhy_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);

 49     /* 2.设置 */

 50     /* 2.1设置nand_chip是给nand_scan函数用的,如果不知道怎么设置,先看nand_scan怎么用

 51      *         它应该提供:选中,发命令,发地址,发数据,读数据,判断状态等功能

 52      */

 53     lhy_nand->select_chip = lhy_select_chip;      //选中,芯片选择函数

 54     lhy_nand->cmd_ctrl       = lhy_nand_cmd_ctrl;        //负责发送地址,命令

 55     lhy_nand->IO_ADDR_R   = "NFDATA 的虚拟地址";

 56     lhy_nand->IO_ADDR_R   = "NFDATA 的虚拟地址";

 57     lhy_nand->dev_ready      = lhy_dev_ready;

 58     /* 3.硬件相关的操作 */

 59     

 60     /* 4.使用nand_scan */

 61     lhy_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);

 62     lhy_mtd->priv = lhy_nand;            //私有数据为我们的nand_chip结构体

 63     lhy_mtd->owner = THIS_MODULE;

 64     

 65     nand_scan(lhy_mtd,1);        //扫描识别nand flash,并且构造mtd,最大芯片个数为1

 66     /* 5.add_mtd_partitions */

 67     

 68     

 69     return 0;

 70 }

 71 

 72 static void lhy_nand_exit(void){

 73     if(lhy_nand)

 74         kfree(lhy_nand);

 75     if(lhy_mtd)

 76         kfree(lhy_mtd);

 77 }

 78 

 79 module_init(lhy_nand_init);

 80 module_exit(lhy_nand_exit);

 81 MODULE_LICENSE("GPL");

 82 

 83 

 84 /*

 85 S3C2440 U-BOOT 的NAND操作

 86 

 87 1.读取ID

 88 选中                    NFCONT的bit1设为0    md.1 0x4E000004 1;    mw.1 0x4e000004 1

 89 发出命令0x90            NFCMMD=0X90            mw.b 0x4E000008 0x90

 90 发出地址0x00            NFADD=0X00            mw.b 0x4E00000c 0x00

 91 读出数据得到0XEC          val=NFDATA            md.b 0x4E000010 1

 92 读数据得到device code    val=NFDATA             md.b 0x4E000010 1

 93 退出读ID状态            NFCMMD=0xff            mw.b 0x4E000008 0xff

 94 

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

 96 输入命令: nand dump 0  得到nand

 97 

 98 选中                    NFCONT的bit1设为0    md.1 0x4E000004 1;    mw.1 0x4e000004 1

 99 发出命令0x00            NFCMMD=0X00            mw.b 0x4E000008 0x00

100 

101 发出地址0x00            NFADD=0X00            mw.b 0x4E00000c 0x00

102 发出地址0x00            NFADD=0X00            mw.b 0x4E00000c 0x00

103 发出地址0x00            NFADD=0X00            mw.b 0x4E00000c 0x00

104 发出地址0x00            NFADD=0X00            mw.b 0x4E00000c 0x00

105 发出地址0x00            NFADD=0X00            mw.b 0x4E00000c 0x00

106 

107 发出命令0x30            NFCMMD=0X00            mw.b 0x4E000008 0x30

108 

109 //接下来就是从0地址开始一个字节一个字节的读出数据,和前面nand dump 0 的数据一样

110 读出数据得到0x17          val=NFDATA            md.b 0x4E000010 1

111 读出数据得到0x00          val=NFDATA            md.b 0x4E000010 1

112 读出数据得到0x00          val=NFDATA            md.b 0x4E000010 1

113 

114 退出读状态                NFCMMD=0xff            mw.b 0x4E000008 0xff

115 

116 3.NAND  flash 驱动层次  Atmel_nand.c  Mtdchar.c

117 块设备:        知道怎么优化

118 NAND Flash协议:知道发什么来读写,擦除,识别

119 硬件相关:        知道怎样发命令/地址,读写数据

120 

121 硬件相关:

122 ①分配nand_chip 结构体 

123 ②设置nand_chip 

124 ③硬件相关设备 

125 ④使用 nand_scan / add_mtd_partitions

126 

127 */


二、完善前面的程序

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>