Academic Company Events NI Developer Zone Support Solutions Products & Services Contact NI MyNI

Document Type: Tutorial
NI Supported: No
Publish Date: Apr 10, 2008

Developing Shared Libraries for the cRIO-901x and Other VxWorks Targets

4 ratings | 4.75 out of 5
Print

Overview

LabVIEW Real-Time users may use their own shared libraries to interface with C/C++ code. For controllers running Wind River VxWorks, including the CompactRIO 901x series, the GNU toolchain distributed with VxWorks is used to compile shared libraries. These shared libraries can be accessed through the Call Library Node similarly to other LabVIEW platforms. National Instruments recommends using CVI Real-Time for C-based shared libraries. This allows for proper compilation and allows for remote debugging. If the shared library is C++-based, National Instruments recommends using VC 6 or VC 7.1 compilers. This document describes developing VxWorks-compatible shared libraries using either a licensed copy of the VxWorks development environment, or a standalone copy of the free GNU toolchain. This document assumes development experience with both the VxWorks and LabVIEW Real-Time environments.

Obtaining the GNU Toolchain

The GNU tool chain for VxWorks may be obtained by either purchasing a VxWorks development license from Wind River; or by downloading a redistributable GNU tool chain attached to this document. Purchasing VxWorks also allows the use of the Wind River Workbench IDE, featuring source code level debugging and build management. If GCC is used otherwise, debugging can only be accomplished at the assembly code level, and building may be accomplished through direct use of GNU Make.

Note: LabVIEW Real-Time 8.5 installs version 6.3 of the VxWorks OS to compatible targets. LabVIEW Real-Time 8.20 installs version 6.1 of the VxWorks OS to compatible targets. All builds should be targeted to corresponding versions and use the corresponding header files. As new versions of NI LabVIEW Real-Time become available, different versions of VxWorks may be installed and may require rebuilding of your libraries. Refer to the LabVIEW Real-Time Read-Me to find the correspondent OS version for that Real-Time release.

Important notes while compiling

  • ABI Incompatibility. Shared libraries compiled for VxWorks controllers are completely incompatible with those compiled for other controllers, and vice versa.
  • Alignment changes. PowerPC-based controllers, including the cRIO-901x series, use 4-byte alignment for all numbers, arrays, pointers, clusters, and handles. This may cause incompatibilities with existing binary file formats used for existing Real-Time shared libraries, or with data passed to/from LabVIEW. Consult the Passing Variably-Sized Data to CINs section of Calling Code Written in Text-Based Programming Languages in the LabVIEW Help for more information.
  • LabVIEW can only call C functions. The Windows host cannot directly look up the symbols present in VxWorks-compiled shared libraries. As a result, symbols with C++ linkage cannot be called. All functions called from LabVIEW must have extern “C” linkage.
  • The Win32 API is not available. VxWorks does not support Windows API calls. Replace them, when possible, with ISO C or C++ calls. If you have a full license for VxWorks, then the complete OS API is made available to you; consult the VxWorks documentation for additional details.
  • Incompatibilities between the GNU tool chain and the Microsoft Visual C++ tool chain. Code compiled using the Microsoft Visual C++ compiler may not immediately compile in GCC. This is remedied by following guidelines for cross-platform development and consulting the GNU Compiler Collection documentation.
  • Avoid duplicate symbol names between shared libraries. VxWorks places all global symbols in the same symbol namespace. If two libraries are loaded with the same global symbol, a warning is displayed, but the load succeeds. This may cause a silent failure if a third library is loaded that expects to reference a symbol from one module, but is linked against another library. To avoid this issue, keep as many symbols marked local (static) as possible, and prefix the remaining symbols with a unique identifier.
  • Larger code size. Compared against equivalent source code compiled for Windows targets, code compiled for the cRIO-901X controllers is roughly 50-300% larger.
  • Strict aliasing optimizations may introduce bugs in your code. The use of strict aliasing optimizations, through the use of “-Os”, “-O2” or higher optimizations, or “-fstrict-aliasing” is highly discouraged. Use the “-fno-strict-aliasing” compiler flag for all optimized builds.
  • Autodownloading is not supported. LabVIEW will not download a shared library to a VxWorks target if it is referenced by a VI and does not already exist on the target. The library must be sent via FTP to the appropriate folder on the target.
  • Directory restrictions. Shared libraries must exist in the ni-rt/ or ni-rt/system/ directories to be used by LabVIEW VIs. Paths specified in the Call Library Node will be ignored.
  • Use –mlongcall for all compiles. This option allows function calls between modules separated by more than 32MB of memory and is required for correct shared library linkage. When –mlongcall is not supplied, you may see console errors of the form “Relocation value does not fit in 24 bits.” and the library will fail to load.
  • DllMain() is not supported for library initialization. One workaround is to place initialization and shutdown code in static global constructors and destructors. Alternatively, consult the VxWorks Application Programmer’s Guide for information on the _WRS_CONSTRUCTOR macro which may be used to initialize libraries.

