IC & COMPONENTS
IC & COMPONENTS
电子产品世界
www.eepw.com.cn
网 上 论 坛
IC 与元器件
V x W o r k s 压缩技术
作者:嵌入式版版主 gem2000
本文详述了缩小VxWorks文件尺寸的方法,
当开发进入产品阶段,很可能会需要这种技术。
更多技术文章请浏览http://bbs.edw.com.cn。
在 嵌入式系统中,我们通常会要求VxWorks文件
尽量小,比如通过串口、软盘或 t f f s 加载
VxWorks 的时候,如果文件太大,可能无法存
过串口或网络加载 VxWorks.z,则需要初始化相应的接
口。
6 修改bootConfig.c文件:
储,或加载失败。下面介绍一种利用Tornado和VxWorks
a. 在 LOCAL STATUS netLoad 函数的 tftpXfer 和
自带的deflate和inflate,对VxWorks文件进行压缩和解
ftpXfer这一部分代码结束的地方添加:
压缩的技术。希望对大家有所帮助。
if ( strstr(fileName,".z") || strstr(fileName,".Z") )
1 使用Tornado创建bootable的project,包括应用
{
程序。对 VxWorks 进行适当的裁减和配置。
printf("\nfile %s is compressed, now begin
2 如果准备将VxWorks存储于硬盘,软盘或tffs上,
uncompressing...\n",fileName);
应该在 usrAppInit 中使用 usrNetEndDevStart 和
if (bootLoadModuleInflate(fd, pEntry) != OK)
usrNetIfConfig启动网络接口。如果存储于tffs上,还要
goto readErr;
修改usrNetBoot.c中:
}
if ( (strncmp (sysBootParams.bootDev, "scsi", 4) == 0)
else if (bootLoadModule (fd, pEntry) != OK)
|| (strncmp (sysBootParams.bootDev, "ide", 3) == 0)
goto readErr;
|| (strncmp (sysBootParams.bootDev, "ata", 3) == 0)
b. 在 LOCAL STATUS tffsLoad 函数的 usrTffsConfig
|| (strncmp (sysBootParams.bootDev, "fd", 2) == 0))
和open这一部分代码结束的地方添加:
为:
if ( strstr(fileName,".z") || strstr(fileName,".Z") )
if ( (strncmp (sysBootParams.bootDev, "scsi", 4) == 0)
{
|| (strncmp (sysBootParams.bootDev, "ide", 3) == 0)
printf("\nfile %s is compressed, now begin
|| (strncmp (sysBootParams.bootDev, "ata", 3) == 0)
uncompressing...\n",fileName);
|| (strncmp (sysBootParams.bootDev, "tffs", 4) == 0)
if (bootLoadModuleInflate(fd, pEntry) != OK)
|| (strncmp (sysBootParams.bootDev, "fd", 2) == 0))
goto readErr;
3 在dos下运行 tornado/host/x86-win32/bin/torvars。
}
4 进入 VxWorks所在的目录,运行:
else if (bootLoadModule (fd, pEntry) != OK)
deflate VxWorks.z。这里我们默认.z文
goto readErr;
件是压缩文件。
c. 在 LOCAL STATUS bootLoad 函数之前定义函数
5 如果准备将VxWorks.z存储于硬盘,软盘或tffs上,
bootLoadModuleInflate的原型:
需要首先创建相应的设备,并用dosFS初始化。如果是通
#define DECOMP_BUF_SIZE (RAM_HIGH_ADRS
www.eepw.com.cn
电子产品世界
2003.6/上半月
49
IC 与元器件
IC & COMPONENTS
IC & COMPONENTS
- RAM_LOW_ADRS)
goto done;
#define COMP_BUF_SIZE (DECOMP_BUF_SIZE /
}
3)
if ((r = inflate(compBuf, imageBuf, compSize)) < 0)
STATUS bootLoadModuleInflate(int zfd, FUNCPTR
{
*pEntry)
{
char *imageBuf = NULL;
char *compBuf = NULL;
int fd = -1;
int rv = ERROR;
int compSize, r;
printErr("\nUncompress failed\n");
goto done;
}
printErr("\nLoading image... ");
memDrv();
memDevCreate("mem:", imageBuf,
DECOMP_BUF_SIZE);
extern STATUS inflate(char *src, char *dst, int
if ((fd = open("mem:0", O_RDONLY, 0)) < 0)
src_size);
{
if ((compBuf = malloc(COMP_BUF_SIZE)) ==
printErr("\nCannot open memory device.\n");
N U L L )
{
goto done;
}
printErr("No enough memory for image buffer\n");
if (bootLoadModule(fd, pEntry) != OK)
goto done;
}
compSize = 0;
{
printErr("\nError loading: errno = %d\n", errnoGet());
goto done;
while ((r = read(zfd, compBuf + compSize,
}
COMP_BUF_SIZE - compSize)) > 0)
compSize += r;
if (r < 0)
{
printErr("\n");
rv = OK;
done:
if (fd >= 0)
printErr("Read failed: errno = %d\n", errnoGet());
close(fd);
goto done;
}
if (compSize == COMP_BUF_SIZE)
{
printErr("Compressed image too large\n");
goto done;
}
if (imageBuf)
free(imageBuf);
if (compBuf)
free(compBuf);
return rv;
}
d . 如果加载不成功,应读懂上一段代码,调整
printErr("Uncompressing %d bytes... ", compSize);
R A M _ H I G H _ A D R S 和 R A M _ L O W _ A D R S 的大小。
if ((imageBuf = malloc(DECOMP_BUF_SIZE)) ==
7 修改 config.h 中的启动参数,比如启动设备为
N U L L )
{
tffs=0,0(0,0),文件名为/tffs0/VxWorks.z等等,重新制作
bootrom,并写入flash。
printErr("Not enough memory for decompression
8 启动时,修改启动参数,使系统仍然从网络加载
buffer\n");
VxWorks,这个 VxWorks 中应该实现了 ftp或
57
50
2003.6/上半月
电子产品世界
www.eepw.com.cn
TEST & SENSOR
TEST & SENSOR
测试测量与传感器
X(n-2)是再前一个输入(-180°)
都以展开形式写出。
实际上,只要输入信号频率高于基准频率,结果Y(n)
采用PSoC混合信号阵列实现正交解调器检测器的程
的符号就是负的,反之符号为正。
序从略。
在这一运算中存在两个小问题:
(1) 结果中某些点可能为零。
简单测试32位累加寄存器的最高有效字节就可测知
结果的符号。如果最高有效字节是 0xFF,那么计算结果
(2) 直流偏移会改变极性,导致结果错误。
为负。任何非0xFF 的数值,包括0x00 在内,都表示结果
有些情况下,这两个问题无伤大局。既然无法区分
为正。
(+0)和(-0),那么最简单的方法就是丢掉所有为零的结
图 1 显示的是计算结果。“HI/LO Y-Sum”曲线显示
果。类似地,直流偏移会引起“虚假检测”。但是如果你
了这些算式前面几个阶段运算的结果。请注意,两条曲线
的设计方案可以容许这些虚假检测,那么就不必再进行
在某些点都接近或等于零。将最后一项加到算式上以后,
修改。
结果就更负或更正了,从而避免了通常会出现零的情况。
幸好这两个问题都可以用数学方法进行修正。将前
这有助于改善检测器的整体可靠性。
一个计算结果与目前的计算结果相加,这既可以让计算
结果不为零,还能去除微小直流偏移的影响。
结语
扩展的算式如下:
本文在介绍检测器的过程中采用的都是非合成输入
Y(n) = [ (X(n) * X(n-1) ) + ( X(n-1) * X(n-2) ) ] + [ ( X(n-
信号,即仅有一个频率分量的信号。虽然一些新型微控制
1) * X(n-2) ) + ( X(n-2) * X(n-3)) ]
器具有模拟滤波器功能,但是测试显示,我们仅需要能够
这个算式看起来好像很难在微控制器中实现,但是
通过被检测的频率并滤掉所有不感兴趣频率的滤波器(带
实验表明,仅采用 8个数据项,就能得到很好的结果。用
通滤波器)。带通滤波器的技术要求由实际的输入信号和
2s-Complement 数学规则,加上 8 个数据项,也就是说,
所需的检测器性能决定。我们发现,6极带通滤波器加上
你仅需处理 16 位数字。采用内置 2s-Complement MAC的
正交解调器可以在实际使用中实现 50Hz 的频率分辨率。
微控制器能极大地降低计算的复杂性。
由于这些方法都使用了模数转换器,所以采用好的
下面的程序说明如何用具有控制器的PSoC混合信号
电路搭建方法让电子噪声最小很重要。另外,CPU 时钟
阵列中内置的 MAC 实现这个算式。全部运算只需要 18条
的精确性也会影响整个检测器的精确性。■
指令,而且全部是数据传送指令。MAC 自动实时执行运
(作者是Cypress半导体公司应用工程师。限于篇幅,
算。有些程序代码是可以合并的,但是为清楚起见,这里
程序从略,读者可发 Email 至 he@edw.com.cn 索阅)
50
tftp功能。通过这些功能,把VxWorks.z文件
54
结语
写入存储介质如tffs中。
采用内存接口的液晶显示模块,外部控制器就不需
9 重新启动从 tffs或硬盘,软盘加载VxWorks,即
要了解具体的液晶操作,对液晶模块的操作就像读写内
可成功。
存一样简单快捷,节省了大量的 CPU 时间,进行实时处
1 0 可以首先通过网络启动,把启动文件名改为
理与显示。■
VxWorks.z来进行验证压缩和解压缩。
11 以上只是考虑了从网络和tffs来加载VxWorks.z
参考文献:
压缩文件,如果从fd, ata等加载,只需在相应地方添加和
1. ‘MCS-51单片机应用设计’,哈尔滨工业大学出
6.a中相同的代码即可。
版社.
12 本方法在ppc850上,利用tffs和网络加载进行了
2. ‘液晶显示应用技术’,电子工业出版社.
验证,完全适用。■ (gem2000 researcher@263.net)
www.eepw.com.cn
电子产品世界
2003.6/上半月
57