VxWorks入门系列教程3:虚拟机中运行VxWorks

本系列索引地址:VxWorks开发入门系列教程索引

在下载的VxWorks安装包中,包含了一份在虚拟机下安装测试的文档,我们按照这个文档测试一下。

VxWorks 6.8.3 + VxWorks Workbench 3.2.3 + VMware 16.1.2 + MS-DOS 6.22 软盘版

按照FTP连接的主机和目标机,将整个VxWorks6.8的安装分为两个部分,一是在主机(win10系统,可以使用虚拟机或者实体机,推荐使用虚拟机)上安装workbench3.2,进行bootrom与VxWroks映像文件的生成,二是在虚拟机上安装VxWorks系统。

安装

已经在之前的文章中演示过了。

编译BSP

1、找到WorkBench的安装目录,目录名为WindRiver,找到vxworks-6.8目录,进入找到target目录,进入找到config目录,进入找到pcPentium4目录

dir

复制到config目录,重命名为Pentium4(自己取名,最好不要带空格或什么特殊符号)

new

我们要修改编译 bootrom、VxWorks 的配置头文件 Config.h 中定义的一些参数,使编译出来的系统引导程序 bootrom 和 VxWorks 的映象符合我们的要求;

修改config.h

1、定位到目录C:\WindRiver\vxworks-6.8\target\config\Pentium4并打开该目录下 config.h 文件;定位到INCLUDE_CPU_PROBE,

1
2
3
4
5
6
7
8
/* CPU auto detection with sysCpuProbe() that support Intel CPUs for now */

#define INCLUDE_CPU_PROBE /* define to perform sysCpuProbe() */
#ifndef INCLUDE_CPU_PROBE
# undef CPU
# define CPU PENTIUM /* for CPU conditionals in BSP */
#endif /* INCLUDE_CPU_PROBE */
#define X86CPU_DEFAULT X86CPU_PENTIUM /* for sysProcessor set in BSP */

更改成如下:

1
2
3
4
5
6
7
8
/* CPU auto detection with sysCpuProbe() that support Intel CPUs for now */

#undef INCLUDE_CPU_PROBE /* define to perform sysCpuProbe() */
#ifndef INCLUDE_CPU_PROBE
# undef CPU
# define CPU PENTIUM /* for CPU conditionals in BSP */
#endif /* INCLUDE_CPU_PROBE */
#define X86CPU_DEFAULT X86CPU_PENTIUM /* for sysProcessor set in BSP */

2、定位到定义 DEFAULT_BOOT_LINE 宏的地方,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

/* Default boot line */

#if (CPU == I80386)
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)host:/fd0/vxWorks.st h=90.0.0.3 e=90.0.0.50 u=target"
#elif (CPU == I80486)
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)host:/fd0/vxWorks.st h=90.0.0.3 e=90.0.0.50 u=target"
#elif (CPU == PENTIUM)
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)host:/fd0/vxWorks.st h=90.0.0.3 e=90.0.0.50 u=target"
#elif (CPU == PENTIUM2)
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)host:/fd0/vxWorks.st h=90.0.0.3 e=90.0.0.50 u=target"
#elif (CPU == PENTIUM3)
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)host:/fd0/vxWorks.st h=90.0.0.3 e=90.0.0.50 u=target"
#elif (CPU == PENTIUM4)
#define DEFAULT_BOOT_LINE \
"fd=0,0(0,0)host:/fd0/vxWorks.st h=90.0.0.3 e=90.0.0.50 u=target"
#endif /* (CPU == I80386) */

修改预处理条件 CPU = = PENTIUM4 分支下的定义如下:

1
"lnPci(0,0)host:vxWorks h=192.168.33.133 e=192.168.33.134 u=target pw=target tn=target"

这里的h(host)地址表示你的主机IP地址,可以先修改为主机IP地址,或者随便填一个IP地址,之后修改主机地址为该地址,e(target)地址表示VxWorks系统目标机的IP地址,只需要和主机IP地址在同一个网段内即可,u=target pw=target是FTP下载的用户名和密码,都可以根据自己实际情况修改,最好使用target,简单易记。

3、定位到INCLUDE_ATA,

1
#undef	INCLUDE_ATA             /* include IDE/EIDE(ATA) hard disk driver */

在前面一句添加#undef INCLUDE_FD,如下所示:

1
2
#undef  INCLUDE_FD              /* include floppy disk driver */
#undef INCLUDE_ATA /* include IDE/EIDE(ATA) hard disk driver */

