NandFlash驱动超详细分析报告报告材料.docx

上传人:b****4 文档编号:12012484 上传时间:2023-04-16 格式:DOCX 页数:23 大小:25.48KB
下载 相关 举报
NandFlash驱动超详细分析报告报告材料.docx_第1页
第1页 / 共23页
NandFlash驱动超详细分析报告报告材料.docx_第2页
第2页 / 共23页
NandFlash驱动超详细分析报告报告材料.docx_第3页
第3页 / 共23页
NandFlash驱动超详细分析报告报告材料.docx_第4页
第4页 / 共23页
NandFlash驱动超详细分析报告报告材料.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

NandFlash驱动超详细分析报告报告材料.docx

《NandFlash驱动超详细分析报告报告材料.docx》由会员分享,可在线阅读,更多相关《NandFlash驱动超详细分析报告报告材料.docx(23页珍藏版)》请在冰豆网上搜索。

NandFlash驱动超详细分析报告报告材料.docx

NandFlash驱动超详细分析报告报告材料

实用标准文案

今天学习了NandFlash的驱动,硬件操作非常简单,就是这个linux下的驱动比较复杂,主要还是MTD层的问题,用了一下午时间整理出来一份详细的分析,只是分析函数结构和调用关系,具体代码实现就不看了,里面有N个结构体,搞得我头大。

我用linux2.6.25内核,2440板子,先从启动信息入手。

内核启动信息,NAND部分:

S3C24XXNANDDriver,(c)2004SimtecElectronics

s3c2440-nands3c2440-nand:

Tacls=2,20nsTwrph0=330ns,Twrph1=2

20ns

NANDdevice:

ManufacturerID:

0xec,ChipID:

0x76(SamsungNAND

64MiB3,3V8-bit)

Scanningdeviceforbadblocks

Creating3MTDpartitionsonNAND64MiB3,3V8-bit:

砰?

?

?

?

?

へ?

?

?

‰?

扜潯屴

砰?

?

っ?

?

へ日挴?

‰?

歜牥敮屬

砰?

?

っ?

?

へ昳捦?

‰?

祜晡獦尲

第一行,在driver/mtd/nand/s3c2410.c中第910行,s3c2410_nand_init函数:

printk(S3C24XXNANDDriver,(c)2004SimtecElectronics\n);

行二行,同一文件,第212行,s3c2410_nand_inithw函数:

精彩文档.

实用标准文案

dev_info(info->device,Tacls=%d,%dnsTwrph0=%d%dns,

Twrph1=%d%dns\n,tacls,to_ns(tacls,clkrate),twrph0,to_ns(twrph0,

clkrate),twrph1,to_ns(twrph1,clkrate));

第三行,在driver/mtd/nand/nand_base.c中第2346行,

printk(KERN_INFONANDdevice:

ManufacturerID:

0xx,ChipID:

0xx(%s%s)\n,*maf_id,dev_id,nand_manuf_ids[maf_idx].name,

type->name);

第四行,在driver/mtd/nand/nand_bbt.c中第380行,creat_bbt函数:

Printk(KERNINFOScanningdeviceforbadblocks\n);

第五行,在driver/mtd/mtdpart.c中第340行,add_mtd_partitions函数:

printk(KERN_NOTICECreating%dMTDpartitionson\%s\:

\n,

nbparts,master->name);

下面三行,是flash分区表,也在mtdpart.c同一函数中,第430行:

printk(KERN_NOTICE

slave->offset+slave->mtd.size,slave->mtd.name);

MTD体系结构:

在linux中提供了MTD(MemoryTechnologyDevice,内存技术设备)系统来建立Flash针对linux的统一、抽象的接口

引入MTD后,linux系统中的Flash设备驱动及接口可分为4层:

设备节点

精彩文档.

实用标准文案

MTD设备层

MTD原始设备层

硬件驱动层

硬件驱动层:

Flash硬件驱动层负责底层硬件设备实际的读、写、擦除,Linux

MTD设备的NAND型Flash驱动位于driver/mtd/nand子目录下

s3c2410对应的nandFlash驱动为s3c2410.c

MTD原始设备层:

