已阅读5页,还剩16页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Tornado之TrueFFS编程者指南按:这篇文章主要根据tornado2.0 for arm的在线帮助写成,前面大部分是翻译过来的,后面将详细介绍mtd驱动的编写,并会给出实际的例子。trueffs对于作嵌入式系统来说非常有用,我希望这儿的每一个开发者都能掌握它。我对trueffs的研究还很浅薄,所以如果有信口开河的地方还请大方之家斧正。如果能对大家有所帮助,也就无枉此笔了。一 概述1简介 Tornado的TrueFFS是和vxworks兼容的一种M-Systems Flite实现方式,版本为2.0。它为种类繁多的flash存储设备提供了统一的块设备接口,并且具有可重入、线程安全的特点,支持大多数流行的CPU构架。 有了Tornado的TrueFFS,应用程序对flash存储设备的读写就好象它们对拥有MS-DOS文件系统的磁碟设备的操作一样。这样 TrueFFS就屏蔽了下层存储介质的差异,为开发者提供了统一的接口方式。然而,当你设计一个嵌入式系统的时候,了解flash存储器和磁碟设备的不同之处还是很重要的。尽管flash存储器不可能适用于所有的嵌入式系统,但由于flash存储器具有体积小,耗电省,非易失存储的特性,在许多的环境下尤其在移动设备和手持设备领域里它成为了理想的选择。 Flash存储器在拥有众多优点的同时也有一些自身的缺点。首先,它在写之前必须要进行擦除操作,而且不能一个字节一个字节的擦,它只能以一个扇区、一个块或者整片的方式进行擦操作。它的写和擦操作都需要较复杂的步骤才能完成,这就降低了它的易使用性。另外,Flash存储器最大的一个缺点就是寿命有限,可擦除的次数因不同厂商而有所不同,一般都在1万到10万次左右。 一个运行在flash存储器上性能良好的块设备应该能针对可移动的媒体(如flash卡)处理各种复杂的情况。比如,完全有这样的可能:当驱动程序正在进行写操作时用户却把flash卡抽出来了。这有时会造成灾难性的后果。幸运的是,TrueFFS在设计时已经仔细考虑了flash存储器的各种特性,以及掉电和用户由于不耐烦或好奇的原因而猛地拔出flash卡想看看发生了什么事的情况。2TrueFFS和块数据 Flash存储器不能无限次重复使用。它的每个扇区的擦除次数虽然很大,但却有限。因此,随着使用次数的加长,它最终会变成只读状态。所以我们应该尽最大可能延长它的寿命。行之有效的方法就是平衡使用所有的存储单元,而不让某一单元过度使用。这种技术被称之为wear leveling。TrueFFS使用一种基于一张动态维护表的block-to-flash(块对应于flash)传输系统来实现wear leveling技术。当块数据被修改、移动,或碎片回收后,这张维护表会自动调整。 就象块设备驱动需要的那样,TrueFFS把flash存储空间映射到一个特殊的连续存储块队列中,以便文件系统可以对它进行数据的读写。这些块被从0开始连续编号。 从一个数据块中读取数据的操作非常直接。文件系统请求指定块的内容,TrueFFS响应后将块号传送到flash存储匹配器(flash memory coordinates)中,找到之上的数据,然后把数据返回给文件系统。向块写数据也一样的直接,只要这个块还没有被写过。TrueFFS要作的就是传送块号到flash存储匹配器(flash memory coordinates)中,并写数据到所指定的地址。但如果写请求试图修改一个已经写过了的块设备内容,情况就复杂了。TrueFFS先是找到flash空间中一个已经可写的区域,然后把修改后的块数据写到那里。当数据安全地写完后,TrueFFS更新它的block-to-flash映射结构,以使块现在映射的区域为放置修改后数据的区域。这就保证了一定程度上的wear leveling。然而,如果存储在flash上的一些数据本质上是静态的,只有在修改时wear leveling才会产生一种被称为静态文件锁定的问题。 存储这些静态数据的区域根本不会被轮循使用,这将降低flash期望的生命值。TrueFFS通过强制转移静态区域的方法成功克服了静态文件锁定的问题。因为block-to-flash映射表是动态的,TrueFFS能够以对文件系统不可见的方式管理这些wear-leveling转移。由于绝对强制 wear-leveling方式会对性能产生一些负面的影响,所以TrueFFS采取了一种非绝对wear-leveling的算法。它保证了所有空间的使用近似平等。最后,TrueFFS的wear-leveling算法更增强了突破被称为死锁这种模式的性能。 所谓死锁就是一些简单的wear-leveling算法只是两个或多个单元长时间循环而忽略了其余的单元的现象。3碎片回收 块数据的修改使得flash的一些块区域不再包含合法的数据,并且这些区域在擦除之前变得不可写。如果没有机制来回收这些区域,flash很快就会变成只读的状态了。不幸的是由于这些块不可以单独擦除,回收这些块就有些复杂了。单次擦除被限制在一个叫作擦除单元(erase unit)的较大范围内。如对于Intel的flash器件来说是64k字节。 TrueFFS使用一种被称为碎片回收(garbage collection)的机制来回收那些不再包含有效数据的块。该机制从一个预擦除单元(source erase unit)内拷贝所有的有效数据块到另一个新的被称为转移单元(transfer unit)的擦除单元。TrueFFS然后更新block-to-flash映射表再擦除这个废旧的预擦除单元。 这样,原来的块出现在外界时仍然包含了原来的数据,虽然这些数据现在已经存放在flash存储器的其它空间。 怎样触发碎片回收功能呢?如果太频繁,则会降低wear-leveling的效果,并影响整个flash的性能。因此在TrueFFS内部,碎片回收只是在块分配算法需要的时候才会触发。块分配算法尽量保持在同一个擦除单元(erase unit)内有一段连续的自由块池。如果块池变得太小,块分配算法就会马上采用碎片回收算法进行碎片回收。然后碎片回收算法就会找到并回收和下面标准最吻合的擦除单元(erase unit): 废块最多 擦除周期数据最少 最静态的区域 另外,碎片回收算法也会采用随机选择的处理方法。这样可以保证回收处理能够均匀地覆盖整修存储空间,而不会由于应用程序使用数据的方式而偏差。4.块分配和关联数据集结的方法为了提高数据的读取效率,TrueFFS使用一种空间分配策略:将关联的数据(如由同一个文件的内容组成的多个块)集结到同一个单独擦除单元(erase unit)内的一段连续的区域中。为此,TrueFFS尽量在同一个擦除单元(erase unit)内维持一个由多个物理上连续自由的块组成的存储池。如果这样连续的存储池无法实现,TrueFFS会尽量保证池中的所有块是在同一个擦除单元(erase unit)内。如果连这样的情况也不可能的话,TrueFFS会尽量把块池分配到一个拥有最多可用空间的擦除单元内。这种集结关联数据的途径有几个好处。首先,如果TrueFFS必须从一个小的存储窗口(memory window)来访问flash,那么这样集结了的关联数据可以减少调用映射物理块(physical blocks)到该窗口的次数。这样可以加快文件继续访问速度(通常是这样)。其次,这种策略可以减少碎片的产生。这是因为删除一个文件可以释放掉更容易回收的完整块。这意味着碎片回收会变得更快。另外,它可以使属于静态文件的多个块存放在同一地方,这样当wear leveling算法决定移动静态区域时,转移这些块就变得更加容易了。5TrueFFS中的错误恢复向flash写数据有时可能会出错,比如在响应文件系统写请求时、碎片回收期间甚至在TrueFFS格式化或擦除flash时。在这些情况下, TrueFFS能够从错误中恢复过来。但在新数据第一次写入flash时,如果出错就会丢掉这些数据。然而,TrueFFS非常仔细地保证所有已经存放在 flash上的数据是可恢复的。TrueFFS健壮的关键是它使用了一种“先写后擦”(erase afer write)的策略。当更新flash一个扇区的数据时,只有在更新操作完成并且新存储的数据校验成功后,先前的数据才会被允许擦掉。这样的结果是数据扇区不能处于部分写状态。操作成功的话新扇区的数据有效,否则老扇区的数据有效。很明显,这样有利于用户已经写到flash媒体上的数据的稳定性。“先写后擦”对flash存储映射表也有积极的影响。比如,尽管TrueFFS采用了用一张RAM-resident的映射表来记录flash存储器内容的方式,但TrueFFS还会非常小心,决不将临界映射信息只放在RAM中。因此,如果更新映射信息时遇到掉电或者flash媒体被移除的情况,原来的映射信息依然是可用的。当电源恢复(或者flash重新连接),TrueFFS能够使用存放在flash上的信息来重建或校验flash映射表的RAM- resident版本。这样,映射信息能够存在于媒体的任何地方,这在开始看来是一项不可能的工作。幸运的是,flash中的每一个擦除单元(erase unit)都在一个可以预知的位置放置了头信息(一般在该扇区的0偏移地址处)。仔细核对在每一个擦除单元(erase unit)中的头信息,TrueFFS可以重建或者校验flash映射表的RAM拷贝。所以掉电后唯一后果是如果这时正在回收碎片则碎片回收需要重新开始。如果写操作第一次尝试失败,TrueFFS通常不会报告给用户。相反,它会使用它的动态映射能力在flash的另一个不同地方来重新进行一次写操作。 TrueFFS通过这种自动修复错误的方法确保了数据的完整性。当flash媒体进入它生命极限的时候,这种写错误修复机制变得显著有用。这时, flash的写/擦失败变得更加频繁,但用户看到的结果只是性能的缓慢降低(因为写操作重试的需要)。TrueTFFS回收碎片的方式是通过将数据从一个旧的单元移到另一个新的单元(置换单元),然后擦除这个旧单元的方式来完成的。这样在进行写数据或者擦除旧单元的过程中碎片回收可能失败。为了最小化这种失败的发生,TrueTFFS将flash媒体格式成包含多个置换单元的方式。这样,如果写到一个置换单元的操作失败,TrueTFFS就会尝试写到另一个置换单元上去。对用户数据没有直接影响,但原来的置换单元不再接受新的数据,变成了只读状态。有时,flash第一次格式化时就被发现有些空间不可用。倘若坏单元的数目没有超过置换单元的数目,格式化能够成功。对用户的影响也只是flash容量减少了。6.引导映象和TrueFFS共享flash存储空间缺省情况下,TrueFFS格式化工具会把整个flash空间用于TrueFFS。虽然TrueFFS的转译服务结合一个文件系统可以为数据的管理提供很多好处,但这也同样增加了flash作为一个引导设备时的复杂性。唯一可行的解决方案就是把TrueFFS排斥在flash的引导区外。幸运地是,TrueFFS自带的格式化工具可以允许你从一个偏移地址开始格式化flash。这样就创建了一个TrueFFS不能触及的区域,你可以使用 TrueFFS的一些工具来管理这个区域。从而你能把一个引导映象写到这个区域或者从上面擦除。不过,你得十分小心地使用这些工具,因为它们不仅可能过度使用flash,也可能写操作时超过这个区域,从而破坏掉TrueFFS。7TrueFFS的层结构简介如图11所示,TrueFFS包含三层:翻译层(translation layer),MTD层(MTD layer),socket层(socket layer)。图1-1 TrueFFS的层结构翻译层主要实现TrueFFS和dosFs之间的高级交互功能。它也包含了控制flash映射到块、wear-leveling、碎片回收和数据完整性所需的智能化处理功能。目前有三种不同的翻译层模块可供选择。选择哪一种层要看你所用的flash介质是采用NOR-based, 还是NAND-based, 或者SSFDC-based技术而定。Socket层则是提供TrueFFS和板卡硬件(如flash卡)的接口服务。其名字来源于用户可以插入flash卡的物理插槽。用来向系统注册socket设备,检测设备拔插,硬件写保护等。后面将详细讲解它的功能。MTD层(Memory Technology Drivers)功能主要是实现对具体的flash进行读、写、擦、ID识别等驱动,并设置与flash密切相关的一些参数。TrueFFS已经包含了支持Intel,AMD以及samsung部分flash芯片的MTD层驱动。新的芯片需要新的MTD支持,你可以使用一个标准的接口来加入这些驱动。以上三部分,我们关心的将会是后两层。当在vxworks下配置TrueFFS时,你必须为每一层至少包含一个软件模块。后面我们将详细讨论。8TrueFFS配置显示工具 主要有两个:tffsShow()和tffsShowAll().前者为一个指定的socket接口打印设备信息。它的主要用来确定当要写一个引导映象时所需要的擦除单元数。后者则是提供在vxworks中已注册的所有socket接口的信息。二 起步1介绍本章将告诉你在Tornado下怎样去配置TrueFFS并包含它。为了在一个vxworks映象中包含TrueFFS,你必须编辑config.h文件并定义INCLUDE_TFFS。这使得vxworks的初始化代码调用tffsDrv()来创建管理TrueFFS所需的结构和全局变量,并为所有挂接了的flash设备注册socket组件驱动。在链接的时候,通过解析与tffsDrv()相关联的符号(symbols)可以将TrueFFS所必需的软件模块链接到vxworks映象中。为了支持TrueFFS,每一个bsp必须包含一个sysTffs.c文件。它将TrueFFS所有的层(翻译层,socket层和MTD层)链接到一起并和vxworks绑定。因此,你必须编辑这个文件并决定哪一种MTD和翻译层模块应该包含到TrueFFS中。另外,如果你的目标系统包含了一个MMU 单元,你还得编辑sysLib.c中的sysPhysMemDesc 数组。 在重新编译vxworks映象并重启目标系统后,你应该可以使用诸如格式化flash、创建TrueFFS块设备、绑定此块设备到dosFs所必要的功能。2配置和使用TrueFFS总述配置vxworks使其包含TrueFFS需要编辑如下: Makefile 在bsp的.o列表中加入sysTffs.o config.h 包含TrueFFS sysLib.c 调整ROM区的描述 sysTffs.c 确定包含在TrueFFS中的功能特点 对于一个支持TrueFFS的BSP来说,以上所有文件必须放在target/config下你的BSP配置目录里。但是, sysTffs.c不会自动捆绑到这个目录。相反,几个sysTffs.c不同的版本被捆绑到src/drv/tffs/sockets下,如 ads860-sysTffs.c, mv177-sysTffs.c, hkbaha47-sysTffs.c等等。阅读一下src/drv/tffs/sockets/README这个文件,你就可以确定哪一个 bspname-sysTffs.c适合你的BSP。这个README也描述了要支持TrueFFS所有BSP需要修改的特定地方。当你启动该映象后,它会自动运行tffsDrv( )。这个函数自动为每一个flash设备注册一个socket组件。这时flash设备还没有挂上块设备驱动。但socket组件驱动已经为调用 tffsDevFormat( )函数提供了充足的条件。为了使用TrueFFS,必须用这个函数来格式化flash媒体。为了在socket组件的顶部创建一个TrueFFS块设备并 mount dos文件系统到这个块设备上,你还得调用usrTffsConfig()函数。下面就具体讲讲这几个文件的修改。修改Makefile:为了加入sysTffs.o的编译,你应该在其中加入如下的宏定义: MACH_EXTRA = sysTffs.o修改config.h:对于大多数的BSP来说,包含TrueFFS也就是要在config.h中加入如下的两个宏定义:#ifndef INCLUDE_TFFS#define INCLUDE_TFFS#endif#ifndef INCLUDE_DOSFS#define INCLUDE_DOSFS#endif当然如果你想使用tffsShow()和tffsShowAll()来查看socket信息,你还要加上#define INCLUDE_SHOW_ROUTINES这样一条宏定义。修改sysLib.c:如果你的目标系统包含了MMU模块,那么它的BSP在sysLib.c文件里面就定义了一个sysPhysMemDesc 表。典型地,这个表告诉MMU包含启动映象(boot image)的存储区域是WRITABLE_NOT(不可写)的,或者说是ROM型的。ROM曾经是唯一能可靠存储启动映象的技术,所以vxworks一直默认包含一个启动映象的存储区域为ROM型的。然而随着flash技术的到来,这种可能性已经得到了扩展。因为它即可写也可以可靠地存储启动映象。所以你必须编辑sysPhysMemDesc ,重新设置启动映象所在的存储区域为WRITABLE(可写)型的。 修改sysTffs.c:这个文件的主要功能就是定义一些BSP特殊的socket代码,作为连接flash硬件和vxworks的桥梁。缺省地,一个WRS支持的 sysTffs.c包含了所有的翻译层模块,所有的MTD层模块,以及tffsBootImagePut( ), tffsShow( ), tffsShowAll( )这样的工具函数。为了减小映象的大小,你可以通过编辑sysTffs.c来去掉一些你知道对你的应用不必要的模块。首先,我们应该选择翻译层模块。根据不同的flash技术有三种翻译层供你选择,如下表所示:宏定义符号 |相应的flash技术INCLUDE_TL_NFTL | NAND-based flashINCLUDE_TL_FTL | NOR-based flashINCLUDE_TL_SSFDC | SSFDC flash 我们一般的flash芯片如sst39vf040,sst39vf160,am29lv160等都是NOR-based flash型,所以可以只“#defineINCLUDE_TL_FTL”。接下来,我们选择MTD层模块。Vxworks自带了支持一些flash型号的MTD层驱动模块。如下表所示:宏定义符号 相应的flash设备INCLUDE_MTD_I28F016 Intel 28f016INCLUDE_MTD_I28F008 Intel 28f008INCLUDE_MTD_I28F008_BAJA Intel 28f008 on the Heurikon Baja 4000INCLUDE_MTD_AMD AMD, Fujitsu: 29F040,80,16 8-bit devicesINCLUDE_MTD_CDSN Toshiba, Samsung: NAND CDSN devices INCLUDE_MTD_DOC2 Toshiba, Samsung: NAND DiskOnChip2000INCLUDE_MTD_CFISCS CFI/SCS deviceINCLUDE_MTD_WAMD AMD, Fujitsu 29F040,80,16 16-bit devices同翻译层一样你也可以去掉一些不必要的模块宏定义。比如,如果你使用的是8bit数据宽度的AMD29F040,那么你完全可以undefine掉除了INCLUDE_MTD_AMD以外的其它宏定义。如果你所用的flash型号很不幸不在这里面,那么你只有自己写MTD层驱动模块了。这时你可以在 src/drv/tffs下找一个比较类似的驱动来修改然后把它放到你的BSP目录下,并修改Makefile加入其.o文件到MACH_EXTRA的. o文件列表中。当然你也可以把它放到src/drv/tffs下,同样地修改该目录下的Makefile文件。另外,缺省情况下sysTffs.c定义了INCLUDE_TFFS_BOOT_IMAGE。这将在sysTffs.o中自动包含了 tffsBootImagePut( )函数。通过使用tffsBootImagePut( )函数,你可以绕过TrueFFS(和它的翻译层)而直接向flash存储空间写数据。用tffsDevFormat( )函数可以将TrueFFS管理区域的起始地址定位到一个偏移地址上,从而在TrueFFS之外留下一个自由区域,可以用来放置启动映象(boot image)。tffsBootImagePut( )可以将启动映象写入这个自由区域。再下来是选择socket层特征。尽管在sysTffs.c文件中设置一些宏定义可以加入翻译层模块和MTD层模块以及其它的一些相关工具模块,但文件的大部分内容还是专注于socket组件驱动程序的定义。这些驱动程序是一个标准的API,作为连接设备硬件和vxworks的桥梁。它们在很大程度上由你使用的flash硬件来决定相应的功能定义。Tornado的TrueFFS支持三种通常种类的flash硬件: PC flash卡(可移动的flash媒介) DiskOnChip 2000 设备 板上固定的flash片组 后面两者都是不可移动的媒介,它们的socket接口相对来说要简单一些。所以对于大多数标准API函数来说,可以简单地“作一点或根本不作”。然而 PC flash卡则是可移动的设备,所以接口处理就要复杂得多。大多数BSP提供的接口程序都很精干,但过于简单。它们都假定socket包含了一张 flash卡,但不支持热拔插。目前,这种简单的PCIC驱动有big-endian 和little-endian两种版本。big-endian版本是由ads860的BSP带有的,little-endian版本则是由PC386和 PC486的BSP提供的。相对于PCIC驱动有两种宏定义:INCLUDE_SOCKET_PCIC0和 INCLUDE_SOCKET_PCIC1。前者是为slot 0创建一个socket接口,后者是为slot 1创建一个socket接口。对于PC386和PC486来说,你可选择一个比简单的PCIC更加完善的socket接口。对此,后面我们有时间的话还会细讲。3.格式化Flash 为了使用TrueFFS,要先调用tffsDevFormat( )函数来格式式flash。在格式化的过程中,该函数先擦除flash然后将TrueFFS数据管理结构(data-management structures)写到位于每个擦除单元(如扇区)起始处的头里。tffsDevFormat( )需要两个输入参数:设备号(socket组件号)和一个指向格式化参数(FormatParams)的指针。设备号由socket组件在系统中注册的先后顺序决定。而FormatParams结构则是传递如何格式化此flash的值。这个结构定义如下:typedef struct /* FTL formatting section */ long int bootImageLen;/*bootImage需要从flash媒体开始处预留的长度*/ unsignedpercentUse;/*flash媒体被格式化的百分率,为了提高TrueFFS的性能,不要设为100%,以便任何时候都有空余空间。默认值为99%*/ unsignednoOfSpareUnits;/*空余擦除单元数目,目的在于flash出现坏块时可以用它来替代,默认为1*/ unsigned long vmAddressingLimit;/* FTL 在RAM中映射的大小,默认为61Kbytes*/ FLStatus (*progressCallback)(int totalUnitsToFormat, int totalUnitsFormattedSoFar); /* 回调函数,用来监测flash擦除过程,如果返回值为OK,则继续,否则停止擦除。*/ /* DOS formatting section */ char volumeId4; /*Dos卷标号*/ char FAR1 * volumeLabel;/*Dos卷标字符串,如果为NULL,则没有卷标*/ unsigned noOfFATcopies; /* 文件分配表(FAT)的拷贝数,正常情况下只使用一个FAT,而另一个只有在使用的FAT被破坏的情况下用来恢复分配表,默认为2*/ unsigned embeddedCISlength;/* CIS 嵌在单元头部(unit header)之后的字节长度*/ char FAR1 * embeddedCIS;/* 单元头部被结构化用来作为一个PCMCIAtuple 链(a CIS)的起始,它包含了一个数据组织tuple,通常用16进制的0xFF来标示上一个单元头部结束的位置(end-of-tuple- chain)。*/ FormatParams;/* 默认的FormatParams 结构*/#define STD_FORMAT_PARAMS 0, 99, 1, 0x10000l, NULL, 0,0,0,0, NULL, 2, 0, NULL。一般来说,你可以把这个指针赋为NULL(0),这样就告诉tffsDevFormat( )使用在dosformt.h中定义的默认FormatParams结构。在这个默认的结构中定义的值对于绝大多数的应用已经足够了。然而,如果你想在该 flash媒体上共用TrueFFS和引导映象(boot image),这个缺省的结构就不太合适了。你必须修改bootImageLen的值,以适应boot Image的大小,tffsDevFormat( )在格式化的时候会保留这一部分空间。另外,我们还应该了解另一个格式化函数sysTffsFormat( )。它在内部其实还是调用了tffsDevFormat( )函数。它没有入口参数,它使用自己的FormatParams参数来格式化flash。要了解更详细的信息你可以参阅bsp中sysTffs.c文件中的sysTffsFormat( )函数。4设置簇的大小 在为TrueFFS格式化一个flash设备时,扇区都被分配到簇里面,一个簇包含的扇区数由flMinClusterSize来决定,这是一个在 dosFormat.c中定义的int型全局变量。合法的值是2的非负数n次幂(1,2,4,8,)。默认值为4。你可以减小这个值以获得更好的存贮密度,但由于FAT的入口数是有限的,flash媒体上的可寻址空间也会相应减小。例如,如果把flMinClusterSize设为1,则最大的可寻址空间为16M字节。5与bootImage区域相关的问题正如上面所说的,当tffsDevFormat( )在一个偏移地址上格式化flash时,它不会碰偏移地址以下的的空间。正常情况下,这是好事。然而,如果先前使用了TrueFFS格式化了偏移地址以下的空间,那么这些空间的擦除单元就会包含tffsDevFormat( )写入的TrueFFS格式化头部信息。当TrueFFS挂接(mount)一个flash设备时,它会扫描整个flash的TrueFFS格式化头部信息,用来建立一个它控制的flash memory的区域表。如果在偏移地址之下的区域碰巧包含这样的头,那么TrueFFS挂接(mount)程序还可以看到这些头,结果当然会失败。怎样解决这个问题呢?你可以调用tffsRawio( )来对这些有问题的单元作一个物理擦除。这非常有效,但也非常危险。如果误用,有可能永久地损坏flash。在你的嵌入式系统开发初期,你可以小心地使用它。如果已经是产品了,你就必须保证你的应用程序和它的用户不被伤及。下图就是调用tffsRawio( )的情况。6创建TrueFFS块设备在你能创建一个逻辑TrueFFS块设备之前,你需要运行tffsDrv( )。如果你正确配置了VxWorks,它会在启动的时候自动加载。tffsDrv( )为Tornado初始化TrueFFS,包括建立互斥信号量、全局变量和用来管理TrueFFS的数据结构。也包括为目标机上所有的flash设备注册 socket组件的驱动程序。 注册socket组件的驱动程序从获取FLSocket中预先分配的5元素(5-element)TrueFFS内部数组开始。下一步是更新FLSocket结构以包含那些控制flash设备基本硬件接口的数据和函数指针。 当TrueFFS需要和具体的socket硬件打交道时,它使用设备号(04)作为索引来查找它的FLSocket结构,然后用相应结构中的函数来控制它的硬件接口需求。虽然这些socket接口函数并没有提供完整的块设备接口,但它们的确提供了一个足够好的使用tffsDevFormat( )的接口。这对于一个从未格式化的flash媒体来说是非常重要的,因为这种能力使得在此阶段创建一个TrueFFS块设备成为可能。 注册完一个socket组件驱动后,就可以调用tffsDevCreate( )在此之上创建一个TrueFFS块设备。作为一个输入参数,你必须为它指定一个设备号(0-4)。也就进入FLSocket结构数组的索引。作为设备号,它稍后对于dosFs是可见的。 在创建了TrueFFS块设备后,你必须调用dosFsDevInit( )函数将dos文件系统挂接(mount)到它上面。之后你就可以象从一个标准disk设备上读写flash了。为了方便,函数 usrTffsConfig( )将tffsDevCreate( )和dosFsDevInit( )合成了,并包含了一些创建TrueFFS块设备和挂接dosFS必要的函数,你只需调用它就可以了。以下是bootCofig.c中关于TrueFFS 块设备的代码,当采用tffs方式引导vxworks内核时,该函数被调用。LOCAL STATUS tffsLoad ( int drive, /* TFFS drive number (0 - (noOfDrives-1) */ int removable, /* 0 - nonremovable flash media */ char * fileName, /* file name to download */ FUNCPTR * pEntry ) int fd; if (tffsDrv () != OK)printErr (Could not initialize.n);return (ERROR); printf (Attaching to TFFS. ); dosFsInit (NUM_DOSFS_FILES); /* initialize DOS-FS */ if (usrTffsConfig (drive, removable, fileName) = ERROR) printErr (usrTffsConfig failed.n); return (ERROR); printErr (done.n); /* load the boot file */ printErr (Loading %s., fileName); if (fd = open (fileName, O_RDONLY, 0) = ERROR) printErr (nCannot open %s.n, fileName); return (ERROR); if (bootLoadModule (fd, pEntry) != OK) goto tffsLoadErr; close (fd); return (OK);Tornado之TrueFFS编程者指南(六)By George (续)按:看了seasoblue兄如此辛苦地翻译了TrueFFS编程者指南1-5,心想不能老是伸手要吃要穿,自己应当做点什么,就心血来潮也翻译起来。seasoblue兄谦虚说自己对TrueFFS造诣不深,其实大家心里明白他是大牛,因为字里行间已现山露水。我需要说明的是我对TrueFFS确实是啥屁不懂,仅仅是想学学,顺便照着字面就翻译了,字里行间肯定是破绽百出。之所以还厚着脸贴出来,是希望大方之家(如seasoblue、xiaohua等)能多多斧正,俺也好早点入门。第三章:如何写socket驱动与MTD1,简介 这一章将为你提供FLASH存储器、tffs与VXWORKS的接口。它将阐述所有对socket驱动和MTD至关重要的函数和结构体。其中我们最关心的两个结构体是FLFlash和FLSocket。 tffs内部分配了一个包含5个FLFlash结构体的阵列(array),每个都对应一个可能的flash设备。tffs使用这些FLFlash结构体来存储数据和函数指针(这些函数是用于管理FLASH设备的)。比如,tffs使用MTD函数来处理对FLASH煤质基本的读写操作,而FLFlash结构体就包含这些MTD函数指针。当运行一个MTD识别程序时,系统就安装了这些函数指针。 FLFlash结构体还包含一个指向FLSocket结构体的指针。tffs使用这些FLSocket结构体来存储数据和函数指针(所不同的是,这些函数是用于处理与FLASH设备的硬件接口的,也就是socket接口)。从我们的sysTffsInit()到xxxRegister()程序调用时,则安装这些函数。 用TFFS注册我们的socket驱动:在VXWORKS中包含TFFS将会使usrRoot()调用tffsDrv()。而这将发起一个函数调用链:如下图这些函数调用的目的之一就是用TFFS注册我们的socket驱动函数。多数情况下,注册工作都发生在xxxRegister()中(这个函数的定义在sysTffs.c中)。该函数能更新FLSocket结构体。而此时,TFFS已经对应socket驱动中的服务程序给FLSocket结构体赋予了一个设备号(也即卷标)。TFFS调用FLSocket结构体中引用的函数来处理与Flash设备的硬件接口。 给FLASH技术确定一个MTD;要创建一个TFFS块设备,我们必须调用tffsDevCreate()。这一调用也将发起一个函数调用链。如图3-2这些函数调用的目的之一是确认合适的MTD。该确认过程在flIdentifyFlash()中。flIdentifyFlash()通过逐个执行xxxIdentify()表中的程序来确定合适的MTD。(相同的MTD是可以在多个不同的FLASH卷标中同时有效的)。一旦找到合适的MTD,确认程序就会更新FLFlash结构体中的数据以及指向用于读、写、擦除、映射等操作的MTD程序指针。此外,确认过程还将完成在当前FLFlash结构体中涉及的FLSocket结构体的初始化。2,关于FLFlash结构体和FLSocket结构体 tffs最多可以处理5个TFFS块设备。它给每个FLFlash结构体和FLSocket结构体都分配一个可能存在的FLASH设备。当使用TFFS注册我们的socket驱动时,系统也同时对这些结构体进行初始化。 多数情况下,注册也将更新FLFlash中socket成员涉及的FLSocket结构体。而FLFlash结构体的初始化使通过运行一个MTD确认程序来完成的。因为,确认程序依赖于FLSocket结构体中所涉及的函数,所以我们必须在运行MTD确认程序之前安装号socket驱动。2.1 FLFlash之庐山真面目 几乎所有的FLFlash结构体成员都是通过MTD确认程序设定的,这样它就可以通过检测flash硬件获取它所需要的绝大多数数据。唯一例外的是socket成员,它是通过TFFS内部函数设定的。FLFlash结构体在h/tffs/flflash.h中有定义:typedef struct tFlash FLFlash; /* forward definition */struct tFlash FlashType type; /* flash device type (JEDEC id) */ long int erasableBlockSize; /* smallest erasable area */ long int chipSize; /* chip size */ int noOfChips; /* no. of chips in array */ int interleaving; /* chip interleaving */ unsigned flags; /* special options */ void * mtdVars; /* MTD private area for socket */ FLSocket * socket; /* FLSocket for this drive */ /* MTD-supplied flash map function */void FAR0 * (*map)(FLFlash *, CardAddress, int); /* MTD-supplied flash read function */ FLStatus (*read)(FLFlash *, CardAddress, void FAR1 *, int, int); /* MTD-supplied flash write function */ FLStatus (*write)(FLFlash *,CardAddress,const void FAR1 *,int,int) /* MTD-supplied flash erase function */FLStatus (*erase)(FLFlash *, int, int); /* callback to execute after power up */void (*setPowerOnCallback)(FLFlash *);说明: (1) type: JEDEC ID用于标识FLASH存储器的硬件。该成员的值在MTD确认程序中设定; (2) erasableBlockSize:大小,单位为字节,为flash存储器一个可擦除块的大小。该值通过交叉计算而得,因此当在MTD中设定该值时,通常用如下格式: vol.erasableBlockSize=aValue*erleaving; 其中,aValue就是未与其它flash芯片交叉存取的可擦除块的大小。(3) chipsize: 单片flash得存储容量,单位字节。通过MTD中的外部函数flFitInSocketWindow()设定。 (4)noOfChips: 构成FLASH存储阵列的flash存储器的片数; (5)interleaving: flash存储阵列的交叉存取参数,必须为2的整数幂(如1,2,4等)。用于定义在一个存储芯片上,两个字节连续媒体的地址差异。 (6)flags: bits0-7 保留用于TFFS;bits8-15 保留用于MTD; (7)mtdVars: 该区域如果被MTD占用,mtd的确认程序则将它初始化为一个指针指向一个特定的存储区。比如,16位AMD设备的MTD使用该成员存储一个指针,该指向存有AMD特有的FLASH参数。 (8)socket: 是个指向FLSocket结构体的指针。而这个FLSocket结构体含有指向socket层函数的指针和数据。当我们注册socket驱动时,该FLSocket结构体中涉及的函数将被安装。而且,因为TFFS要使用这些socket驱动函数来寻址FLASH存储器,所以我们必须在运
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025国家公务员霍尔果斯国际边境合作中心海关面试题及答案
- 2025版设备租赁合同协议
- 2025临时用工合同协议模板
- 2025年电气设计工作总结报告(3篇)
- 2025年上海市房屋租赁合同(中介版)
- 2025版合同:附条件租赁协议书
- 2025定制、采购合同范本
- 2025年个体汽车租赁合同样本及关键注意事项(合同协议样本)
- 2025年下半年吉林辽源东丰县事业单位招聘13人(2号)易考易错模拟试题(共500题)试卷后附参考答案
- 2025年下半年吉林省能源投资集团限责任公司公开招聘易考易错模拟试题(共500题)试卷后附参考答案
- 2025广东广州市海珠区凤阳街道第四批招聘雇员5人考试笔试模拟试题及答案解析
- 营盘山隧道施工方案设计
- 2025至2030中国电站建设行业市场深度调研及投资策略及有效策略与实施路径评估报告
- 2026年广西现代职业技术学院单招职业技能考试必刷测试卷及答案1套
- 砌筑抹灰升降平台专项施工方案
- 中学生宿舍楼施工组织设计
- 医院地震知识培训内容课件
- 酒狂古琴曲教学课件
- 机电行业职业知识培训课件
- 大学生创新创业(邓文达)全套教案课件
- 研学基地安全管理与应急预案
评论
0/150
提交评论