4、定位到/* Network driver options: VxBus drivers */

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Network driver options: VxBus drivers */

#undef INCLUDE_AM79C97X_VXB_END
#undef INCLUDE_AN983_VXB_END
#ifndef _WRS_CONFIG_WRHV_GUEST
#define INCLUDE_FEI8255X_VXB_END
#endif
#define INCLUDE_GEI825XX_VXB_END
#undef INCLUDE_MVYUKONII_VXB_END
#undef INCLUDE_MVYUKON_VXB_END
#undef INCLUDE_NS8381X_VXB_END
#undef INCLUDE_RTL8139_VXB_END
#undef INCLUDE_RTL8169_VXB_END
#undef INCLUDE_TC3C905_VXB_END
#undef INCLUDE_NE2000_VXB_END

作如下修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* Network driver options: VxBus drivers */

#undef INCLUDE_AM79C97X_VXB_END
#undef INCLUDE_AN983_VXB_END
#undef INCLUDE_FEI8255X_VXB_END
#undef INCLUDE_GEI825XX_VXB_END
#undef INCLUDE_MVYUKONII_VXB_END
#undef INCLUDE_MVYUKON_VXB_END
#undef INCLUDE_NS8381X_VXB_END
#undef INCLUDE_RTL8139_VXB_END
#undef INCLUDE_RTL8169_VXB_END
#undef INCLUDE_TC3C905_VXB_END
#undef INCLUDE_NE2000_VXB_END

5、定位到INCLUDE_LN_97X_END,

1
#undef  INCLUDE_LN_97X_END      /* (END) AMD 79C97x PCI interface */

将其定义上,修改如下:

1
#define  INCLUDE_LN_97X_END      /* (END) AMD 79C97x PCI interface */

6、定位到INCLUDE_PC_CONSOLE,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* use global variable for console tty */

#undef CONSOLE_TTY
#define CONSOLE_TTY sysConsoleTty
#endif /* _WRS_CONFIG_WRHV_GUEST */

#undef INCLUDE_PC_CONSOLE /* PC keyboard and VGA console */
#ifdef INCLUDE_PC_CONSOLE
# define PC_CONSOLE (0) /* console number */
# define N_VIRTUAL_CONSOLES (2) /* shell / application */
# ifdef INCLUDE_VXBUS
# define DRV_KBD_I8042
# define DRV_VGA_M6845
# endif /* INCLUDE_VXBUS */
#endif /* INCLUDE_PC_CONSOLE */

将其设成定义的,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* use global variable for console tty */

#undef CONSOLE_TTY
#define CONSOLE_TTY sysConsoleTty
#endif /* _WRS_CONFIG_WRHV_GUEST */

#define INCLUDE_PC_CONSOLE /* PC keyboard and VGA console */
#ifdef INCLUDE_PC_CONSOLE
# define PC_CONSOLE (0) /* console number */
# define N_VIRTUAL_CONSOLES (2) /* shell / application */
# ifdef INCLUDE_VXBUS
# define DRV_KBD_I8042
# define DRV_VGA_M6845
# endif /* INCLUDE_VXBUS */
#endif /* INCLUDE_PC_CONSOLE */

7、定位到 #if(SYS_WARM_TYPE == SYS_WARM_BIOS),

1
2
3
4
5
6
7
8
9
10
/* memory addresses, offsets, and size constants */

#if (SYS_WARM_TYPE == SYS_WARM_BIOS) /* non-volatile RAM size */
# define NV_RAM_SIZE (NONE)
#else
# define NV_RAM_SIZE (0x1000)
#endif

#define LOCAL_MEM_LOCAL_ADRS (0x00100000) /* on-board memory base */
#define USER_RESERVED_MEM (0) /* user reserved memory */

修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* memory addresses, offsets, and size constants */

#if (SYS_WARM_TYPE == SYS_WARM_BIOS) /* non-volatile RAM size */
# define NV_RAM_SIZE (NONE)
#else
# define NV_RAM_SIZE (0x1000)
#endif

#ifdef NV_RAM_SIZE
# undef NV_RAM_SIZE
# define NV_RAM_SIZE (NONE)
#endif

#define LOCAL_MEM_LOCAL_ADRS (0x00100000) /* on-board memory base */
#define USER_RESERVED_MEM (0) /* user reserved memory */

修改configNet.h

1、定位到/* max number of END ipAttachments we can have */

1
2
3
4
5
/* max number of END ipAttachments we can have */

