1 VxWorks加载
1.1 从TFFS文件系统加载
Tornado的TrueFFS是和VxWorks兼容的一种M-Systems Flite实现方式,它为种类繁多的flash存储设备提供了统一的块设备接口,并且具有可重入、线程安全的特点,支持大多数流行的CPU构架。有了Tornado的TrueFFS,应用程序对 flash存储设备的读写就好象它们对拥有MS-DOS文件系统的磁盘设备的操作一样。
如图18所示,TrueFFS由核心层(core layer)和三个功能层,翻译层(translation layer)、MTD层(MTD layer)、socket层(socket layer)组成。
图18 TrueFFS层结构布局
核心层(Core layer):核心层主要起相互连接其他几层的功能。同时它也可以进行碎片回收、定时器和其他系统资源的维护。通常WindRiver公司将这部分内容以二进制文件提供。
翻译层主要实现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支持,你可以使用一个标准的接口来加入这些驱动。
以上四部分,我们通常要的工作就是后两层。
MX29LV160BT
芯片上建立TrueFFS
文件系统
1.配置相关文件
在此,以Nor Flash MX29LV160BT为例,开发工具为Tornado2.2 for PPC。要在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中。即:
#define INCLUDE_MTD_MX29LV /* MX29LV160BT MTD driver */
#define INCLUDE_TL_FTL /* FTL translation layer */
#define FLASH_BASE_ADRS 0x2a10000 /* Flash memory base address */
#undef FLASH_SIZE
#define FLASH_SIZE 0x001f0000 /*Flash memory size, 2M (parameter block) */
其他无关的MTD driver包含头都#undef掉,同时定义Flash在系统中的基地址和大小。另外,还必须编辑sysLib.c中的 sysPhysMemDesc[ ]数组,将Flash基地址和大小加入到MMU中,以供将来访问Flash,否则访问Flash会失败。如果BSP目录下没有sysTffs.c文件,那么我们可以从其他BSP目录下拷贝一个即可,然后做上述修改,其他的内容基本可以不用修改。
接下来需要修改tffsConfig.c文件,为了方便管理,通常我们将src/drv/tffs/目录下该文件拷贝到我们BSP目录下,然后再做出修改。在MTDidentifyRoutine mtdTable[]表中加入如下语句:
#ifdef INCLUDE_MTD_MX29LV
mx29lvMTDIdentify,
#endif /* INCLUDE_MTD_MX29LV */
并在该文件开头声明。
#ifdef INCLUDE_MTD_MX29LV
FLStatus mx29lvMTDIdentify (FLFlash vol);
#endif /* INCLUDE_MTD_MX29LV */
最后就是将我们的flash相关MTD驱动加入到makefile中。即:
MACH_EXTRA = mx29lvMtd.o
为了方便我们调试MTD驱动,应该在重新编译VxWorks映象前将诸如格式化flash、创建TrueFFS块设备、绑定此块设备到dosFs所必要的功能包含到VxWorks映像中。比如如下定义:
#define INCLUDE_TFFS
#ifdef INCLUDE_TFFS
#define INCLUDE_TFFS_DOSFS
#define INCLUDE_TFFS_SHOW
#define INCLUDE_DOSFS /* dosFs file system */
#define INCLUDE_SHOW_ROUTINES /* show routines for system facilities*/
#define INCLUDE_TL_FTL
#define INCLUDE_IO_SYSTEM
#define INCLUDE_DISK_UTIL
#endif /* INCLUDE_DOSFS */
2.MTD驱动
做了上述配置后,进入VxWorks操作系统后,我们在shell上利用tffsShow工具来显示flash的信息。TffsShow函数最终会调用 MTD驱动中的mx29lvMtdIdentiy( )函数,在mx29lvMtdIdentiy ( )函数主要是通过读取MX29LV160BT芯片的设备和厂商ID来识别它,然后对FLFlash结构成员进行初始化,最主要的几个参数是:
type:Flash内存的JEDEC ID号;
erasableBlockSize:Flash内存的擦除块大小(字节)。设置这个值时应考虑到interleaving。因此,通常通过如下方法来设置它的大小;
Vol.erasableBlockSize = MX29LV_MTD_SECTOR_SIZE * vol.interleaving;
对于MX29LV160BT,MX29LV_MTD_SECTOR_SIZE为64K字节;
chipSize:使用来构建TrueFFS文件系统的flash实际大小(字节);
noOfChips:使用来构建TrueFFS文件系统的flash实际片数;
interleaving:Flash内存交叉因子(interleaving factor)。即扩展数据总线的设备数。比如,一个32位数据总线上,我们可以使用4片8位或2片16位的设备;
map:指向flash内存映射(map)函数。该函数将flash映射到内存区;
read:指向flash内存的读函数。在MTD驱动识别函数中,这个成员函数已经被初始化为缺省的读函数。通常情况下,我们不需要再初始化它,否则还需要修改很多相关的函数;
write:指向flash内存的写函数。这个成员必须初始化,这是我们要做的一个重要工作;
erase:指向flash内存的擦除函数。这个成员必须初始化,这也是我们要做的一个重要工作。
针对FLFlash结构成员,我们所关心的两个函数就是写和擦除函数。在mx29lvMtdIdentiy()函数中必须有如下定义:
vol.write = mx29lvWrite;
vol.erase = mx29lvErase;
在mx29lvWrite()函数中主要是实现将数据写到flash中。首先需要对扇区进行解锁,然后写入写命令,之后才能进行数据的写入。最后需要判断数据是否写完。为了确保操作成功,我们应该在写完每个数据后进行数据的比较,比较正确后方能进行下一个数据的操作。
在mx29lvErase()函数中主要是实现flash扇区的擦除。如今的flash一般都是按照扇区进行擦除操作的。在擦除操作之前也应该首先对扇区进行解锁,然后写擦除建立和扇区擦除命令。擦除成功后,flash中的内容应该是0xffff。所以为了确保成功,我们还是应该在擦除后进行比较,比较正确后方能进入下一个扇区的擦除操作,否则返回擦除错误标志。
所以,对于MTD驱动的调试,基本上就是调试写和擦除两个函数。在调试过程中,我们可以在这两个函数相应位置加入打印语句来调试。为了能调试这两个函数,我们通过在shell上输入命令tffsDevFormat来格式化flash, tffsDevFormat最终会调用mx29lvErase和mx29lvWrite函数,如果成功就会返回0,否则返回-1。当然也可以调用 tffsDevCreate函数来验证我们的写和擦除函数的正确性。图19说明了tffsDevCreate调用过程。
图19 tffsDevCreate()调用过程
在shell上利用tffsShow来验证mx29lvMtdIdentiy。
> tffsShow
0: socket=RFA: type=0x2249, unitSize=0x10000, mediaSize=0x1f0000
value = 49 = 0x31 = "1"
说明已正确识别到MX29LV160BT设备,设备号为0x2249。
建立TFFS
设备
1.挂接设备名
MTD驱动调试成功后,我们就可以给flash设备挂接上dos设备名,如下操作:
格式化:
> tffsDevFormat
value = 1
> usrTffsConfig 0,0,”/tffs0”
value = 0
然后通过devs来查看挂接的设备名:
> devs
drv name
0 /null
1 /tyCo/0
1 /tyCo/1
5 host:
6 /pty/rlogin.S
7 /pty/rlogin.M
3 /tffs0/
8 /vio
value = 25 = 0x19
看到/tffs0/说明挂接设备已经成功,接下来就可以利用dosFs文件系统相关命令来操作flash了。如,ls、copy等。
用代码来完成上述过程:
STATUS flashInit(void)
{
STATUS rc = OK;
if (tffsDrv() != OK)
{
printf("Could not initialize.\n");
return (ERROR);
}
#if 0
printf("Attaching to flash file system... ");
#endif
dosFsInit(NUM_DOSFS_FILES); /* initialize DOS-FS */
if (usrTffsConfig(driveNumber1, 0, SYS_BASE_FS) == ERROR)
{
printf("\ncore file system not exist.\n");
rc = sysTffsFormat(0, 0, 0, SYS_BASE_FS, 0, 0, 0);
}
return rc;
}
上述代码中的sysTffsFormat()会调用tffsDevFormat()进行格式化操作,如:
tffsDevFormat(driveNumber, (int)params);
params为tffsDevFormatParams结构体指针,即格式化参数,如:
#define TFFS_FORMAT_PARAM_WITH_ROOM_FOR_CONFIG_WORD \
{{1, 99, 1, 0x10000l, NULL, {0,0,0,0}, NULL, 2, 0, NULL}, FTL_FORMAT_IF_NEEDED}
而函数usrTffsConfig( )则将tffsDevCreate( )和dosFsDevInit( )进行了合成,是一个快捷函数。
2.从Flash中启动并下载VxWorks映像
要从flash中下载VxWorks映像,首先需要把VxWorks映像拷贝到flash中,在shell中的操作命令为copy “VxWorks”,“tffs0/VxWorks”,然后修改config.h文件中引导行,如下:
#define DEFAULT_BOOT_LINE \
"tffs=0,0(0,0)host:/tffs0/VxWorks h=192.168.0.153 e=192.168.0.154 u=target pw=target o=cpm"
修改完后,重新编译生成bootrom_uncmp.bin,并把它烧写到flash中。然后重新启动,即可看到如下启动画面:
boot device : tffs=0,0
unit number : 0
processor number : 0
host name : host
file name : /tffs0/VxWorks
inet on ethernet (e) : 192.168.0.154
host inet (h) : 192.168.0.153
user (u) : target
ftp password (pw) : target
flags (f) : 0x0
other (o) : cpm
Attaching to TFFS... done.
Loading /tffs0/VxWorks...894304
Starting at 0x10000...
Development System
VxWorks version 5.5.1
KERNEL: WIND version 2.6
Copyright Wind River Systems, Inc., 1984-2003
CPU: Motorola ADS - PowerPC 860. Processor #0.
Memory Size: 0x1000000. BSP version 1.2/5.
WDB Comm Type: WDB_COMM_END
WDB: Ready.
到此,说明引导成功。flash整个TFFS文件系统就已经建立成功。
在一片FLASH
上
同时装载BootRom
、VxWorks
文件
我们将Flash地址映射成两个地址段,一段用做BootRom,一段用做 VxWorks使用,用做BootRom的地址段为0xFFF00000~0xFFF80000,另外一段用做 VxWorks的地址段为0x04080000~0x04800000(假设此Flash大小为8M大小),在 0xFFF00000~0xFFF80000地址段写入BootRom,在0x04080000~0x04800000地址段写入 VxWorks,加电后,PC指针会跳到0xFFF00100地址执行第一条指令,引导BootRom起来并最终 VxWorks系统引导成功。实现过程:
1.片选(?)
在romInit.s文件中要做如下的片选操作,片选0为BOOT Flash的地址片选,片选1为Flash的地址片选,其中ROM_BASE_ADRS为0xFFF00000
/* -------------------------------------------------------- */
/* Initialize Chip Select 0 for Bootrom */
/* ------------------------------------------------------------- */
lis r5, HIADJ( ROM_BASE_ADRS | BR_PS_8 | BR_WP | BR_V)
addi r5, r5, LO( ROM_BASE_ADRS | BR_PS_8 | BR_WP | BR_V)
stw r5, BR0(0)(r4)
lis r5, HIADJ( 0xFFF80000 | 0x00000100 | 0x00000080)
addi r5, r5, LO( 0xFFF80000 | 0x00000100 | 0x00000080)
stw r5, OR0(0)(r4)
/* -------------------------------------------------- */
/* Initialize Chip Select 1 for FLASH */
/* -------------------------------------------------- */
lis r5, HIADJ( 0x04000000 | BR_PS_16 | 0x00000001)
addi r5, r5, LO( 0x04000000 | BR_PS_16 | 0x00000001)
stw r5, BR1(0)(r4)
lis r5, HIADJ(0xff800000 | 0x00000100 | 0x00000080)
addi r5, r5, LO(0xff800000 | 0x00000100 | 0x00000080)
stw r5, OR1(0)(r4)
2.地址映射
在sysLib.c文件中有一sysPhysMemDesc的地址映射数组的声明,对BOOT Flash和Flash的地址按照如下的地址映射后,VxWorks系统才会让你对此地址进行相应的读写操作。
{
(void *) 0x04000000,
(void *) 0x04000000,
0x00800000, /* 8 m - Flash window 1 */
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE,
VM_STATE_VALID | VM_STATE_WRITABLE
},
{
(void *) ROM_BASE_ADRS,
(void *) ROM_BASE_ADRS,
ROM_SIZE, /* Flash memory */
VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE |
VM_STATE_MASK_CACHEABLE ,
VM_STATE_VALID | VM_STATE_WRITABLE |
VM_STATE_CACHEABLE_NOT
}
3.文件烧录
还存在一个问题,因为BOOT Flash是可以在烧录器上烧录的,而Flash芯片是直接焊接在MPC860的主板上,只能通过相应的Flash驱动才能进行读写的,是不可能通过烧录器烧录,要解决此问题那只能按照如下办法解决。
在主板上要保留有BootRom Flash座,要有一片从BOOT Flash引导的BOOT Flash芯片,此芯片中要有已经烧录好的可以正常运行的 BootRom程序,先将此芯片加到BootRom Flash座上,加电将系统引导起来,然后用事先写好的将BootRom及VxWorks写入 Flash的函数将BootRom及VxWorks文件写入Flash相应的地址段,注意写入地址要正确,即BootRom的第一条指令必须写在 0xFFF00100地址,关电后将BOOT Flash从座中取出来,加电后系统就从Flash中引导起来了。
1.2 从串口加载
1.配置config.h文件
a. 修改DEFAULT_BOOT_LINE为tsfs (target server file system) 方式引导VxWorks映象:
#define DEFAULT_BOOT_LINE \
"tsfs(0,0)aman:/vxWorks h=192.168.0.108 e=192.168.0.67 u=amd pw=0000 tn=snds100"
b. 如果定义了INCLUDE_END,则#undef掉它。
c.屏蔽掉原来对串口的设置。如果有两个可用串口,那么增加以下的配置内容:
�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D
/* Serial port configuration */
#define INCLUDE_SERIAL
#undef CONSOLE_TTY
#define CONSOLE_TTY 1 /*console channel */
#undef CONSOLE_BAUD_RATE
#define CONSOLE_BAUD_RATE 38400 /* Redefine to PP1 default */
#undef WDB_TTY_CHANNEL
#define WDB_TTY_CHANNEL 0
#undef WDB_COMM_TYPE
#define WDB_COMM_TYPE WDB_COMM_SERIAL /* 0 communication through serial port */
#undef WDB_TTY_BAUD
#define WDB_TTY_BAUD 38400
#define INCLUDE_TSFS_BOOT
�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D
这时串口0通道将被用作VxWorks映象下载及握手的通道,而串口1通道则被作为控制台信息的打印通道。两者的波特率都是38400。如果只有一个串口,那么必须这样配置:
�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D
#undef CONSOLE_TTY
#define CONSOLE_TTY NONE
#undef WDB_TTY_CHANNEL
#define WDB_TTY_CHANNEL 0
#undef WDB_COMM_TYPE
#define WDB_COMM_TYPE WDB_COMM_SERIAL
#undef WDB_TTY_BAUD
#define WDB_TTY_BAUD 38400
#define INCLUDE_TSFS_BOOT
这时将没有控制台,所以将不能更改boot参数。
2.配置Tornado的Target Server
a.选择Tornado下的菜单“Tools”->“Target Server”->“Config…”->“New”,新建一个Target Server。如下图所示:
b.配置core file
如下图所示,指定要下载的VxWorks映象文件:
c.配置tsfs文件系统
如下图所示:
3.这样就基本完成了所有的配置。重新编译bootrom和VxWorks,接上2根串口线,配置好作为控制台的超级终端。再启动tornado的target server,然后重启目标机,出现如下的界面:
目标机从串口0开始下载VxWorks映象并运行它。最后打印出WDB: Ready.要了解更详细的内容请参阅Tornado在线帮助:TSFS Boot Configuration。
目标服务文件系统:TSFS
虽然目标服务文件系统(TSFS)是一个全特征VxWorks文件系统,但是通过使用目前定位在主机上的文件系统执行文件操作。TSFS使用WDB驱动程序把来自I/O系统的请求转移到目标服务器。目标服务器使用主机文件系统读取执行请求。那么当你用TSFS打开一个文件,被打开的文件事实上在主机上。将来在对open()调用中获得的文件描述符的read()和write()调用事实上是从打开的主机文件读取和写入。