8.9   Creating Bootable Applications

As you approach a final version of your application, you will probably want to add modules to the bootable system image, and include startup of your application with the system initialization routines. In this way, you can create a bootable application, which is completely initialized and functional after booting, without requiring any interaction with the host-resident development tools.

Linking the application with VxWorks is really a two-step process. You must add an entry point to the application in usrConfig.c, and you must modify the makefile to link the application statically with VxWorks.

To start your application during system initialization, add code to the usrRoot( ) routine in usrConfig.c. You can call application initialization routines, create additional I/O devices, spawn application tasks, and so on, just as you do from the Tornado shell during development. An example is provided in usrConfig.c. This file includes and initializes a simple demo if the preprocessor constant INCLUDE_DEMO is defined in one of the configuration files. In that situation, usrRoot( ) spawns usrDemo( ) as a task as the last step in booting the system. You can simply insert the appropriate initialization of your application after the conditional code to start the demo. For example:

/* spawn demo if selected */ 
#if defined(INCLUDE_DEMO) 
    taskSpawn ("demo", 20, 0, 2000, (FUNCPTR)usrDemo, 0,0,0,0,0,0,0,0,0,0); 
#endif 
    taskSpawn ("myMod", 100, 0, 20000, (FUNCPTR)myModEntryPt, 
    0,0,0,0,0,0,0,0,0,0);

To include your application modules in the bootable system image, add the names of the application object modules (with the .o suffix) to MACH_EXTRA in Makefile. For example, to link the module myMod.o, add a line like the following:

MACH_EXTRA = myMod.o 
...

Building the system image with the application linked in is the final part of this step. In the target directory, execute the following command:

% make vxWorks

Application size is usually an important consideration in building bootable applications. Generally, VxWorks boot ROM code is copied to a start address in RAM above the constant RAM_HIGH_ADRS, and the ROM in turn copies the downloaded system image starting at RAM_LOW_ADRS. The values of these constants are architecture dependent, but in any case the system image must not exceed the space between the two. Otherwise the system image overwrites the boot ROM code while downloading, thus killing the booting process.

To help avoid this, the last command executed when you make a new VxWorks image is vxsize, which shows the size of the new executable image and how much space (if any) is left in the area below the space used for ROM code:

vxsize 386 -v 00100000  00020000  vxWorks 
vxWorks: 612328(t) + 69456(d) + 34736(b) = 716520 (235720 bytes left)

If your new image is too large, vxsize issues a warning. In this case, you can reprogram the boot ROMs to copy the ROM code to a sufficiently high memory address by increasing the value of RAM_HIGH_ADRS in config.h and in your BSP's Makefile (both values must agree). Then rebuild the boot ROMs by executing the following command:

% make bootrom.hex

The binary image size of typical boot ROM code is 128KB or less. This small size is achieved through compression; see Boot ROM Compression. The compressed boot image begins execution with a single uncompressed routine, which uncompresses the remaining boot code to RAM. To avoid uncompressing and thus initialize the system a bit faster, you can build a larger, uncompressed boot ROM image by specifying the make target bootrom_uncmp.hex.

8.9.1   Creating a Standalone VxWorks System with a Built-in Symbol Table

It is sometimes necessary to create a VxWorks system that includes a copy of its own symbol table. However, it is confusing to work with the host-resident Tornado tools when there is a target-resident symbol table, because the host-resident tools use a separate symbol table on the host. Thus, it is advisable to include the target-resident versions of the development tools (especially the shell) in this configuration, until you are ready to build a finished application that requires no interaction with the target.

The procedure for building such a system is somewhat different from the procedure described above. No change is necessary to usrConfig.c. A different make target, vxWorks.st, specifies the standalone form of VxWorks:

% make vxWorks.st

The rules for building vxWorks.st create a module usrConfig_st.o, which is the usrConfig.c module compiled with the STANDALONE flag defined. The STANDALONE flag causes the usrConfig.c module to be compiled with the built-in system symbol table, the target-resident shell, and associated interactive routines.