MTD原始设备层由两部分构成,一部分是MTD原始设备的通用代码,另一部分是各个特定Flash的数据,比如分区

主要构成的文件有:

drivers/mtd/mtdcore.c支持mtd字符设备

driver/mtd/mtdpart.c支持mtd块设备

MTD设备层:

基于MTD原始设备,Linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90),构成MTD设备层

简单的说就是:

使用一个mtd层来作为具体的硬件设备驱动和上层文件系统的桥梁。

mtd给出了系统中所有mtd设备(nand,nor,diskonchip)的统一组织方式。

mtd层用一个数组structmtd_info*mtd_table[MAX_MTD_DEVICES]保存系统中所有的设备,mtd设备利用structmtd_info这个结构来描述,该结构中描述了存储设备的基本信息和具体操作所需要的内核函数,mtd系统的那个机制主要就是围绕这个结构来实现的。

结构体在include/linux/mtd/mtd.h中定义:

精彩文档.

实用标准文案

structmtd_info{

u_chartype;//MTD设备类型

u_int32_tflags;//MTD设备属性标志

u_int32_tsize;//标示了这个mtd设备的大小

u_int32_terasesize;//MTD设备的擦除单元大小,对于NandFlash来说就是Block的大小

u_int32_toobblock;//oob区在页内的位置,对于512字节一页的nand来说是512

u_int32_toobsize;//oob区的大小,对于512字节一页的nand来说是16

u_int32_tecctype;//ecc校验类型

u_int32_teccsize;//ecc的大小

char*name;//设备的名字

intindex;//设备在MTD列表中的位置

structnand_oobinfooobinfo;//oob区的信息,包括是否使用ecc,ecc的大小

//以下是关于mtd的一些读写函数,将在nand_base中的nand_scan中重载

int(*erase)

int(*read)

int(*write)

精彩文档.

实用标准文案

int(*read_ecc)

int(*write_ecc)

int(*read_oob)

int(*read_oob)

void*priv;//设备私有数据指针,对于NandFlash来说指nand芯片的结构

下面看nand_chip结构,在include/linux/mtd/nand.h中定义:

structnand_chip{

void__iomem*IO_ADDR_R;//这是nandflash的读写寄存器

void__iomem*IO_ADDR_W;

//以下都是nandflash的操作函数,这些函数将根据相应的配置进行重载

u_char(*read_byte)(structmtd_info*mtd);

void(*write_byte)(structmtd_info*mtd,u_charbyte);

u16(*read_word)(structmtd_info*mtd);

void(*write_word)(structmtd_info*mtd,u16word);

void(*write_buf)(structmtd_info*mtd,constu_char*buf,intlen);

void(*read_buf)(structmtd_info*mtd,u_char*buf,intlen);

int(*verify_buf)(structmtd_info*mtd,constu_char*buf,intlen);

void(*select_chip)(structmtd_info*mtd,intchip);

int(*block_bad)(structmtd_info*mtd,loff_tofs,intgetchip);

int(*block_markbad)(structmtd_info*mtd,loff_tofs);

void(*hwcontrol)(structmtd_info*mtd,intcmd);

精彩文档.

实用标准文案

int(*dev_ready)(structmtd_info*mtd);

void(*cmdfunc)(structmtd_info*mtd,unsignedcommand,int

column,intpage_addr);

int(*waitfunc)(structmtd_info*mtd,structnand_chip*this,int

state);

int(*calculate_ecc)(structmtd_info*mtd,constu_char*dat,u_char

*ecc_code);

int(*correct_data)(structmtd_info*mtd,u_char*dat,u_char*read_ecc,

u_char*calc_ecc);

void(*enable_hwecc)(structmtd_info*mtd,intmode);

void(*erase_cmd)(structmtd_info*mtd,intpage);

int(*scan_bbt)(structmtd_info*mtd);

inteccmode;//ecc的校验模式(软件,硬件)

intchip_delay;//芯片时序延迟参数

intpage_shift;//页偏移,对于512B/页的,一般是9

u_char*data_buf;//数据缓存区

跟NAND操作相关的函数:

1、nand_base.c:

定义了NAND驱动中对NAND芯片最基本的操作函数和操作流程,如擦除、读写page、读写oob等。

当然这些函数都只是进行一些常规的操作,若你的系统在对NAND操作时有一些特殊的动作,则需要在你自己的驱动代码中进行定义。

精彩文档.

实用标准文案

2、nand_bbt.c:

定义了NAND驱动中与坏块管理有关的函数和结构体。

3、nand_ids.c:

定义了两个全局类型的结构体:

structnand_flash_devnand_flash_ids[]和structnand_manufacturersnand_manuf_ids[]。

其中前者定义了一些NAND芯片的类型,后者定义了NAND芯片的几个厂商。

NAND芯片的ID至少包含两项内容:

厂商ID和厂商为自己的NAND芯片定义的芯片ID。

当NAND加载时会找这两个结构体,读出ID,如果找不到,就会加载失败。

4、nand_ecc.c:

定义了NAND驱动中与softewareECC有关的函数和结构体,若你的系统支持hardwareECC,且不需要softwareECC,则该文件也不需理会。

我们需要关心的是/nand/s3c2410,这个文件实现的是s3c2410/2440nandflash控制器最基本的硬件操作,读写擦除操作由上层函数完成。

s3c2410.c分析:

首先看一下要用到的结构体的注册:

structs3c2410_nand_mtd{

structmtd_info

mtd;//mtd_info的结构体

chip;//nand_chip的结构体structnand_chip

structs3c2410_nand_set*set;

structs3c2410_nand_info*info;

intscan_res;

精彩文档.

实用标准文案

};

enums3c_cpu_type{//用来枚举CPU类型

TYPE_S3C2410,

TYPE_S3C2412,

TYPE_S3C2440,

};

structs3c2410_nand_info{

/*mtdinfo*/

structnand_hw_controlcontroller;

*mtds;structs3c2410_nand_mtd

*platform;structs3c2410_platform_nand

/*deviceinfo*/

structdevice*device;

*area;structresource

*clk;structclk

*regs;void__iomem

void__iomem*sel_reg;

intsel_bit;

mtd_count;int

save_nfconf;unsignedlong

enums3c_cpu_typecpu_type;

精彩文档.

实用标准文案

};

设备的注册:

staticint__inits3c2410_nand_init(void)

{

printk(S3C24XXNANDDriver,(c)2004SimtecElectronics\n);

platform_driver_register(&s3c2412_nand_driver);

platform_driver_register(&s3c2440_nand_driver);

returnplatform_driver_register(&s3c2410_nand_driver);

}

platform_driver_register向内核注册设备,同时支持这三种CPU。

&s3c2440_nand_driver是一个platform_driver类型的结构体:

staticstructplatform_drivers3c2440_nand_driver={

.probe=s3c2440_nand_probe,

=s3c2410_nand_remove,.remove

.suspend=s3c24xx_nand_suspend,

.resume=s3c24xx_nand_resume,

={.driver

=s3c2440-nand,.name

.owner=THIS_MODULE,

},

};

精彩文档.

实用标准文案

最主要的函数就是s3c2440_nand_probe,(调用s3c24XX_nand_probe),完成对nand设备的探测,

staticints3c24xx_nand_probe(structplatform_device*pdev,

enums3c_cpu_typecpu_type)

{

*/主要完成一些硬件的初始化,其中调用函数:

/*

(info,nmtd,sets);s3c2410_nand_init_chip

mtd_infoflash的探测及/*init_chip结束后,调用nand_scan完成对*/读写函数的赋值

(&nmtd->mtd,(sets)?

nand_scannmtd->scan_res=

sets->nr_chips:

1);

if(nmtd->scan_res==0){

s3c2410_nand_add_partition(info,nmtd,sets);

}

}

进行的一步非常好重要的操作,nand的时候对nand是在初始化Nand_scan结nand_scan在中会对我们所写的关于特定芯片的读写函数重载到nand_chipmtdnandmtd_info并会将构中去,结构体中的函数用的函数来重载,实现了到底层驱动的联系。

芯片的设备号和厂家号自动在芯片并且在nand_scan函数中会通过读取nand列表中寻找相应的型号和参数,并将其注册进去。

精彩文档.

实用标准文案

staticvoids3c2410_nand_init_chip(structs3c2410_nand_info*info,

structs3c2410_nand_mtd*nmtd,

structs3c2410_nand_set*set)

{

structnand_chip*chip=&nmtd->chip;

void__iomem*regs=info->regs;

/*以下都是对chip赋值,对应nand_chip中的函数*/

chip->write_buf=s3c2410_nand_write_buf;//写buf

chip->read_buf=s3c2410_nand_read_buf;//读buf

chip->select_chip=s3c2410_nand_select_chip;//片选

chip->chip_delay=50;

chip->priv=nmtd;

chip->options=0;

chip->controller=&info->controller;//?

switch(info->cpu_type){

caseTYPE_S3C2440:

chip->IO_ADDR_W=regs+S3C2440_NFDATA;//数据寄存器

info->sel_reg=regs+S3C2440_NFCONT;//控制寄存器

info->sel_bit=S3C2440_NFCONT_nFCE;

chip->cmd_ctrl=s3c2440_nand_hwcontrol;//硬件控制

chip->dev_ready=s3c2440_nand_devready;//设备就绪

精彩文档.

实用标准文案

chip->read_buf=s3c2440_nand_read_buf;//读buf

chip->write_buf=s3c2440_nand_write_buf;//写buf

break;

}

chip->IO_ADDR_R=chip->IO_ADDR_W;//读写寄存器都是同一个

nmtd->info

=info;

nmtd->mtd.priv=chip;//私有数据指针指向chip

nmtd->mtd.owner=THIS_MODULE;

nmtd->set=set;

/*后面是和ECC校验有关的,省略*/

}

初始化后,实现对nand的基本硬件操作就可以了,包括以下函数:

s3c2410_nand_inithw//初始化硬件,在probe中调用

s3c2410_nand_select_chip//片选

s3c2440_nand_hwcontrol//硬件控制,其实就是片选

s3c2440_nand_devready//设备就绪

s3c2440_nand_enable_hwecc//使能硬件ECC校验

s3c2440_nand_calculate_ecc//计算ECC

s3c2440_nand_read_bufs3c2440_nand_write_buf

注册nand设备到MTD原始设备层:

(这个函数由probe调用)

#ifdefCONFIG_MTD_PARTITIONS//如果定义了MTD分区

精彩文档.

实用标准文案

staticints3c2410_nand_add_partition(structs3c2410_nand_info*info,

structs3c2410_nand_mtd*mtd,

structs3c2410_nand_set*set)

{

if(set==NULL)

returnadd_mtd_device(&mtd->mtd);

if(set->nr_partitions>0&&set->partitions!

=NULL){

returnadd_mtd_partitions(&mtd->mtd,set->partitions,

set->nr_partitions);

}

returnadd_mtd_device(&mtd->mtd);

}

#else

注册设备用这两个函数:

整体不分区,用这个,//如果nandadd_mtd_device

中实现该函数在//mtdcore.c

是分区结构,用这个,nandadd_mtd_partitions//如果

中实现//mtdpart.c该函数在

同样,注销设备也有两个函数:

del_mtd_device

del_mtd_partitions

精彩文档.

实用标准文案

NandFlash还有一个分区表结构体,mtd_partition,这个是在arch/arm/plat-s3c24XX/common-smdk.c中定义的。

staticstructmtd_partitionsmdk_default_nand_part[]={

[0]={

.name=oot,

.size

=0x00040000,

.offset=0,

},

[1]={

=kernel,.name

.offset=0x0004C000,

=0x00200000,.size

},

[2]={

=yaffs2,.name

.offset=0x0024C000,

=0x03DB0000,.size

},

};

有几个分区,每个分区的名字,大小,偏移量是多少记录了当前的nandflash

系统就是依靠这些分区表找到各个文件系统的

精彩文档.

实用标准文案

这些分区表nand中的文件系统没有必然关系,分区表只是把flash分成不同的部分

如果自己编写一个nandflash驱动,只需要填充这三个结构体:

Mtd_infonand_chip

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工作范文 > 演讲主持

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1