基于linux的MTD的NANDFLASH设备驱动底层实现原理分析(DOC)_第1页
基于linux的MTD的NANDFLASH设备驱动底层实现原理分析(DOC)_第2页
免费预览已结束,剩余45页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 设备节点:用户在/dev 目录下使用 mknod 命令建立 MTD 字符设备节点(主设备号 为90),或者 MT块设备节点(主设备号为 31),使用该设备节点即可访问 MTD 设备。 MTD 设备层:基于 MTD 原始设备层,系统将 MTD 设备可以定义为 MTD 字符(在 /mtd/mtdchar.c 中实现,设备号 90)和 MTD 块设备(在/mtd/mtdblock.c 中实现, 设备号 31)。 MTD 原始设备层:MTDM始设备层由两部分构成,一部分是 MTD 原始设备的通 用代码,另一部分是各个特定 Flash 的数据,如分区。 主要构成的文件有: drivers/mtd/mt

2、dcore.c 支持 mtd 字符设备 Flash 硬件驱动层:Flash 硬件驱动层负责对 Flash 硬件的读、写和擦除操作。 MTD 设备的 Nor Flash 芯片驱动位于 drivers/mtd/chips/ 子目录下,NandFlash 芯片的驱动则位于 drivers/mtd/nand/ 子目录下。 二、Linux 内核中基于 MTD 的 NANDFLAS 驱动代码布局: 在 LinuX2.6.35 内核中,MTDS代码放在 driver/mtd 目录中,该目录中包含 chips、devices、maps nand、onenand lpdrr、tests 和 ubi 八个子目录。

3、 其中只有 nand 和 onenand 目录中的代码才与 NAND 区动相关,不过 nand 目 录中的代码比较通用,而 onenand 目录中的代码相对于 nand 中的代码而言则简 化了很多,它是针对三星公司开发的另一类 Flash 芯片,即 OneNAND Flash 本文我们需要关注的代码是 linux-2635/drivers/mtd/nand 目录中,在该 目录中我们关心的文件如下: 1、 nand_base.c : 定义了 NAND 区动中对 NAND5 片最基本的操作函数和操作流程,如擦除、读 写page、读写 oob 等。当然这些函数都只是进行一些 default 的操作,

4、若你的 系统在对NAND 操作时有一些特殊的动作, 则需要在你自己的驱动代码中进行定 义, 然后 Replace这些 default 的函数。 2、 nand_bbt.c : 定义了 NAND 区动中与坏块管理有关的函数和结构体。 3、 nand_ids.c : 定义了两个全局类型的结构体:struct nand_flash_dev nand_flash_ids 和 struct nand_manufacturers nand_manuf_ids。其中前者定义了一些 NAND 芯片的类型,后者定义了 NAND 芯片的几个厂商。NAN 芯片的 ID 至少包含两项 内容:厂商 ID 和厂商为自己的

5、 NAND5 片定义的芯片 ID。当 NAN驱动被加载的 时候,它会去读取具体 NANC芯片的 ID,然后根据读取的内容到上述定义的 nand_manuf_ids和 nand_flash_ids两个结构体中去查找,以此判断该 NAND 芯片是那个厂商的产品,以及该 NAND5 片的类型。若查找不到,则 NAN驱动就 会加载失败,因此在开发 NANtS区动前必须事先将你的 NANC 芯片添加到这两个结 构体中去(其实这两个结构体中已经定义了市场上绝大多数的 NANC 芯片,所以除 非你的 NAND 芯片实在比较特殊,否则一般不需要额外添加)。值得一提的是, nand_flash_ids 中有三项