Compiling with GNU Make

If Wind River Workbench is not available, e.g. when the GNU tool chain redistributable is being used, GNU Make may be used to compile your projects. Use the following makefile as a template to construct your own makefile for your project.

# These variables control the compiler and linker flags. Change them as

# appropriate.

DEBUG_MODE = 0

ADDED_CFLAGS =

ifeq ($(DEBUG_MODE),1)

OBJ_DIR := PPC603gnu_DEBUG< /SPAN>

CFLAGS = -g -mlongcall

else

OBJ_DIR := PPC603gnu< /SPAN>

CFLAGS = -Os -fstrength-reduce -fno-builtin -fno-strict-aliasing -mlongcall

endif

LINKFLAGS = $(CFLAGS)

LIBPATH =

# List all the *compiled* object files here, under the OBJ_DIR

# directory. Make will automatically locate the source file and

# compile it.

OBJECTS := $(OBJ_DIR)/example.o< /SPAN>

# This is the name of the output shared library.

PROJECT_TARGETS := $(OBJ_DIR)/example.out< /SPAN>

# If you have other VxWorks .a files to reference, list them here.

LIBS =

LIBPATH =

# Everything after this line should not need to be modified for

# basic compilation. However, significant changes to the build structure

# will probably involve modifying these lines.

WIND_BASE := $(subst \,/,$(WIND_BASE))< /SPAN>

CPU = PPC603

TOOL_FAMILY = gnu

TOOL = gnu

CC_ARCH_SPEC = -mcpu=603 -mstrict-align -mno-implicit-fp < /SPAN>

IDE_INCLUDES = -I$(WIND_BASE)/target/h -I$(WIND_BASE)/target/h/wrn/coreip

# This basic rule compiles a .c file into a .o file. It can be adapted to

# all other source files that GCC can compile, including assembly (.s) and

# C++ (.cpp, .cc, .C, .cxx) files. To enable support for those extensions,

# copy this rule and modify its extension and compile flags for the

# required source file type.

$(OBJ_DIR)/%.o : %.c

ccppc $(CFLAGS) $(CC_ARCH_SPEC) -ansi -Wall -MD -MP $(ADDED_CFLAGS) $(IDE_INCLUDES) $(ADDED_INCLUDES) -DCPU=$(CPU) -DTOOL_FAMILY=$(TOOL_FAMILY) -DTOOL=$(TOOL) -D_WRS_KERNEL $(DEFINES) -o "$@" -c "$<"< /SPAN> < /SPAN>

# Adapted rule for .cpp files

$(OBJ_DIR)/%.o : %.cpp

c++ppc $(CFLAGS) $(CC_ARCH_SPEC) -ansi -Wall -MD -MP $(ADDED_CFLAGS) $(IDE_INCLUDES) $(ADDED_INCLUDES) -DCPU=$(CPU) -DTOOL_FAMILY=$(TOOL_FAMILY) -DTOOL=$(TOOL) -D_WRS_KERNEL $(DEFINES) -o "$@" -c "$<"< /SPAN> < /SPAN>

all : check_objectdir $(PROJECT_TARGETS)

$(PROJECT_TARGETS) : $(OBJECTS)

rm -f "$@" ctdt.c;nmppc $(OBJECTS) | tclsh $(WIND_BASE)/host/resource/hutils/tcl/munch.tcl -c ppc > ctdt.c

ccppc $(LINKFLAGS) $(CC_ARCH_SPEC) -fdollars-in-identifiers -Wall $(ADDED_CFLAGS) $(IDE_INCLUDES) $(ADDED_INCLUDES) -DCPU=$(CPU) -DTOOL_FAMILY=$(TOOL_FAMILY) -DTOOL=$(TOOL) -D_WRS_KERNEL $(DEFINES) -o ctdt.o -c ctdt.c< /SPAN> < /SPAN>