#ifndef IP_MAX_UNITS
# define IP_MAX_UNITS (NELEMENTS (endDevTbl) - 1)
#endif

在上面添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* Am79C97x (lnPci) driver defines */

#ifdef INCLUDE_LN_97X_END

#define LN_97X_LOAD_FUNC sysLn97xEndLoad
#define LN_97X_BUFF_LOAN TRUE
#define LN_97X_LOAD_STR ""

IMPORT END_OBJ * LN_97X_LOAD_FUNC (char *, void *);

#endif /* INCLUDE_LN_97X_END */

/* max number of END ipAttachments we can have */

#ifndef IP_MAX_UNITS
# define IP_MAX_UNITS (NELEMENTS (endDevTbl) - 1)
#endif

2、定位到/* Atheros AR521X WLAN Support */

1
2
3
4
5
6
7
8
/* Atheros AR521X WLAN Support */

#ifdef INCLUDE_AR521X_END
{-1, END_TBL_END, NULL, 0, NULL, FALSE}, /* up to 4 Atheros NICs */
{-1, END_TBL_END, NULL, 0, NULL, FALSE},
{-1, END_TBL_END, NULL, 0, NULL, FALSE},
{-1, END_TBL_END, NULL, 0, NULL, FALSE},
#endif /* INCLUDE_AR521X_END */

在上面添加如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
#ifdef INCLUDE_LN_97X_END
{0, LN_97X_LOAD_FUNC, LN_97X_LOAD_STR, LN_97X_BUFF_LOAN,
NULL, FALSE},
#endif /* INCLUDE_LN_97X_END */

/* Atheros AR521X WLAN Support */

#ifdef INCLUDE_AR521X_END
{-1, END_TBL_END, NULL, 0, NULL, FALSE}, /* up to 4 Atheros NICs */
{-1, END_TBL_END, NULL, 0, NULL, FALSE},
{-1, END_TBL_END, NULL, 0, NULL, FALSE},
{-1, END_TBL_END, NULL, 0, NULL, FALSE},
#endif /* INCLUDE_AR521X_END */

添加In97xEnd.c

C:\WindRiver\vxworks-6.8\target\src\drv\end目录下的ln97xEnd.c拷贝进你的Pentium4目录下,

drv

并作如下修改,定位到:

1
2
3
4
do {
; /* poll for suspend mode entry */
}
while ((csrLockedRead (pDrvCtrl, CSR(5)) & CSR5_SPND) == 0);

添加宏如下:

1
2
3
4
5
6
#if !defined(VMWARE_HACK)
do {
; /* poll for suspend mode entry */
}
while ((csrLockedRead (pDrvCtrl, CSR(5)) & CSR5_SPND) == 0);
#endif

添加Sysln97xEnd.c

由于workbench内本身没有提供,因此将我们提供的Sysln97xEnd.c移植到你的Pentium4目录下即可。

与原文件不同的地方在于:

1、定位到/* map a 4Kb 32-bit non-prefetchable memory address decoder */

1
2
3
4
5
6
7
8
9
#if !defined(VMWARE_HACK)
/* map a 4Kb 32-bit non-prefetchable memory address decoder */

if (sysMmuMapAdd ((void *)(memIo32 & PCI_DEV_MMU_MSK),
PCI_DEV_ADRS_SIZE, VM_STATE_MASK_FOR_ALL, VM_STATE_FOR_PCI) == ERROR)
{
return (ERROR);
}
#endif

2、定位到ln97xPciResources[ln97XUnits].bar[0] = ioBase;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    /* update the board-specific resource table */

ln97xPciResources[ln97XUnits].bar[0] = ioBase;
#if defined(VMWARE_HACK)
ln97xPciResources[ln97XUnits].bar[1] = (UINT32)NONE;
#else
ln97xPciResources[ln97XUnits].bar[1] = memIo32;
#endif
ln97xPciResources[ln97XUnits].irq = irq;
ln97xPciResources[ln97XUnits].irqvec = INT_NUM_GET (irq);

ln97xPciResources[ln97XUnits].vendorID = vendorId;
ln97xPciResources[ln97XUnits].deviceID = deviceId;
ln97xPciResources[ln97XUnits].revisionID = revisionId;
ln97xPciResources[ln97XUnits].boardType = boardType;

修改makefile文件

定位到EXTRA_DEFINE,

1
2
3
EXTRA_DEFINE       = -DFAST_REBOOT

MACH_EXTRA =

作如下修改:

1
2
3
EXTRA_DEFINE       = -DVMWARE_HACK -DFAST_REBOOT

MACH_EXTRA = ln97xEnd.o

修改sysNet.c

1、定位到# include “sysUltraEnd.c”

1
2
3
4
5
6
7
8
9
10
/* includes */

#ifdef INCLUDE_END
# include "sysDec21x40End.c" /* dec21x40End support routines */
# include "sysElt3c509End.c" /* elt3c509End support routines */
#ifdef INCLUDE_ENE_END
# include "sysNe2000End.c" /* ne2000End support routines */
#endif
# include "sysUltraEnd.c" /* ultraEnd support routines */
#endif /* INCLUDE_END */

添加内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* includes */

#ifdef INCLUDE_END
# include "sysDec21x40End.c" /* dec21x40End support routines */
# include "sysElt3c509End.c" /* elt3c509End support routines */
#ifdef INCLUDE_ENE_END
# include "sysNe2000End.c" /* ne2000End support routines */
#endif
#ifdef INCLUDE_LN_97X_END
# include "sysLn97xEnd.c"
#endif
# include "sysUltraEnd.c" /* ultraEnd support routines */
#endif /* INCLUDE_END */

2、定位到LOCAL VEND_ID_DESC vendorIdEnet [] =

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* locals */

/* This table maps END PCI driver initialization routines to
* the PCI Vendor IDs for supported (tested) device types.
*/

LOCAL VEND_ID_DESC vendorIdEnet [] =
{
#if defined(INCLUDE_DEC21X40_END)
{DEC_PCI_VENDOR_ID, sysDec21x40PciInit},
#endif /* INCLUDE_DEC21X40_END */

{0xffffffff, NULL} /* last entry */
};

修改内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* locals */

/* This table maps END PCI driver initialization routines to
* the PCI Vendor IDs for supported (tested) device types.
*/

LOCAL VEND_ID_DESC vendorIdEnet [] =
{
#if defined(INCLUDE_DEC21X40_END)
{DEC_PCI_VENDOR_ID, sysDec21x40PciInit},
#endif /* INCLUDE_DEC21X40_END */

#if defined(INCLUDE_LN_97X_END)
{AMD_PCI_VENDOR_ID, sysLan97xPciInit},
#endif /* INCLUDE_LN_97X_END */

{0xffffffff, NULL} /* last entry */
};

当然如果有现有的文件,直接复制覆盖就可以了。

2、打开Workbench3.2,Workspace就选择WindRiver目录下的workspace目录

workspace

3、File->New->Wind River Workbench Project,选择Wind River VxWorks 6.8,然后Next

new

target

4、Build type选择Boot Loader / BSP Project,然后Next

buildtype

5、Project name任取,最好与BSP相关,Location选择默认的in workspace,然后Next

name

6、Board support package选择步骤1中经过修改的Pentium4目录,Tool chain选择gnu,勾上Copy files to project,然后Finish

setup

7、右键选中项目,选择Build Project或者Rebuild Project进行构建

build

done

8、构建完成后,右键选中项目,选择Open Wind River VxWorks 6.8 Development Shell,打开命令行,cd进入Pentium4目录后,输入make bootrom.bin命令,将生成bootrom.bin文件

bootrom

9、找到workspace目录,找到该项目目录,在项目目录下找到Pentium4目录,进入并找到生成的bootrom.bin,复制出来,并修改后缀名为.sys,后续该文件作为引导程序

bootrom

10、找到vxload.com和vxsys.com两个文件(手动搜索,或者一般在XX\WindRiver\vxworks-6.8\host\x86-win32\bin目录下),与上一步得到的bootrom.sys放在一起,以待后续使用

vx

生成VxWorks镜像

1、打开Workbench3.2,Workspace就默认为WindRiver目录下的workspace目录

2、File->New->Other,在Wizards内输入VxWorks image查找并选择VxWorks Image Project,然后Next

image

3、Project name任取,最好与Image相关,Location选择默认项in workspace,然后Next

name

4、4.Based on选择an existing project,Project中将显示此时workspace中的项目,选择第2章节中创建好的BSP项目,然后Finish

setup

5、右键选中项目,选择Build Project或者Rebuild Project构建

6、找到workspace目录,找到该项目目录,在项目目录下找到default目录,进入并找到生成的vxWorks以及vxWorks.sym,复制出来,后续这两个文件将作为VxWorks系统文件通过FTP引导系统

image

VxWorks虚拟机安装