6、属性比较重要,即 pagesize、chipsize 和 erasesize,驱动就是依据这三项属性来决定对 NAND5 片进行擦除,读写等操作 时的大小的。 其中 pagesize 即 NANC 芯片的页大小, 一般为 256、 512 或 2048; chipsize即 NAND5 片的容量;erasesize 即每次擦除操作的大小,通常就是 NAND 芯片的 block大小。 4、 nand_ecc.c :driver/mtd/mtdpart.c 支持 mtd 块设备 定义了 NAND 驱动中与 softeware ECC 有关的函数和结构体,若你的系统 支持 hardware ECC,

7、且不需要 software ECC,则该文件也不需理会。 上面这些内容我是 Copy 别人的我觉得写得太好了,因为一开始我真的很迷茫,在 nand目录下有那么多的文件,到底哪个是值得我读的.我真的不值得,读了这个 大神的博客后对 NANDDLASH 驱动我不再是那么的迷茫。 三、NANDFLASH 硬件特性 要想读懂后面 Linux 系统中对 NANDFLASH 件驱动代码,了解 NANDFLASH 的 硬件特性这是再好不过的。 1、NANDFLAS 的内部布局 Nand Flash Layout Nand Flash 比如型号为 K9K8G08U0A这个芯片(chip),内部有两个 K9F4

8、G08U0A-每个 K9F4G08UOA 包含了 2 个 Plane,每个 Plane 是 1Gbr 所以 K9F4G08UOA 的大小是!CbX2=2GbP=;256MB. 因止匕 K9KSG08UOA 内咅;有 2 个 K9F4G08L0A,即 4 个 Plane, 4X256MB= 1GB = 而型号是K9VAG08LT1A的 MndFI日 5h.内凯包含了 2个 K9K8G08UOA,所儿总容量是 KK8GO8UOA的两 ffi= IGB X 2 = 2GB 类似地 K9NBG0W5A 内部包含了 4个 K9K8GO8U0A, &大小就是 4X1GB=4GB. 2、Nand F

