Tornado之TrueFFS编程者指南
2012-10-08
seasoblue
标签:

二. 起步

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 flash

INCLUDE_TL_FTL |NOR-based flash

INCLUDE_TL_SSFDC |SSFDC flash

----------------------

我们一般的flash芯片如sst39vf040,sst39vf160,am29lv160等都是NOR-based flash型,所以可以只“#define INCLUDE_TL_FTL”。

接下来,我们选择MTD层模块。Vxworks自带了支持一些flash型号的MTD层驱动模块。如下表所示:

____________________________________

宏定义符号相应的flash设备

INCLUDE_MTD_I28F016Intel 28f016

INCLUDE_MTD_I28F008Intel 28f008

INCLUDE_MTD_I28F008_BAJAIntel 28f008 on the Heurikon Baja 4000

INCLUDE_MTD_AMDAMD, Fujitsu: 29F0{40,80,16} 8-bit devices

INCLUDE_MTD_CDSNToshiba, Samsung: NAND CDSN devices

INCLUDE_MTD_DOC2Toshiba, Samsung: NAND DiskOnChip2000

INCLUDE_MTD_CFISCSCFI/SCS device

INCLUDE_MTD_WAMDAMD, Fujitsu 29F0{40,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媒体开始处预留的长度*/

unsigned percentUse;/*flash媒体被格式化的百分率,为了提高TrueFFS的性能,不要设为100%,以便任何时候都有空余 空间。默认值为99%*/

unsigned noOfSpareUnits;/*空余擦除单元数目,目的在于flash出现坏块时可以用它来替代,默认为1*/

unsigned long vmAddressingLimit;/* FTL 在RAM中映射的大小,默认为61Kbytes*/

FLStatus (*progressCallback)(int totalUnitsToFormat, int totalUnitsFormattedSoFar);/* 回调函数,用来监测flash擦除过程,如果返回值为OK,则继续,否则停止擦除。*/

/* DOS formatting section */

charvolumeId[4];/*Dos卷标号*/

char FAR1 * volumeLabel;/*Dos卷标字符串,如果为NULL,则没有卷标*/

unsignednoOfFATcopies;/* 文件分配表(FAT)的拷贝数,正常情况下只使用一个FAT,而另一个只有在使用的FAT被破坏的情况下用来恢复分配表,默认为2*/

unsigned embeddedCISlength; /* CIS 嵌在单元头部(unit header)之后的字节长度*/

char FAR1 * embeddedCIS;/* 单元头部被结构化用来作为一个PCMCIA ''tuple'' 链(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硬件打交道时,它使用设备号(0-4)作为索引来查找它的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

(

intdrive,/* TFFS drive number (0 - (noOfDrives-1)) */

intremovable,/* 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);

共 4 页   上一页1234下一页
可能会用到的工具/仪表
相关文章
推荐文章
热门文章
章节目录
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号