ccppc -r -nostdlib -Wl,-X -T $(WIND_BASE)/target/h/tool/gnu/ldscripts/link.OUT -o "$@" $(OBJECTS) $(LIBPATH) $(LIBS) $(ADDED_LIBPATH) $(ADDED_LIBS) ctdt.o

rm -f ctdt.c ctdt.o

check_objectdir :

@if [ ! -d "$(OBJ_DIR)" ]; then\

mkdir -p $(OBJ_DIR);\

fi

clean :

rm -f $(OBJECTS) $(PROJECT_TARGETS) $(wildcard $(OBJ_DIR)/*.unstripped)

.DUMMY: check_objectdir clean

Compiling with Wind River Workbench

Creating a New Project

Open Wind River Workbench, the main VxWorks application IDE. The Open Wind River Workbench contains an integrated debugger and symbol table.


[+] Enlarge Image

This Open Wind River Workbench splash screen appears the first time you start the application. Select Start to continue.


[+] Enlarge Image

Select Workbench to display the Wind River Workbench window.


[+] Enlarge Image

You must create a new Wind River Workbench project to build a VxWorks Kernel Library. Select File » New » VxWorks Downloadable Kernel Module Project to create a new project.

Enter a unique name for the project using the Project name text box. Click the Next button until you arrive at the Build Specs page. Click the Deselect All button and the select PPC603gnu. Click the Finish button.

 

Importing the Library Source Code

In the IDE, select File » Import to open the Import dialog box. Select File system from the import source list and then click the Next button.

Browse to your tutorial source code directory and select the library.cpp and library.h files. These files are the included sample code for the example library. Click Finish to complete the import of the source code into your new project.

Building the library

Select Project » Build Project from the Workbench window.

The build output will appear in the Build Console. A dialogue for generating includes may appear on the first build. Accept the recommended include paths.


[+] Enlarge Image


Downloading and Executing Shared Library Code

Use your choice of FTP program to upload your built library to the ni-rt/system directory on the target. Your module is now ready to use from within LabVIEW VIs.

Shared libraries can be called in a virtually identical manner on VxWorks compared to how they are called on other Real-Time targets – through the use of the Call Library Function node. The only real limitation is that, as the LabVIEW development environment cannot read the library information in VxWorks shared libraries, configuration of the Call Library Function node must be done blindly, without parsed symbol lists. (This can be worked around by configuring the node to use a Win32 build of the same library. The VxWorks library will be used on the target.) Note that the Calling Convention configuration parameter is ignored.

For more information on calling shared library code, consult LabVIEW Help>>Fundamentals » Calling Code Written in Text-Based Programming Languages » Concepts » Using External Code in LabVIEW, and NI Developer Zone: An Overview of Accessing DLLs or Shared Libraries from LabVIEW.

Debugging through the serial console

This section describes debugging techniques available with the GNU tool chain that do not require the Wind River Workbench IDE.

Disabling the CPU exception handler

CPU exceptions include crashes and breakpoints. By default, CPU exceptions trigger a reboot of the controller. This must be disabled in order to set breakpoints or debug a task that has crashed. The handler can be disabled through two different ways.

Disabling via INI file

The first way is to modify the ni-rt.ini file on the controller to add the given text; this will disable exceptions until the text is removed.

[debug]
InstallExceptionHandlers=false

Disabling via bootline

The second way is to boot the controller manually. Exceptions will be re-enabled on the next reboot.

  1. Reboot the controller and the following text should appear, along with a 1-second countdown:

    Press any key to stop auto-boot…

  2. Press a key then type the following text into the console:

    @tffs=0,0(0,0)host:/c/ni-rt/system/vxWorks f=0x8 o=0x1000

  3. When the “->” prompt appears type:

    realInitVxExec

Configuring the console

VxWorks development often requires the use of the serial console. This console provides standard input/output for running code and a command shell for executing commands.

To connect your computer to the serial console, follow these instructions.

  • Connect a null modem serial cable from your computer’s serial port to the controller’s serial port.
  • Configure a terminal program for 9600 bps, no parity bit, 8 data bits, and 1 stop bit.
  • Enable the DIP switch marked “CONSOLE OUT” on the cRIO and reboot it. The terminal should display output and diagnostics during the boot process. When it is finished, the message “Welcome to LabVIEW Real-Time” will print.

    Loading LVRT...

    Welcome to LabVIEW Real-Time 8.2.1

For more information about using the console, consult the VxWorks Kernel Programmer’s Guide.

Using the console

The console can print debug statements compiled into the library, and can set breakpoints at functional scope. Execution debugging can be performed at assembly code scope. No licensing is required to use this functionality.

Here is a brief summary of the commands used at the console to debug shared libraries. Please consult the VxWorks documentation for more details.

Name

Command

Example

Function breakpoints

b <function name or instruction address>

b MyFunction

Resolve a symbol to an address

lkup “<symbol name>

lkup “MyFunction”

Disassemble a function

l <function name or instruction address>

l MyFunction

Step through a single instruction

s [<task name or id>]

s 0xc73d08

Step through a single instruction; step over subroutine calls

so [<task name or id>]

so 0xc73d08

Continue execution

c [<task name or id>]

c 0xc73d08

Spawn a new task

taskSpawn “<task name>”, 100, 8, 65536,

<function name>

taskSpawn “test”,100,8,65536,MyFunction

List all running tasks

i

I

Show task information

ti <task name or id>

ti 0xc73d08

Load library from disk

ld < <library path>

ld < mylib.out

Memory dump

d <symbol name or address>

d 0x100000

Debugging with Wind River Workbench

The techniques described in this section require the Wind River Workbench which can be obtained from and is supported by Wind River.

Disabling the CPU exception handler

As when debugging through the console, the CPU exception handler must be disabled. See the above section for instructions.

Configuring the target server

The target server is a process running on the host that sends debugging commands to the target. (The target runs a process to process these commands.) It is used for source-level debugging and can also be used to download shared libraries. By default, it is not enabled on a cRIO, but it can be enabled after boot with these instructions.

  • Boot the controller with the target console (see the Appendix section above on configuring the target console).
  • When booting is complete, run the following command on the console shell:

    debuggingInit

    You should see output similar to the following:

    Debugging is up, target server mounted at /z
    VxWorks
    Copyright 1984-2005 Wind River Systems, Inc.
    CPU: MPC5200 -- Wind River Lite5200 BSP.
    Runtime Name: VxWorks
    Runtime Version: 6.1
    BSP version: 2.0/10
    Created: Sep 19 2006, 14:16:01
    ED&R Policy Mode: Lab
    WDB Comm Type: WDB_COMM_END
    WDB: Ready.

    value = 0 = 0x0
  • FTP the file “ni-rt/system/vxWorks” from the cRIO to the host.
  • Create a new Target Connection in Workbench, under the Target Manager view. The following configuration parameters are required:
    • Name / IP Address = IP address of controller
  • Kernel Image File = Path to downloaded vxWorks file
  • The configuration window should look similar to this:


  • Connect to the target through the new connection entry.

For more information, please consult the Wind River Workbench User’s Guide.

Using the Workbench debugger

Workbench can capture standard I/O from the console, set breakpoints at function and line scope, and trace running code at source code scope.

Debugging with Workbench requires the following:

  • A fully licensed copy of Workbench
  • A debug build of the shared library
  • An active target server connection (visible via the Target Manager view in Workbench)
  • The shared library must be loaded on the target, and the target server has loaded its symbols from the local library copy. (The icon representing the library will have an “S” on it, and the symbols are reported as loaded.)

Breakpoints may be set from the console or from the source code view. To set a source code breakpoint, right-click on the left bar of the view and select “Add Global Line Breakpoint.”


[+] Enlarge Image

 

The target console will report when a breakpoint is hit. To debug at the breakpoint location, locate the stopped task in the Process tree of the target server connection, right-click it, and select Attach to Process.

 

The Debug menu is now populated with a full set of debugging commands.

For additional information, consult the Workbench User’s Guide.

Downloads

vxworks63gccdist.zip

vxworks61gccdist.zip

4 ratings | 4.75 out of 5
Print

Reader Comments | Submit a comment »

 

Legal
This tutorial (this "tutorial") was developed by National Instruments ("NI"). National Instruments does not support this tutorial or guarantee its quality in any way. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).