9、lash 的物理存储单元的阵列组织结构(以开发板上的 K9F2G08 为例)ChipO Chip 1 Plsrie 0 WareN Block 0 Block 1 Stock 2 Page 1 page N Block 3 Block N p咻0 ocb 1 Block - 64 Pages (128K +4k) Byte 1 Page - 2K + 64)Bytes 1 0IOCK = (2K + 64 jB X 64 Pages = (123K *4K H呻 1 DE. ice = (2K+64jB x 64364 x 2.048 Blocks -2,115 Mbits Bbl K9F2G

10、08 的大小是 256M a) block:Block 是 Na nd Flash 的擦除操作的基本/最小单位,一片 NANDFLASH(chip 由很多块 (block)组成,块的大小一般是 128KB, 256KB, 512KB 此处是 128KB。其他 的小于 128KB 的, 比如 64KB 称之为 small block 的 Nand Flash。 b) page:page 是读写操作的最小单位,每一个 block 里面包又含了许多 page(页),每个页的大小, 对于现在常见的 Na nd Flash 多数是 2KB 最新的 Nand Flash 的是 4KB 8KB 等, LfO

11、O ra 1 I/O 2 1/0 3 2 4 L/0 5 i;0 6 1/0 7 W Cycit Ao Al A? Al AA As Aft A? 2nd Ccle AS Afi Ai a AIT L L L L 3fd Cyde A12 Ail Au AiS A16 At? Aia Aifi 竝 h Cycle AZQ Azi 阳2 As AJS AJS Az? 5th Cycle A26 L L L L L *L NOTE Columr: AdSf*ss Staging Asdr站 of | fi&g SI? L ntusf b 刚 tc LOW Th,* osvio* i戸on

12、$ any additiixai put( (/ eye s than ruixd Column Address CaFumn Address Rfiw Addre&S Row Address Row Address 128K Pages 2.04fi Blocks, 2K Bytes 64 Bylas 这类的页大小大于 2KB 的 Nan dFlash,被称作 big block 的 Na nd Flash,对应的发读写命令地址, 一共 5 个周期(cycle), 而老的 Na nd Flash, 页大小是 256B, 512B,这类的 Na nd Flash 被称作 small b

13、lock 的 nandflash 地址周期只有 4 个。 c) oob:每一个页,对应还有一块区域,叫做空闲区域(spare area )/ 冗余区域(redundant area) 而 Linux 系统中,一般叫做 OO(Out Of Ba nd,这个区域,是最初基于 Na nd Flash 的硬件特 性:数据在读写时候相对容易错误,所以为了保证数据的正确性,必须要有对应 的检测和纠 错机制,此机制被叫做 EDC(Error Detection Code)/EC( Error CodeCorrection, 或者 Error Checking and Correcting ),所以设计了多余

14、的区域,用于放置数据的校验 值。 Oob 的读写操作,一般是随着页的操作一起完成的,即读写页的时候,对应地就 读写了 oob。 关于 oob 具体用途,总结起来有: 1、 标记是否是坏快 2、 存储 ECC 数据 3、 存储一些和文件系统相关的数据。如 jffs2 就会用到这些空间存储一 些特定信息, 4、 而 yaffs2 文件系统,会在 oob 中,存放很多和自己文件系统相关的 信 息。 3、K9F2G08 的引脚定义 Pin Pin Funetiian l,r0: 心心 DATAINPUTSOUTPUTS T阳 LO prs .sed to npji compare dddj6s$ MC

15、 daa. and lOojipLt ddta dur:ng 芒町 吐凶1肿臺 Tne - 0 pins float to hig-z nhen cip s dese or 肿* the o-jiputs are o sailed CLE COMMAMD LATCH ENABLE The CLE i.put canira.s ta path for camms理 g讨 to anc rag tte*. Aha- active My;. ca*irr.ard ar rto (re m产5日词,&臼去& thraugn th* 0 porli on tna f s 3 sdgg o

16、f t-.e gALE ADDRESS LftTCH NABL Ths A_E tontros re aciair pam for addjAss 10 :仙 inions address rg.stars. Addrs ae atehad on the n&ng Ado* of WE with ALE high. CE CHIPNABLE _ The CE Input 4 the device selection comm 讥 ieithe device 腥 m ttw Bus? stats CE hiQh is ignortd and tha daicB doe& not

17、rwtum to standby ce m pragremor aru operabon. RE READMABLE The RE inpul stha 弹阳 data-OLC control, and set .e dfrves iris esta crnQ ITA 0 b Data is va d tREA aftir he fa mg cidga of RE nn ala 爪匕用巾旷is th* rtfimai oo-jmr courier by ona WE WRITEENABLE The WE input corvois 虻虻 tn 10 the .0 pod Commands, a

18、ddrui and data ar laicned or ths rising adge of the 闪T PLES WP WRITE PROTECT T卜电 WP p( (n prov:BE ,n3C.;flde.t pgram,Brass fotadm sjng 口。曲艸 tans Ls Tne nta hign yx- apa 讲凯or s resat tha MP pn) )s active low RB READY/BUSY OUTPUT The RB output indicatss the soius of the 细细 侧 opeiaton.川卜禹 加,i indicaies

19、 that a program G ase farKkm mad canton 氐 in process and ratums ID high state upon com teton it i& an epe n d a in output a nd coes not f!oal to h gp -i cand-Lori .vhen in a chip s secls siec 0/ Aten tJdtp_ts are 已Et,l 曲 Vcc POWFR VCC ifi DD-flfir s-jaoly for ce g GROUND N.C HO CONNECTION Lad 1$

20、 not mrra:ly cowwetftd 107100:用于输入地址/数据/命令,输出数据 CLE:命令锁存使能位,在发送命令之前要先将模式寄存器中设置 CLE 使能(高电平有效)。 ALE:地址锁存使能位,在发送地址之前,要先将模式寄存器中设置 ALE使能(高电平有效)。 CE: (nFCE)芯片的片选信号,操作 nandflash 前应该拉低该位使之选 中该芯片。 RE: (nFRE)读使能,低电平有效,读之前使 CE 有效。 WE (nFWE 写使能,低电平有效,写之前必须使 WEt效。 WP 写保护低电平有效 R/B : (R/nB)Ready/Busy Output,就绪/忙,主

21、要用于在发送完编程/ 擦除命令后,检测这些操作是 否完成,忙,表示编程/擦除操作仍在进行中,就绪表示操作完成。(其中就绪:高 电平,忙:低电平)。 四、常见的 NANDFLAS 的操作 1、要实现对 Nand Flash 的操作,比如读取一页的数据,写入 一页的数据等,都要发送对应的命令,而且要符合硬件的规定,如图: Function 1st Cycle 2nd Cycle Acceptable Command during Busy Read ooh Read for Copy Back OOh 35h Read ID 90h Reset FFh 0 Page Program 0Oh 12h

22、 TA-o-piane Page Program1, flih-10h Ccpyack Program 05h Wli To-Fian CcpyAarx Prcgram5 85-11ti 8ih-i0h Block Erase 60h DOh TvvoPlane Bieck Erase GOhiGOti noh Rar don Data npui 35h n Rar don DataOuput1 05h EOh Read Status 70h 0 Read EDC Siatus; 7Bh 0 NOTE 1. Ra*xlom D弗npLLOutput tan 阳 exsDjtsc H a 2.

23、Rad EDC Status It only avails e on Cooy Back opraticn. 3. 讪 conmad twtAMi tlhancfllh i DfohDi( (ec except 70hana FFr 4. K9F2GOSROA doE not support Twoopticns NAND_BTSffICTH_l 6) column = 1; colusin, cttL);严发送翩地址 Ctrl 孑 D_CTF1_CHGE; ciiip-c3Dd_ctrI(mtd, column 8f ctU);严发送列地址2*/ I _ if (pageyddr != -1

24、 f 厲邛-皿况佃上山p3g&yddrr Ctrl丿;严蓉送疗堆址广/ c/iip-crad_ctrltdf pdge_(adc!i 发送行址2*i WDJCE I 思疏少 E); 严 One isore address cycle for devices 12SM1B */ if (chip-比hipsiE (128 20) chip-cnL(i_ctrl(ntdf page_addr 疋 J*发送行地址3*! NANDCE I N盹 ALE 丿; ) 一 _ 上面的 column 即对应着页内地址,通常情况是 0,如果不是 0 则通过传入进来 的地址除于页地址就可得到相应的列地址了

25、。而 page_addr 即页号,就是通过 要访问的地址,除于页大小,即可得到。 对于其他操作还正在研究中。虽然说上面这些东东大部分都是来 自别人的东西,但是我相信现在它已经变成我自己的东西了。我不记得那个大 帅的博客了,因为我是直接把它的博客给保存到本地了。 非常的说:我突然发现在写这些关于 NAND 驱动的文章的时候,原来我 一直是在改写别人的博客。其实这并不要紧的 ,我也觉得这不仅仅是 一种比较好的学习方法了,为什么呢 ,因为当我在看他的博客的时候,我明白 了一点 撚后当我自己要写的时候。对这个东东又进一步了解一点了。呵 呵 Copy 也分档次了 五、硬件时序到软件代码的演变过程对 na

26、nd_base.c 部分代码的分析 该文件位于 还是把那个读 NAND 勺硬件时序图给贴上,如下图: Read OperationflnlercepledbyCEj :此阶段,是读命令第一个周期,发送的命令为 0 x00。 :此阶段,依次发送列地址,关于这些行地址,列地址等是如何计算出来的, 后面的内容 会有详细解释。 :此阶段是发送对应的行地址 :此阶段是发送读命令第二周期 2nd cycle 所对应的命令,0 x30 :此阶段是等待时间,等待 Nand Flash 硬件上准备好对应的数据,以便后续 读出。 :此阶段,就是一点点地把所需要的数据读出来。 MTD 读取数据的入口是 nand_r

27、ead,然后调用 nand_do_read_ops,此函数主体 如下: Read Operation 3f Xi/ | 1 2?:刁2乂戏 Co umn Addffisf tCSD tAE BE CE RE Row Address RJA; static int nan d_do_read_ops(struct mtdnfo *mtd, loff_t from, struct mtd_oob_ops *ops) /*此处省略部分代码*/ /* 7省略 */ 000000000000000 if (likely(s ndcmd) /*#defi ne NAND_CMD_READO 0*/ /*1

28、)*读取数据前肯定要先发送对应 的读页命令*/ 0 x00, page); sn dcmd = 0; /* Now read the page into the buffer */ if (uni ikely(ops-mode = MTD_00B_RAW) ret = chip-ecc.read_page_raw(mtd, chip, bufpoi, else if (!alig ned & NAND_SUBPAGE_READ(chip) ret = chip-ecc.read_subpage(mtd, chip, col, else /* 执行到这里 read_page 函数读取对应

29、的 ret = chip-ecc.read_page(mtd, chip, page); if (ret pagebuf = realpage; memcpy(buf, chip-buffers-databuf + col, bytes); buf += bytes; 000000000000000000 0 0 0 0 0 while(1) OOOOOOOOO chip-cmdfu nc(mtd, NAND_CMD_READ0, page); & !oob) bytes, bufpoi); 数据了 */ bufpoi, if (mtd-ecc_stats.failed - stats

30、.failed) return -EBADMSG; return mtd-ecc_stats.corrected - stats.corrected ? -EUCLEAN 0; 上面这些代码都不需要我们去实现的,使用 MTD 层的自定义代码就行。 nan d_comma ndp 的分析 static void nan d_comma nd_lp(struct mtd_i nfo *mtd, un sig ned int comma nd, int colu mn, int page_addr) register struct nan d_chip *chip = mtd-priv; /* Em

31、ulate NAND_CMD_READOOB */ if (comma nd = NAND_CMD_READOOB) colu mn += mtd-writesize; comma nd = NAND_CMD_READ0; /* Comma nd latch cycle */ /*此处就是就是发送读命令的第一个周期 1st Cycle 的命令,即 0 x00, 对应着上述步骤中的*/ chip-cmd_ctrl(mtd, comma nd & 0 xff, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); if (colu mn != -1 | page

32、_addr != -1) in t ctrl = NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE; /* Serially in put address */ if (column != -1) /* Adjust colum ns for 16 bit buswidth */ if (chip-optio ns & NAND_BUSWIDTH_16) colu mn = 1; /*发送两个 column 列地址,对应着上述步骤中的 */ chip-cmd_ctrl(mtd, colu mn, Ctrl);/* 发送列地 址 1*/ ctrl &=

33、 NAND_CTRL_CHANGE; chip-cmd_ctrl(mtd, colu mn 8, ctrl);/* 发送列地 址 2*/ if (page_addr != -1) /*接下来是发送三个 Row行地址,对应着上述步骤 中的*/ chip-cmd_ctrl(mtd, page_addr, ctrl);/* 发送行 地址 1*/ chip-cmd_ctrl(mtd, page_addr 8,/* 发送行地址 2*/ NAND_NCE | NAND_ALE); /* One more address cycle for devices 128MiB */ if (chip-chipsi

34、ze (128 cmd_ctrl(mtd, page_addr 16,/* 发送 行地址3*/ NAND_NCE | NAND_ALE); chip-cmd_ctrl(mtd, NAND_CMD_NONA(ND_NC|ENAND_CTRL_CHANGE); /* * program and erase have their own busy han dlers * status, seque ntial in, and deplete1 n eed no delay */ switch (comma nd) 0000000000000 return; /* 复位 */ case NAND_CM

35、D_RESET: if (chip-dev_ready) break; udelay(chip-chip_delay); chip-cmd_ctrl(mtd, NAND_CMD_STATUS, NAND_NCE|NAND_CLE | NAND_CTRL_CHANGE); chip-cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); while (心 hip-read_byte(mtd) & NAND_STATUS_READY); return; /*读忙信号*/ case NAND_CMD_RNDOUT: /* No r

36、eady / busy check n ecessary */ chip-cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART, NAND_NCE|NAND_CLE | NAND_CTRL_CHANGE); chip-cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); return; /*接下来发送读命令的第二个周期 2nd Cycle 的命令,即 0 x30,对应着上述步 骤 中的*/ case NAND_CMD_READ0: chip-cmd_ctrl(mtd, NAND_CMD_READSTART, NAN

37、D_NCE|NAND_CLE | NAND_CTRL_CHANGE); chip-cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); /* This applies to read comma nds */ default: /* * If we dont have access to the busy pin, we apply the give n * comma nd delay */ if (!chip-dev_ready) udelay(chip-chip_delay); return; /* Apply this s

38、hort delay always to en sure that we do wait tWB in * any case on any machi ne. */ /*此处是对应着中的 tWB 的等待时间*/ n delay(IOO); /*接下来就是要等待一定的时间,使得 NandFlash 硬件上准备好数据,以供你 之 后读取,即对应着步骤*/ nan d_wait_ready(mtd); 还有一个步骤没有实现那就是步骤了一点一点的把数据读出来 nan d_read_page_hwecc 分析 static int nan d_read_page_hwecc(struct mtdnfo

39、*mtd, struct nan d_chip *chip, uin t8_t *buf, i nt page) 0000000000000000000000 for (i = 0; eccsteps; eccsteps-, i += eccbytes, p += eccsize) chip-ecc.hwctl(mtd, NAND_ECC_READ); /*这个最重要了这才是真正的从 NAND 勺缓冲区中把数 据给读出来*/ chip-read_buf(mtd, p, eccsize); chip-ecc.calculate(mtd, p, &ecc_calci); 000000000

40、0 return 0; 上面的 read_buf, 就是真正的去读取数据的函数了, 由于不同的 NandFlash co ntroller 控制器所实现的方式不同,所以这个函数必须在你的 Nand Flash 驱动中实现,即 MTD 层,能帮我们实现的都实现了,不能实现的,那肯定是我 们自己的事情了。接下来的工作是什么 ?MTD 原始设备和硬件驱动层的交互 了.这个才是我们要去真正实现的。0 进过前面 3 篇文章对 NANDFLAS 的些硬件特性以及 MTD 勺上层操作已经有 了一个大体概念,这些东西的重要性就像你要吃饭那么你首先得学会拿筷子道理 一样吧,应该一样的。 五、MTD 原始设备层和

41、硬件驱动层的桥梁:CT3SC EE 熟悉这几个重要的结构体:linu x/mtd/mtd.h struct mtdnfo u_char type; /*内存技术类型(包括 MTD_RAM,MTD_ROM,MTD_NANDFL*S H uin t32_t flags; /*MTD 设备属性标志*/ uin t64_t size; / Total size of the MTD uint32_t erasesize;/MTD 设备的擦除单元大小, 对于 NandFlash 来说 就是 Block的大小 uin t32_t writesize;/ 最小的可写单元的字节数 uin t32_t oobs

42、ize; uin t32_t oobavail; / Amou nt of OOB data per block (e.g. 16) / Available OOB bytes per block un sig ned int erasesize_shift; un sig ned int writesize_shift; /* Masks based on erasesize_shift and writesize_shift */ un sig ned int erasesize_mask; un sig ned int writesize_mask; / Kern el-only stu

43、ff starts here. const char *n ame; int in dex; /* ecc layout structure pointer - read only ! */ struct nan d_ecclayout *ecclayout; 址(Mil nud Jaihlc del mid JikLilttd device 11 Yem? Fih (uur-llnsli del nii4 tCC 1 I mtd.nurt it ion mtdpurt c) - 1 Flash蚩动 /* Data for variable erase regions. If numerase

44、regions is zero, * it means that the whole device has erasesize as give n above. * 一般为 1 吧 */ int nu meraseregi ons; /擦除区域的指针 struct mtd_erase_regio nnfo *eraseregi ons; /擦除函数将一个 erase_info 结构放入擦除队列中 int (*erase) (struct mtdnfo *mtd, struct erase_i nfo *in str); /* This stuff for eXecute-In-Place */

45、 /* phys is opti onal and may be set to NULL */ int (*poi nt) (struct mtdnfo *mtd, loff_t from, size_t le n, size_t *retle n, void *virt, resource_size_t *phys); /* We probably should nt allow XIP if the un poi nt isnt a NULL */ void (*unpoint) (struct mtdnfo *mtd, loff_t from, size_t len); /* Allow

46、 NOMMU mmap() to directly map the device (if not NULL) * - retur n the address to which the offset maps * - return -ENOSYS to in dicate refusal to do the mapp ing */ un sig ned long (*get_ unm apped_area) (struct mtd_i nfo *mtd, un sig ned long len, un sig ned long offset, unsigned long flags); /* B

47、ack ing device capabilities for this device * - provides mmap capabilities */ struct back in g_dev_i nfo *back in g_dev_i nfo; /read 和 write 分别用于 MTD 设备的读和写 int (*read) (struct mtdnfo *mtd, loff_t from, size_t len, size_t *retle n, u_char *buf); int (*write) (struct mtdnfo *mtd, loff_t to, size_t le

48、n, size_t *retle n, const u_char *buf); int (*pa ni c_write) (struct mtdnfo *mtd, loff_t to, size_t len, size_t *retle n, const u_char *buf); /读写 MTD 设备的 00B 区域的数据 int (*read_oob) (struct mtdnfo *mtd, loff_t from, struct mtd_oob_ops *ops); int (*write_oob) (struct mtdnfo *mtd, loff_t to, struct mtd_

49、oob_ops *ops); /访问一些受保护的寄存器 int (*get_fact_prot_info) (struct mtdnfo *mtd, struct otp_info *buf, size_t len); int (*read_fact_prot_reg) (struct mtd nfo *mtd, loff_t from, size_t len, size_t *retle n, u_char *buf); int (*get_user_prot_info) (struct mtdnfo *mtd, struct otp_info *buf, size_t len); int

50、(*read_user_prot_reg) (struct mtdnfo *mtd, loff_t from, size_t len, size_t *retle n, u_char *buf); int (*write_user_prot_reg) (struct mtdnfo *mtd, loff_t from, size_t len, size_t *retle n, u_char *buf); int (*lock_user_prot_reg) (struct mtdnfo *mtd, loff_t from, size_t len); /* kvec-based read/write

51、 methods. NB: The co unt parameter is the nu mber of _vectors_, each of which contains an (ofs, le n) tuple. */ int (*writev) (struct mtdnfo *mtd, const struct kvec *vecs, un sig ned long coun t, loff_t to, size_t *retle n); /* Sync */* 同步 */ void (*s ync) (struct mtdnfo *mtd); /* Chip-supported dev

52、ice lock ing */ int (*lock) (struct mtdnfo *mtd, loff_t ofs, ui nt64_t len); int (*u nl ock) (struct mtdnfo *mtd, loff_t ofs, uin t64_t len); /* Power Man ageme nt fun cti ons */ int (*suspe nd) (struct mtd_i nfo *mtd); void (*resume) (struct mtdnfo *mtd); /* Bad block man ageme nt fun cti ons */ in

53、t (*block_isbad) (struct mtdnfo *mtd, loff_t ofs); int (*block_markbad) (struct mtdnfo *mtd, loff_t ofs); struct no tifier_block reboot_ no tifier; /* default mode before reboot */ /* ECC status in formatio n */ struct mtd_ecc_stats ecc_stats; /* Subpage shift (NAND) */ int subpage_sft; /私有数据 指向 map

54、_info 结构 void *priv; struct module *ow ner; struct device dev; int useco unt; /设备驱动回调函数 int (*get_device) (struct mtdnfo *mtd); void (*put_device) (struct mtdnfo *mtd); ; 上面的 read()、write()、read_oob()、等都是 MTD 设备驱动要实现的主要 函数, 不过这些函数都是透明的不需要我们自己去实现 ,因为 Linux 在 MTD 的下层实现 了针对 NORFLAS 和 NANDFLAS 的通用 mtd_i

55、nfo 成员函数。 感觉没什么可写的了,因为这些都不是我要关注的东西,但是又不能不知道有这 么回事 这些结构体还是得了解了解 driver/mtd/mtdpart.c /* Our partiti on node structure */ struct mtd_part struct mtdnfo mtd; / 分区信息 struct mtdnfo *master; / 该分区的主分区 uint64_t offset; /该分区的偏移量 struct list_head list; ; struct nand_ecclayout *ecclayout; /* out of band layou

56、t for this partition (NAND only)*/ ; 一个 MTD!始设备可以通过 mtd_part 分割成数个 MTD!始设备注册进 mtd_table , mtd_table 中的每个 MTD 原始设备都可以被注册成一个 MTD 设备, 有两个函数可以完成这个工作, 即 add_mtd_device 函数和 add_mtd_partitions 函数。 其中 add_mtd_device 函数是把整个 NAND FLASH 注册进 MTD Core,而 add_mtd_partitions 函数则是把 NAND FLASH 勺各个分区分别注册进 MTDCore int

57、add_mtd_device(struct mtdnfo *mtd) int del_mtd_device(struct mtdnfo *mtd) int add_mtd_partitions(struct mtd_info *master,structmtd_partitions *parts,i nt n bparts) int del_mtd_partitions(struct mtdnfo *master) 当 MTD 原始设备调用 add_mtd_partitions() 的时候它会对每一个新建分区 建立一个 struct mtd_part 结构将其加入 mtd_partitions

58、 中并调用 add_mtd_device()将此分区做为 MTC 设备注册进 MTD Core,成功的时返回 0 重点关注一下 add_mtd_partitions(struct mtdnfo *master,struct mtd_partitions *parts,int nbparts)其中 master 就是这个 MTD 原始设备,parts 即 NAND 勺分区信息,nbparts 指有几个分区。那么 parts 和 nbparts 怎么来的 呢,其实上面有一句话已经说了。举个例子在我们移植 Linux 内核到我们的开 发板的时候我们会对 NANDFLAS 进行分区这 eilian24

59、0_default_nand_part 就 是起到上面这两个参数的作用如下: static struct mtd_partiti on eilia n240_default_ nan d_part = 0 = .n ame = bootloader,/*uboot 存放的地址对应 dev/mtdblock0*/ .size = 0 x00040000, /* 大小mtd_partition 会在 MTD 原始设备调用 区参数 /lin ux/mtd/partitio n.h struct mtd_partiti on char *n ame; uin t64_t size; uin t64_t

60、 offset; space */ uin t32_t mask_flags; for this partiti on */ add_mtd_partitio ns() 的时候传递分 /* identifier string */ /* partition size */ /* offset within the master MTD /* master MTDflags to mask out void (*write_buf)(struct mtdnfo *mtd, const .offset = 0, , 1 = .n ame = param, .offset = 0 x00040000,/* 如果 UBOO 比较大就放在这个区域 可以将前面的覆盖掉*/*0 x00040000 是偏移量*/ .siz

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论