1、首先使用DOS622镜像文件创建虚拟机,镜像文件格式为IMG,大小为1.44MB,软盘的大小。

2、使用VMware,新建虚拟机->典型->稍后安装操作系统->其他(MS-DOS)->自定义名称(默认为MS-DOS)和位置->使用默认最大磁盘大小2GB,将虚拟磁盘存储为单个文件->完成

3、打开上一步创建的虚拟机设置,在硬件部分“添加”“软盘驱动器”

floppy

4、软盘添加“完成”后,选择软盘,勾选“启动时连接”,以及“使用软盘映像文件”,并点击“浏览”选择提供的DOS662.img文件

image

5、选择CD/DVD,取消勾选“启动时连接”,修改内存大小为256MB(适当大小即可)

6、完成设置后,开启该虚拟机,进入开始界面,选择第三个选项Other IDE CD-ROM

startup

7、选择3后进入真正的DOS界面,开始进行硬盘分区,输入fdisk

other

8、选择1,建立DOS分区

fdisk

9、选择1,建立一个主分区

partition

10、选择Y,此时询问这个分区是否使用全部的空间,由于我们只需要一个分区就可以,因此选择Y

full

11、输入任意键,虚拟机将重启

done

12、重新选择3 Other IDE CD-ROM,进行主分区的格式化,输入format c: /s ,这里输入Y确认

format

13、这里询问是否填写卷标,由于并不需要所以直接回车即可

label

14、此时已经有主分区C盘了,关闭虚拟机,在虚拟机设置中选择硬盘,选择“映射”,取消勾选“以只读模式打开文件”后确定,弹出警告点“是”即可,由此将打开该虚拟机的硬盘空间

mapping

当时测试的是Windows10,在某一次更新之后,就无法实现虚拟磁盘映射了。经过测试,几乎所有Windows10版本都是这样,没办法,我只能在Win7上测试。

15、将章节2中的三个文件放入盘中后,在硬盘处“断开连接”,重新开启虚拟机,依然选择3,输入c:进入c盘(即主分区)

files

16、输入dir,可以看见三个文件已经在盘中了

files

17、输入vxsys c: 命令,输入y确认

boot

18、由此bootrom.sys成功设置为引导程序,关闭虚拟机,在虚拟机设置中选择软盘,取消勾选“启动时连接”,再次开启虚拟机,VxWroks系统虚拟机安装完成,其中IP地址为172.18.101.124,也就是所提供的config.h文件内设置的地址

boot

发现与我们修改的不一样,host的值是奔腾的值,我们修改错了。重新来一遍上面的步骤。

正常的效果应该是

boot

19、到主机中,设置主机IP为h的值

host

我的h值就是根据主机IP设置的。

20、在C:\WindRiver\vxworks-6.8\host\x86-win32\bin下找到wftpd32.exe,使用该程序进行FTP的连接,最好将该软件发送到桌面快捷方式以便使用

wftpd32

21、在任意位置创建一个文件夹,用来给目标机提供FTP文件目录,方便起见,我们直接在C盘下创建一个名为ftp的文件夹,将之前得到的vxWorksvxWorks.sym两个文件放入其中

ftp

22、打开wftpd32.exe,Security->Users/Rights->New User->创建一个名为target,密码为target的用户(这个用户名密码是在config.h文件修改时设定好的)

new

23、用户创建好后选择该用户,在Home Directory内填入C:\ftp,即21步中创建的文件夹,然后选择“Done”

security

24、重启VxWorks虚拟机,此时虚拟机将通过FTP连接载入VxWroks系统,完成

result

25、其中,如果在章节3中的文件,只将vxWorks文件放入FTP文件目录而不放置vxWorks.sym,VxWorks系统依然可以跑起来,但在命令行下将没有各种基本命令

问题解决

mmuI86Enable

如果出现mmuI86Enableundefined reference ***之类的错误,表示编译连接的库中没有链接mmuI86Lib.o这个库。

在Makefile中添加上就可以了

1
2
3
EXTRA_DEFINE       = -DVMWARE_HACK -DFAST_REBOOT

MACH_EXTRA = ln97xEnd.o mmuI86Lib.o

当然,要把位于arch/i86/下的mmuI86Lib.c复制到奔腾4目录下。

DOSIMG

DOSIMG版本经过测试7.1版本是不行的,现在使用的是6.22版本,不知道其他版本行不行。

本文附属的代码和编译结果在VxWorks_Freshman中,可以直接替换文件。