韦东山视频实验之Nand驱动

本文详细探讨了Nand驱动的实现,包括Nand的原理分析、驱动细节,如时钟和时序设置、自动探测以及分区管理。在实践中遇到的挑战包括oops错误和文件复制问题。通过源代码解析,深入理解Nand驱动的编写过程。
摘要由CSDN通过智能技术生成

这里主要牵涉到static struct nand_chip mtd_info这两个底层封装的函数

Nand原理分析:

Nand驱动分析:

1)要进行nand时钟和时序的设置

     这里面会进行nand的寄存器的片选,命令的设置,地址或者数据的设置,状态位的读取,nand时钟和时序的设置等

2)nand flash底层的自动探测,识别nand

     这里面会进行初始的函数设置nand的函数,否则使用默认的底层函数进行探测与设置

3)增加nand分区

      使用struct mtd_partition可以对nand进行分区:nand_chip-> mtd_info->nand_scan->add_mtd_partitons

遇到的问题:

1.发生oops错误,各种指针都是null,最后定位到时寄存器地址设置错误

2.就是无法使用flash_erase flash_eraseall这两个复制到/bin目录下的文件

源代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/clk.h>

#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>

#include <asm/io.h>
//#include <asm/arch/regs-nand.h>
//#include <asm/arch/nand.h>



struct nand_regs{
	unsigned long nfconf;  //0x4E000000
	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_regs*		nand_regs_base;
static struct nand_chip*		mini2440_nand;
static struct mtd_info*			mini2440_mtd;


static struct mtd_partition mini2440_partiton[] = {
	[0] = {
		.name	= "supervivi",
		.size	= 0x00040000,
		.offset	= 0,
	},
	[1] = {
		.name	= "param",
		.offset = MTDPART_OFS_APPEND,
		.size	= 0x00020000,
	},
	[2] = {
		.name	= "Kernel",
		.offset = MTDPART_OFS_APPEND,
		.size	= 0x00500000,
	},
	[3] = {
		.name	= "root",
		.offset = MTDPART_OFS_APPEND,
		.size	= MTDPART_SIZ_FULL, //
	}
};



//片选
static void mini2440_select_chip(struct mtd_info *mtd, int chip)
{
	if (chip == -1)
	{
		nand_regs_base->nfcont |= (1<<1);
	}
	else
	{
		nand_regs_base->nfcont &= ~(1<<1);
	}
}

//发送命令/地址
static void	mini2440_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
{
	if ( ctrl & NAND_CLE ) //命令
	{
		nand_regs_base->nfcmmd = dat;
	}
	else //地址
	{
		nand_regs_base->nfaddr = dat;
	}
}

//nand状态
static 	int mini2440_dev_ready(struct mtd_info *mtd)
{
	return (nand_regs_base->nfstat & (1<<0));
}


static int nand_init(void)
{
	struct clk* clk;
	// 1 分配nand_chip空间
	mini2440_nand = kzalloc(sizeof(struct nand_chip), GFP_KERNEL);
	nand_regs_base = ioremap(0x4E000000, sizeof(struct nand_regs));

	// 2 设置nand_chip
	mini2440_nand->select_chip	= mini2440_select_chip;
	mini2440_nand->cmd_ctrl		= mini2440_cmd_ctrl;
	mini2440_nand->IO_ADDR_R	= &nand_regs_base->nfdata;
	mini2440_nand->IO_ADDR_W	= &nand_regs_base->nfdata;
	mini2440_nand->dev_ready	= mini2440_dev_ready;
	mini2440_nand->ecc.mode		= NAND_ECC_SOFT;


	//3.硬件相关的设置 
	//1) nand时钟
	clk = clk_get(NULL, "nand");
	clk_enable(clk);
	//2) nand 时序
	/* HCLK=100MHz
	 * TACLS:  发出CLE/ALE之后多长时间才发出nWE信号, 从NAND手册可知CLE/ALE与nWE可以同时发出,所以TACLS=0
	 * TWRPH0: nWE的脉冲宽度, HCLK x ( TWRPH0 + 1 ), 从NAND手册可知它要>=12ns, 所以TWRPH0>=1
	 * TWRPH1: nWE变为高电平后多长时间CLE/ALE才能变为低电平, 从NAND手册可知它要>=5ns, 所以TWRPH1>=0
	 */
#define TACLS		0
#define TWRPH0		1
#define TWRPH1		0
	nand_regs_base->nfconf = (TACLS<<12) | (TWRPH0<<8) |(TWRPH1<<4);
	nand_regs_base->nfcont = (1<<1) | (1<<0); //取消片选,使能控制器

	// 4.使用nand_scan
	mini2440_mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
	mini2440_mtd->owner		= THIS_MODULE;
	mini2440_mtd->priv		= mini2440_nand;

	//识别nand flash
	nand_scan(mini2440_mtd, 1);

	// 5 增加分区
	add_mtd_partitions(mini2440_mtd, mini2440_partiton, 4);

	return 0;
}

static void nand_exit(void)
{
	del_mtd_partitions(mini2440_mtd);
	kfree(mini2440_mtd);
	iounmap((nand_regs_base));
	kfree(mini2440_nand);
}

module_init(nand_init);
module_exit(nand_exit);

MODULE_AUTHOR("LCL");
MODULE_LICENSE("GPL");

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值