linux flash驱动程序,嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序(示例代码)...

NAND FLASH是一个存储芯片。

在芯片上的DATA0~DATA7上既能传输数据也能传输地址。

当ALE为高电平时传输的是地址。

当CLE为高电平时传输的是命令。

当ALE和CLE都为低电平时传输的是数据。

将数据发给nand Flash后,在发送第二次数据之前还要判断芯片是否处于空闲状态。一般是通过引脚RnB来判断,一般是高电平代表就绪,低电平代表正忙。

操作Nand Flash的一般步骤是:

1. 发命令

选中芯片

CLE设置为高电平

在DATA0~DATA7上输出命令值

发出一个写脉冲

2. 发地址

选中芯片

ALE为高电平

在DATA0~DATA7上传输数据

发出一个写脉冲

3. 发数据

选中芯片

发出读脉冲

读取DATA0~DATA7上的数据。

使用UBOOT来体验NAND FLASH的操作:

读ID

选中        NFCONT的bit1设置为0      md.l   0x4e000004 1; mw.l 0x4e000004 1

发出命令0x90     NFCMMD=0X90          mw.b  0x4e000008  0x90;

发出地址0x00     NFADDR=0X00           mw.b  0x4e00000C  0x00;

读取数据得到0XEC     val=NFDATA          md.b   0x4e000010  1

读取数据得到device code val=NFDATA         md.b  0x4e000010  1

退出读ID的状态      NFCMMD=0XFF      mw.b  0x4e000008  0xff

NAND FLASH驱动程序层次

看内核启动信息

S3C24XX NAND Driver, (c)2004Simtec Electronics

s3c2440-nand s3c2440-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=330ns

NAND device: Manufacturer ID:0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit)

Scanning deviceforbad blocks

Bad eraseblock256 at 0x02000000Bad eraseblock257 at 0x02020000Bad eraseblock319 at 0x027e0000Bad eraseblock606 at 0x04bc0000Bad eraseblock608 at 0x04c00000Creating4 MTD partitions on "NAND 256MiB 3,3V 8-bit":0x00000000-0x00040000 : "bootloader"

0x00040000-0x00060000 : "params"

0x00060000-0x00260000 : "kernel"

0x00260000-0x10000000 : "root"搜"S3C24XX NAND Driver"S3c2410.c (drivers\mtd\nand)

s3c2410_nand_inithw

s3c2410_nand_init_chip

nand_scan//drivers/mtd/nand/nand_base.c 根据nand_chip的底层操作函数识别NAND FLASH,构造mtd_info

nand_scan_ident

nand_set_defaultsif (!chip->select_chip)

chip->select_chip = nand_select_chip; //默认值不适用

if (chip->cmdfunc ==NULL)

chip->cmdfunc =nand_command;

chip->cmd_ctrl(mtd, command, ctrl);if (!chip->read_byte)

chip->read_byte =nand_read_byte;

readb(chip->IO_ADDR_R);if (chip->waitfunc ==NULL)

chip->waitfunc =nand_wait;

chip->dev_ready

nand_get_flash_type

chip->select_chip(mtd, 0);

chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);*maf_id = chip->read_byte(mtd);

dev_id= chip->read_byte(mtd);

nand_scan_tail

mtd->erase =nand_erase;

mtd->read =nand_read;

mtd->write =nand_write;

s3c2410_nand_add_partition

add_mtd_partitions

add_mtd_device