The STANDALONE flag also suppresses the initialization of the network. If you want to include network initialization, define STANDALONE_NET in either of the header files installDir/target/config/bspname/config.h or installDir/target/config/all/configAll.h.1

VxWorks is linked as described previously, except that the first pass through the loader does not specify the final load address; thus the output from this stage is still relocatable. The makeSymTbl tool is invoked on the loader output; it constructs a data structure containing all the symbols in VxWorks. This structure is then compiled and linked with VxWorks itself to produce the final bootable VxWorks object module.

As before, to include your own application in the system image, add the object modules to the definition of MACH_EXTRA and follow the procedures discussed in the previous section.

Because vxWorks.st has a built-in symbol table, there are some minor differences in how it treats VxWorks symbols, by contrast with the symbol table used through the target server during development. First, VxWorks symbol table entries cannot be deleted from the vxWorks.st symbol table. Second, no local (static) VxWorks symbols are present in vxWorks.st.

8.9.2   Creating a VxWorks System in ROM

General Procedures

To put VxWorks or a VxWorks-based application into ROM, you must enter the object files on the loader command line in an order that lists the module romInit.o before sysALib.o. Also specify the entry point option -e _romInit. The romInit( ) routine initializes the stack pointer to point directly below the text segment. It then calls bootInit( ), which clears memory and copies the vxWorks text and data segments to the proper location in RAM. Control is then passed to usrInit( ).

A good example of a ROM-based VxWorks application is the VxWorks boot ROM program itself. The file installDir/target/config/all/bootConfig.c is the configuration module for the boot ROM, replacing the file usrConfig.c provided for the default VxWorks development system. The makefiles in the target-specific directories contain directives for building the boot ROMs, including conversion to a file format suitable for downloading to a PROM programmer. Thus, you can generate the ROM image with the following make command:

% make bootrom.hex

Tornado makefiles also define a ROMable VxWorks runtime system suitable for use with Tornado tools, as the target vxWorks.res_rom_nosym. To generate this image in a form suitable for writing ROMs, run the following command:

% make vxWorks.res_rom_nosym.hex

VxWorks target makefiles also include the entry vxWorks.st_rom for creating a ROMable version of the standalone system described in the previous section. vxWorks.st_rom differs from vxWorks.st in two respects: (1) romInit code is loaded as discussed above, and (2) the portion of the system image that is not essential for booting is compressed by approximately 40 percent using the VxWorks compress tool (see Boot ROM Compression).

To build the form of this target that is suitable for writing into a ROM (most often, this form uses the Motorola S-record format), enter:

% make vxWorks.st_rom.hex

When adding application modules to a ROMable system, size is again an important consideration. Keep in mind that by using the compress tool, a configuration that normally requires a 256-KB ROM may well fit into a 128-KB ROM. Be sure that ROM_SIZE (in both config.h and Makefile) reflects the capacity of the ROMs used.

Boot ROM Compression

VxWorks boot ROMs are compressed to about 40 percent of their actual size using a binary compression algorithm, which is supplied as the tool compress. When control is passed to the ROMs on system reset or reboot, a small (8 KB) uncompression routine, which is not itself compressed, is executed. It then uncompresses the remainder of the ROM into RAM and jumps to the start of the uncompressed image in RAM. There is a short delay during the uncompression before the VxWorks prompt appears. The uncompression time depends on CPU speed and code size; it takes about 4 seconds on an MC68030 at 25 MHz.

This mechanism is also available to compress a ROMable VxWorks application. The entry for vxWorks.st_rom in the architecture-independent portion of the makefile, installDir/target/h/make/rules.bsp, demonstrates how this can be accomplished. For more information, see also the reference manual entries for bootInit and compress.


1:  vxWorks.st suppresses network initialization, but it includes the network. The STANDALONE option defines INCLUDE_STANDALONE_SYM_TBL and INCLUDE_NETWORK, and undefines INCLUDE_NET_SYM_TBL and INCLUDE_NET_INIT. The alternative option STANDALONE_NET includes INCLUDE_NET_INIT.