驱动程序之_2_块设备_4_Nand Flash_3_驱动程序编写

本文详细介绍NAND Flash驱动程序的编写过程,包括初始化、功能实现及测试步骤。通过分析s3c2410.c和At91_nand.c源代码,指导如何配置nand_chip,设置硬件,构造mtd_info,以及进行设备扫描和分区。同时,提供了一个基于S3C2440 SoC的NAND Flash驱动示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

驱动程序之_2_块设备_4_Nand Flash_3_驱动程序编写

 

 

参考/drivers/mtd/nand/目录下的s3c2410.c和At91_nand.c

 

一、入口函数

1、分配nand_chip

2、设置nand_chip(如果不知道怎么设置,可以从nand_scan函数入手分析,如果不设置,会分配有默认值、默认函数,可以参数默认函数编写符合自己的函数,如果默认函数可用,可以不额外编写)

3、硬件设置(首先要开启时钟)

4、分配mtd_info

5、扫描构造mtd_info

6、添加mtd分区

 

二、出口函数,完成与入口函数相反的操作

 

三、完善功能函数

1、片选控制

2、命令、地址传送

3、状态检测

 

 

测试步骤:

1、重新编译内核(反选内核的nand flash驱动),用新内核,并从网络文件系统启动

  |   Location:                                                                                                                                                   |
  |     -> Device Drivers                                                                                                                                         |
  |       -> Memory Technology Device (MTD) support (MTD [=y])                                                                                                    |
  |         -> NAND Device Support (MTD_NAND [=y])                                                                                                                |
  |           -> NAND Flash support for S3C2410/S3C2440 SoC (MTD_NAND_S3C2410 [=n]) 

2、加载驱动

3、查看设备

ls /dev/mtd*

  4、挂载设备

mkdir /mnt
mount /dev/mtdblock3 /mnt

5、格式化(网上下载mtd-utils-05.07.23.tar.bz2,送到服务器解压,进入解压目录下的util目录,修改Makefile,反注释CROSS=arm-linux-,编译make,拷贝flash_erase、flash_eraseall到网络文件系统/bin目录中)

擦除后默认就是yaffs格式

umount /mnt
flash_eraseall /dev/mtd3

6、再挂载

mount -t yaffs /dev/mtdblock3 /mnt

7、可以参考前面块设备简单实例的测试方法继续测试

 

 

 

附上完整代码

#include <linux/slab.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/clk.h>
#include <asm/io.h>
#include <asm/sizes.h>
#include <asm/hardware.h>
#include <asm/arch/gpio.h>

#define PARTITIONS


#define TACLS  0
#define TWRPH0 1
#define TWRPH1 0

static struct mtd_partition s3c2440_nand_parts[] = {
	[0] = {
        .name   = "bootloader",
        .size   = 0x00040000,
		.offset	= 0,
	},
	[1] = {
        .name   = "params",
        .offset = MTDPART_OFS_APPEND,
        .size   = 0x00020000,
	},
	[2] = {
        .name   = "kernel",
        .offset = MTDPART_OFS_APPEND,
        .size   = 0x00200000,
	},
	[3] = {
        .name   = "root",
        .offset = MTDPART_OFS_APPEND,
        .size   = MTDPART_SIZ_FULL,
	}
};


struct s3c2440_nand_regs{
	unsigned long nfconf;
	unsigned long nfcont;
	unsigned long nfcmmd;
	unsigned long nfaddr;
	unsigned long nfdata;
	unsigned long nfeccd0;
	unsigned long nfeccd1;
	unsigned long nfeccd;
	unsigned long nfstat;
	unsigned long nfestat0;
	unsigned long nfestat1;
	unsigned long nfmecc0;
	unsigned long nfmecc1;
	unsigned long nfsecc;
	unsigned long nfsblk;
	unsigned long nfeblk;
};

static struct nand_chip *s3c2440_nand_chip;
static struct mtd_info  *s3c2440_mtd;
static struct s3c2440_nand_regs *s3c2440_nand_regs;

static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chipnr)
{
	if(chipnr == -1)
	{
		s3c2440_nand_regs->nfcont |=  (1<<1);
	}
	else
	{
		s3c2440_nand_regs->nfcont &= ~(1<<1);
	}
}

static void s3c2440_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
	if(ctrl & NAND_CLE)
		s3c2440_nand_regs->nfcmmd = dat;
	else
		s3c2440_nand_regs->nfaddr = dat;
}

static int s3c2440_nand_ready(struct mtd_info *mtd)
{
	return (s3c2440_nand_regs->nfstat & (1<<0));
}




static int nand_init(void)
{
	struct clk *nand_clk;

	
	s3c2440_nand_chip = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
	s3c2440_nand_regs = ioremap(0x4e000000,sizeof(struct s3c2440_nand_regs));

	nand_clk = clk_get(0,"nand");
	clk_enable(nand_clk);	

	s3c2440_nand_regs->nfconf = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4); 		
	s3c2440_nand_regs->nfcont = (1<<1) | (1<<0);	

	s3c2440_nand_chip->select_chip = s3c2440_nand_select_chip;
	s3c2440_nand_chip->IO_ADDR_R   = &s3c2440_nand_regs->nfdata;	//virtual addr
	s3c2440_nand_chip->IO_ADDR_W   = &s3c2440_nand_regs->nfdata;
	s3c2440_nand_chip->cmd_ctrl    = s3c2440_nand_cmd_ctrl;
	s3c2440_nand_chip->dev_ready   = s3c2440_nand_ready;
	s3c2440_nand_chip->ecc.mode    = NAND_ECC_SOFT;
		
	s3c2440_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
	s3c2440_mtd->owner = THIS_MODULE;
	s3c2440_mtd->priv = s3c2440_nand_chip;
	nand_scan(s3c2440_mtd,1);

#ifdef PARTITIONS
	add_mtd_partitions(s3c2440_mtd, s3c2440_nand_parts, 4);		//分区
#else
	add_mtd_device(s3c2440_mtd);		//不分区
#endif

	return 0;
}

static void nand_exit(void)
{
#ifdef PARTITIONS
	del_mtd_partitions(s3c2440_mtd);
#else
	del_mtd_device(s3c2440_mtd);
#endif

	kfree(s3c2440_mtd);
	iounmap(s3c2440_nand_regs);
	kfree(s3c2440_nand_chip);
}

module_init(nand_init);
module_exit(nand_exit);
MODULE_LICENSE("GPL");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值