list_for_each(this, &mtd_notifiers) { //问. mtd_notifiers在哪设置//答. drivers/mtd/mtdchar.c,mtd_blkdev.c调用register_mtd_user

struct mtd_notifier *not = list_entry(this, structmtd_notifier, list);

not->add(mtd);//mtd_notify_add 和 blktrans_notify_add

先看字符设备的mtd_notify_add

class_device_create

class_device_create

再看块设备的blktrans_notify_add

list_for_each(this, &blktrans_majors) { //问. blktrans_majors在哪设置//答. drivers\mtd\mdblock.c或mtdblock_ro.c register_mtd_blktrans

struct mtd_blktrans_ops *tr = list_entry(this, structmtd_blktrans_ops, list);

tr->add_mtd(tr, mtd);

mtdblock_add_mtd (drivers\mtd\mdblock.c)

add_mtd_blktrans_dev

alloc_disk

gd->queue = tr->blkcore_priv->rq; //tr->blkcore_priv->rq = blk_init_queue(mtd_blktrans_request, &tr->blkcore_priv->queue_lock);

add_disk

驱动程序代码:

/** drivers\mtd\nand\s3c2410.c

* drivers\mtd\nand\at91_nand.c*/#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include#include

struct nand_chip *s3c_nand;struct mtd_info *s3c_mtd;struct clk *clk;structs3c_nand_regs{

unsignedlongnfconf;

unsignedlongnfcont;

unsignedlongnfcmd;

unsignedlongnfaddr;

unsignedlongnfdata;

unsignedlongnfeccd0;

unsignedlongnfeccd1;

unsignedlongnfeccd;

unsignedlongnfstat;

unsignedlongnfestat0;

unsignedlongnfestat1;

unsignedlongnfeecc0;

unsignedlongnfeecc1;

unsignedlongnfsecc;

unsignedlongnfsblk;

unsignedlongnfeblk;

};static struct mtd_partition s3c_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,

}

};static volatile struct s3c_nand_regs *nand_regs;static void s3c2440_select_chip(struct mtd_info *mtd, intchipnr )

{if(chipnr == -1)

{/*取消选中*/nand_regs->nfcont |= (1<<1);

}else{/*选中 NFCONT^1 设置为1*/nand_regs->nfcont &= ~(1<<1);

}

}static void s3c2440_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned intctrl)

{if (cmd ==NAND_CMD_NONE)return;if (ctrl &NAND_CLE)

{/*发命令*/nand_regs->nfcmd =cmd;

}else{/*发地址*/nand_regs->nfaddr =cmd;

}

}static int s3c2440_dev_ready(struct mtd_info *mtd)

{/* */

return (nand_regs->nfstat & (1<<0));

}static int s3c_nand_init(void)

{/*分配一个nand_chip结构体*/s3c_nand= kzalloc(sizeof(structnand_chip), GFP_KERNEL);

nand_regs= ioremap(0x4e000000,sizeof(structs3c_nand_regs));

clk= clk_get(NULL,"nand");

clk_enable(clk);/*设置*/s3c_nand->select_chip =s3c2440_select_chip;

s3c_nand->cmd_ctrl =s3c2440_nand_cmd_ctrl;

s3c_nand->IO_ADDR_R = (void *)&nand_regs->nfdata;

s3c_nand->IO_ADDR_W = (void *)&nand_regs->nfdata;

s3c_nand->dev_ready =s3c2440_dev_ready;

s3c_nand->ecc.mode =NAND_ECC_SOFT;/*硬件相关的操作:根据nand Flash的手册设置时间参数*/

/*HCLK = 100MHz*/

/*TACLS: 发出cle/ale之后多长时间才发出nWE信号*/

/*TWRPHO: nWE的脉冲宽度*/nand_regs->nfconf = (1<<8);

nand_regs->nfcont = 0x03;/*使用:nand_scan*/s3c_mtd= kzalloc( sizeof(structmtd_info), GFP_KERNEL );

s3c_mtd->owner =THIS_MODULE;

s3c_mtd->priv =s3c_nand;

nand_scan(s3c_mtd,1); /*扫描识别*/

/*add_mtd_partitions*/add_mtd_partitions(s3c_mtd,s3c_nand_parts,4);//add_mtd_device(s3c_mtd);//整个flash只有一个分区的话可以用这个

return 0;

}static void s3c_nand_exit(void)

{

del_mtd_partitions(s3c_mtd);

kfree(s3c_mtd);

iounmap(nand_regs);

kfree(s3c_nand);

}

module_init(s3c_nand_init);

module_exit(s3c_nand_exit);

MODULE_LICENSE("GPL");

在添加这个内核模块的时候,首先卸载内核中的nand Flash驱动。

->Device Drivers

->Memory Technology Device (MTD) support

->NAND Device Support

sd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值