Documente Academic
Documente Profesional
Documente Cultură
0
User’s Guide
VenturCom, Inc.
Five Cambridge Center
Cambridge, MA 02142
Tel: 617-661-1230
Fax: 617-577-1607
info@vci.com
http://www.vci.com
RTX User’s Guide
No part of this document may be reproduced or transmitted in any form or by any means,
graphic, electronic, or mechanical, including photocopying, and recording or by any
information storage or retrieval system without the prior written permission of VenturCom,
Inc. unless such copying is expressly permitted by federal copyright law.
While every effort has been made to ensure the accuracy and completeness of all information
in this document, VenturCom, Inc. assumes no liability to any party for any loss or damage
caused by errors or omissions or by statements of any kind in this document, its updates,
supplements, or special editions, whether such errors, omissions, or statements result from
negligence, accident, or any other cause. VenturCom, Inc. further assumes no liability arising
out of the application or use of any product or system described herein; nor any liability for
incidental or consequential damages arising from the use of this document. VenturCom, Inc.
disclaims all warranties regarding the information contained herein, whether expressed,
implied or statutory, including implied warranties of merchantability or fitness for a particular
purpose.
VenturCom, Inc. reserves the right to make changes to this document or to the products
described herein without further notice.
RTX is a trademark and CENTer is a servicemark of VenturCom, Inc.
Microsoft, MS, and Win32 are registered trademarks and Windows, Windows CE, and
Windows NT are trademarks of Microsoft Corporation.
All other companies and product names may be trademarks or registered trademarks of their
respective holders.
iii
RTX User’s Guide
iv
RTX User’s Guide
v
RTX User’s Guide
vi
RTX User’s Guide
vii
RTX User’s Guide
viii
Welcome to RTX 5.0
In addition to using the real-time interfaces and tools provided by RTX, developers can
continue to take advantage of the abundance of products available for Windows NT and
Windows 2000. And, with the RTX inter-process communication features, the Win32 run-
time environment works seamlessly with the RTX real-time subsystem — enabling the
integration of Win32 and real-time functionality.
Experienced real-time developers will value the power of the RTX interface; we suggest that
you refer to the topics in the RTX Overview for a more detailed description of RTX and a
discussion of important design decisions that need to be made in order to fully take advantage
of RTX features.
Getting Support
VenturCom offers a number of support options for RTX users, including technical support
and the VenturCom Web site.
Note: If you are a customer who purchased direct support, you would have received a
Support ID# in the letter that comes with the software. Please have this number available for
reference when contacting VenturCom. Users who purchased their product through third
parties should contact those parties directly with their questions.
Technical Support
For technical support related to installing and using RTX, VenturCom offers several channels
of communication. You can:
Call technical support at 800-334-8649 between 9:00 AM and 6:00 PM (Eastern Time)
ix
RTX User’s Guide
http://www.vci.com/tech_support/support_description.html
If you are a customer with a current support contract or a member of the Real-time and
Embedded Partner Program, then you should bookmark to the Web page in the Technical
Support Area located at:
http://www.vci.com/tech_support/support_login.html
These pages provide electronic access to the latest product releases, documentation, and
release notes. With a valid Support ID#, you can access the online problem report database to
submit new issues, or to obtain the status of previously reported issues.
Documentation Updates
VenturCom is committed to providing you with the information you need to use our products.
From time to time, we may provide documentation updates for our products. Check our
CENTer page for updates. While visiting CENTer, check out the various white pages and
presentations. CENTer also provides access to several newsgroups. You’ll also find free
utilities and extensions that you can download.
RTX Overview — Describes the RTX architecture, discusses how to design programs using
RTX.
Using Software Development Tools — Explains how to use RTX programs, utilities, and
tools to develop real-time applications. It also contains procedures for building applications
and dynamic link libraries as well as procedures for debugging and testing your application.
Using the RTX Functionality — Presents the RTX functionality, discusses important real-
time programming issues, and provides references to real-time code examples that illustrate
the implementation of real-time programming techniques.
Performance — Discusses key real-time performance issues, such as latency metrics and
timing factors, and provides programming approaches for ensuring good response times in
your applications. It also explains how to use the RTX performance tools.
x
CHAPTER 1
Introduction to RTX
Today’s real-time and embedded applications contain a broad range of functionality, such as
GUI-based operator interfaces, communication with other information systems, and time-
critical monitoring and control of equipment. For both developers and end users of these
applications, Windows NT and Windows 2000 — with their advanced features, range of
supported hardware configurations, and availability of off-the-shelf add-on components —
are the the operating system platforms of choice. However, since their functionality was not
targeted for "hard" real-time applications, the use of Windows NT and Windows 2000 are
significantly restricted, and often prevented, for these applications. VenturCom's RTX
product bridges this gap by adding "hard" real-time capabilities to both Windows NT and
Windows 2000.
By extending the Windows NT and Windows 2000 operating systems, RTX enables
application components or modules that require deterministic and high-speed response times,
along with other non-real-time application components, to work together on a common
Windows system. With RTX, you can use a single, low-cost platform to satisfy a full range of
real-time and embedded application requirements.
While RTX brings superior real-time capabilities to Windows NT and Windows 2000, there
are two areas in which real-time application developers must take active responsibility to
fully realize its benefits. First, because worst-case response times vary significantly among
systems, developers and their end users must carefully select their systems. Different board
vendors, especially video card vendors, make different tradeoffs between price, throughput,
and deterministic behavior. With the help of VenturCom's RTX performance analysis tools,
developers and their users can select systems that ensure their real-time requirements are met.
Second, developers must properly implement RTX in their applications. RTX provides raw
power that can, if implemented in applications improperly, adversely impact other Windows
applications and might even compromise overall system stability. The User’s Guide can assist
you in implementing RTX.
1
RTX User’s Guide
57;DQG:LQGRZV17:RUNLQJ7RJHWKHU
RTSS also supports Inter-Process Communication (IPC) objects that can be manipulated by
either RTSS or Win32 processes; this enables simple and standard communication and
synchronization between real-time and non-real-time programs. Finally, RTSS provides other
time-critical services — such as clocks and timers and interrupt management — to RTSS
processes.
HAL Extension
RTX includes a real-time enabled Hardware Abstraction Layer (HAL) extension. This
extension maintains interrupt isolation between RTSS and Windows NT or Windows 2000.
Windows cannot mask (at the interrupt controller level) interrupts managed by RTSS.
Windows interrupts are masked during RTSS processing. The real-time HAL extension
supports high-resolution clocks and timers for RTSS, while it also supports non-real-time
clocks and timers for Windows NT and Windows 2000. Other real-time HAL extension
features include a software interrupt mechanism between RTSS and Windows; basic
exception management; and various enhancements for determinism.
RTX supports both uniprocessor and multiprocessor Windows NT and Windows 2000
systems. The run-time version of RTX, which supports multiprocessor systems, provides all
of the features of the uniprocessor version, plus it exploits the features of Intel MPS-
compliant multiprocessor systems to provide improved performance in both Windows and
RTX environments.
Run-time RTX, for multiprocessor systems, implements a dedicated processor model. In this
model, RTSS runs on one processor, while the remaining processors continue to run on
Windows. The multiprocessor HAL acquires control of the last logical processor during the
Windows boot sequence and it is reserved for RTSS. RTSS programs can then be loaded and
2
Chapter 1: Introduction
The RTX Application Programming Interface for Win32 and RTSS processes, including
Floating-Point Unit (FPU) and structured exception handling, is used for both uniprocessor
and multiprocessor systems. This eliminates the need to recode RTX (uniprocessor)
applications for a multiprocessor platform.
Win32_and_Real-Time_API
RTX_Executable_Images
Run-Time_Libraries
Unicode
Win32 and Real-Time API
RTX supports a subset of Win32 API functions, plus it provides a special set of real-time
functions, known as RTAPI (Real-Time API). RTAPI functions are identified by an "Rt"
prefix in their names. Some RTAPI functions are semantically identical to their Win32
counterparts, while others are unique to RTX (i.e., there are no similar Win32 calls). For
example, RTAPI real-time IPC functions differ from Win32 IPC functions only in the IPC
name space in which they operate and in the determinism possible with real-time IPC objects.
On the other hand, the Win32 API does not include any functions related to interrupt
management; therefore, unique interrupt management functions are defined in RTAPI.
The RTX API was carefully selected to promote efficient development of real-time
application components. RTX intentionally does not include Win32 functions, such as the
GUI-related calls, that are normally used by the less time-critical components of an
application. In fact, Win32 functions that are not essential to real-time programming, and
impractical to implement with deterministic behavior, are not included in the RTX API. It is
expected that most applications will consist of at least two processes working together-one
Win32-based process (to take advantage of GUI and other Win32-only functions) and an
RTSS-based process to perform time-critical processing.
RTX provides three types of executable images: RTSS applications, RTSS DLLs, and
RTDLLs. RTSS applications are the real-time analogues of Win32 applications. RTSS DLLs
are RTSS applications that have been linked to provide an export library that RTSS and other
applications can use to call functions within an RTSS DLL. RTSS DLLs are full RTSS
processes and must be launched manually prior to their use by RTSS applications. RTDLLs
3
RTX User’s Guide
are passive code containers, similar in functionality to Win32 DLLs, which run in RTSS. For
details about how to choose, design, and build appropriate combinations of these types of
images, see the chapters Using Software Development Tools and Developing an Application
in this guide.
Run-Time Libraries
RTX also supports various run-time libraries, and provides a ’C’ run-time library based on MS
Visual C++. RTSS processes can be statically linked to include these libraries, provided they
do not attempt to link to unsupported Win32 functions. RTSS processes can also be linked
against specialized versions of dynamic link libraries (DLLs), which can be used to
modularize real-time application code or provide run-time customization of real-time
software environments.
Unicode
RTX supports Unicode applications. An RTSS process can use the wmain() function and
accept wide character input arguments. Support for the WCS family of functions is included
as part of the RTX-supported C run-time library.
RTX_Device_Drivers
Testing Real-Time Applications
Starting an RTSS Process
Stopping an RTSS Process
Some designs call for application components that act as device drivers to other application
components, or board vendors may want to provide real-time device drivers for their boards
that can be used by a variety of real-time and non-real-time applications. The device driver
designer can use either DLLs or real-time IPC mechanisms to connect drivers and
applications together. The real-time IPC offers the most flexible option because Win32 and
RTSS processes can both access a common real-time driver using the same interface, even at
the same time. The sample directory includes an RTX library for device drivers based on
real-time IPC that provides a traditional device driver interface (e.g., open, close, read, write,
4
Chapter 1: Introduction
In most cases, the initial development and testing of real-time application components,
including device drivers, is most easily done in the Win32 environment. The Win32
environment provides the widest range of development, debug, and test tools, and the best
detection of misbehaving applications. After all non-time-critical testing is completed, the
real-time application component is simply re-linked as an RTSS process for final testing in
the deterministic RTSS environment. If extensive debugging of RTSS processes is necessary,
you can use Microsoft’s WinDbg.
Several methods are available for starting RTSS processes. During development and testing,
you will typically start RTSS processes from the command prompt with optional command
line arguments or by clicking on the RTSS executable file icon in Windows Explorer. For
final applications, you will generally use either the feature that starts specified RTSS
processes at boot time (i.e., when the "blue screen" starts), or you will launch RTSS processes
directly from a Win32 process. To create and launch the RTSS process directly, you will use
the Win32 RTCreateProcess call to ceate and start the specified RTSS process.
5
RTX User’s Guide
6
CHAPTER 2
7
RTX User’s Guide
The table that follows shows which utility to use to perform a particular task.
,I\RXZDQWWR 8VH
5XQDQ5766SURFHVV 5766UXQFRQVROHRUIURPWKH57;6WDUW
PHQX
/RDGDQ5766'// 5766UXQFRQVROHRUIURPWKH57;6WDUW
PHQX
5HJLVWHUDQ57'// 5766UXQFRQVROHRUIURPWKH57;6WDUW
PHQX
7HUPLQDWHDQ5766SURFHVV 5766NLOOFRQVROH
RU
57667DVN0DQDJHURQWKH57;6WDUW
PHQX
8QUHJLVWHUDQ57'// 5766NLOOFRQVROH
RU
57667DVN0DQDJHURQWKH57;6WDUW
PHQX
9LHZDOLVWRIDOOSURFHVVHVDQG 5766NLOOFRQVROH
UHJLVWHUHG57'//V RU
57667DVN0DQDJHURQWKH57;6WDUW
PHQX
9LHZLQIRUPDWLRQDERXW5766SURFHVVHV 5766YLHZFRQVROH
DQGWKHLUDVVRFLDWHGREMHFWVLQFOXGLQJ RU
7KUHDG7LPHU6HPDSKRUH0XWH[ 57662EMHFW9LHZHURQWKH57;6WDUW
6KDUHGPHPRU\DQG/RDGHG57'// PHQX
8
Chapter 2: Using Software Developmen Tools
Use the RTSSrun utility to run an RTSS process in the RTSS environment, load an RTSS
DLL, and register an RTDLL.
When you use RTSSrun to run an RTSS process, it scans the RTSS process service slots for a
free slot. It copies the RTSS executable image to the target directory for the process slot and
establishes a pointer to the path. It then copies the command line to the registry and starts the
service for this RTSS process. If successful, the slot number of the new process is returned;
otherwise, RTSSrun returns -1.
RTSSrun Console
Each time you use this utility with the /b or /d switch, the current version of the .rtss or .rtdll
file is copied to a location in the %SystemRoot% directory. Thus, whenever you rebuild a
boot-time RTSS application or an RTDLL, you must rerun RTSSrun in order to access the
new version.
Usage
RTSSrun file [arguments]
Format
To run an RTSS process: RTSSrun [ /b ] <filename>[.rtss] [ arguments ]
where
9
RTX User’s Guide
RTSSrun GUI
Usage
On the VenturCom RTX SDK Start menu, choose RTSSRun.
or
On the RTSS Task Manager window, click the Start Task button.
Results
The RTSSrun window, shown below, opens.
5766UXQ:LQGRZ
See Also
RTSS Task Manager
10
Chapter 2: Using Software Developmen Tools
RTSSkill Utility
Use the RTSSkill utility to terminate a particular RTSS process or unregister an RTDLL that
is not loaded. You cannot unregister an RTDLL if any RTSS process currently has it loaded.
You can also use this utility to view a list of all RTSS processes, including registered
RTDLLs that have not been loaded, by omitting the process number or filename.
Usage
To view processes and registered RTDLLs: RTSSkill
Format
To terminate a particular process: RTSSkill [/b] [process number]
where
/b = Undoes the RTSSrun /b action. The program will not start automatically at boot time.
RTSSkill Examples
See the RTSSkill Examples in Code and File Examples in Appendix A.
11
RTX User’s Guide
RTSSview Utility
Use the RTSSview utility to view information about RTSS processes and their associated
objects, such as events, semaphores, and loaded RTDLLs.
Results
RTSSview lists each type of RTSS object, followed by its memory address in the kernel
address space and the process id. It also lists information specific to each particular object:
Process — Gives the name or type of process, followed beneath the listing by each thread
object owned by that process.
Thread — Provides the priority and state of the thread, plus the value of the flag settings
which indicate certain thread behaviors. RTX assigns a priority value to each thread in the
user's process, with values ranging from 0 to 127 (see Thread Priorities on page 35). Threads
that have negative priority numbers belong to system processes. The thread flags have the
following assignments:
9DOXH 0HDQLQJ
[ 'RQRWGHDOORFDWHPHPRU\
[ 'RQRWIUHHWKHWKUHDG
VVWDFN
[ 7KUHDGWHUPLQDWHG
[ 7KUHDGFDQQRWEHUHVXPHG
[ ,QWHUUXSWWKUHDG
[ )ORDWLQJSRLQW
Timer — Provides the clock number, the remaining time, and the timing interval.
Semaphore — Provides the count, maxcount, and the object name (if there is one).
Mutex — Lists the count, the address of the owner, and its object name (if there is one).
Shared memory — Gives the base memory address, the size of the shared memory, and the
object name.
RTDLL — Lists the count, address of the owner, and the object name.
Event — Provides the state of the event, whether the event is reset manually or not, and the
name of the event.
File — Provides the Windows NT handle for the file and the filename.
RTSSview Example
See the RTSSview Example in Code and File Examples in Appendix A.
12
Chapter 2: Using Software Developmen Tools
When you start RTSS Object Viewer, it displays an explorer that allows you to navigate
through all the active objects found in the Real-Time Subsystem (RTSS). The tree view (left
panel) displays all active RTSS objects, while the list view (right panel) displays extended
information on the items checked in the tree view.
Usage
On the VenturCom RTX SDK Start menu, choose RTSS Object Viewer.
Results
The RTSS Object Viewer window, shown below, opens.
57662EMHFW9LHZHU
13
RTX User’s Guide
Menu
The RTSS Object Viewer window contains the following menus. For additional information,
refer to the online help that is included in the application.
14
Chapter 2: Using Software Developmen Tools
RTSS Task Manager lets you view and control all active RTSS Processes and registered
RTDLLs on your system.
Usage
On the VenturCom RTX SDK Start menu, choose RTSS Task Manager.
Results
The RTSS Task Manager window, shown below, opens.
57667DVN0DQDJHU
15
RTX User’s Guide
RtxServer
The RtxServer handles RTSS output and enables the user to view the output in the RtxServer
output window and/or log the output to a file. The RtxServer is an RTX service that starts up
at boot time if RTX is set to run at boot time or at runtime when an RTSS application is run
or from the RTX control panel. Since the RtxServer is a service, it can not be started up by
double clicking on its icon.
The service can run in GUI mode or in non-GUI mode. The GUI is brought up by default
when the first printf or RtPrintf in an RTSS application is encountered. The GUI can also be
manually brought up by double clicking on the RtxServer notification icon in the Taskbar’s
Status Area. The RtxServer notification icon is visible when the RtxServer is running and
displays the state of the service and show error messages. Fatal error messages are are
flagged with the notification icon and logged to the Event Viewer.
The RtxServer allows for the storing and viewing of RTSS output through the screen and log
file. When the GUI is exited, the display buffer is purged. Because logging is independent of
the GUI, the logging will continue even if the GUI is exited. Some options for writing to the
screen are saving the screen buffer to a file, clearing the display, changing screen buffer size
and font settings of the output. You can also write to a log file, clear it, change its path, and
put a banner containing RTX version information and start time in it. You can use append
mode or clear mode for logging.
16
Chapter 2: Using Software Developmen Tools
Create a project and set options using the RTX AppWizard and then build an image (Win32
or RTSS) or build a dynamic link library (RTDLL or Win32 DLL)
Run an image
Register an RTDLL
Use the procedure that follows to create an RTX project using the RTXAppWizard in
Microsoft Visual Studio.
57;$SS:L]DUG1HZ3URMHFWV'LDORJ%R[
17
RTX User’s Guide
Platforms — Select the platform for which RTX AppWizard will build
configurations (WCE emulation mode is not supported).
4. Click OK to save the settings.
5. Complete the steps of the RTX AppWizard by selecting the appropriate options in the
RTX AppWizard dialog boxes. See the following instructions, Setting Project
Options and Setting Program Options.
57;$SS:L]DUG6WHSRI'LDORJ%R[
1. The RTX AppWizard sets the Project Settings in each configuration for compiling
and linking programs. Choose whether to build an RTX application (default) or a
DLL by clicking the labeled radio buttons.
2. RTX supports either UNICODE (default) or ASCII string types in RTSS programs.
Select which type of string format to use.
3. Some programs need support for C run-time functions. If your project needs this
support, select either the single-threaded library or the multi-threaded library. If an
RTDLL needs C run-time support, you must use the multi-threaded library. The
default is no C run-time library support.
4. If these are all the options needed, click Finish. Otherwise, click Next to open the
second dialog box, shown in the figure below.
18
Chapter 2: Using Software Developmen Tools
57;$SS:L]DUG6WHSRI'LDORJ%R[
1. The wizard can provide a basic C program framework by inserting some files into the
project. The framework consists of a C source file that contains basic C construction
calls and a C header file that contains #include and #define statements. The default is
No program framework, just Set Project Setings. Select an option by clicking on
the appropriate radio button.
2. RTX program elements can be included in the C program framework. These
programming elements are code segments that create each RTX object and
demonstrate its use. Areas in the element code that need to be customized by the user
are indicated by "TO DO" comments. You can select more than one type of
programming element for a single project. The default option is that no programming
elements are to be included.
3. Click Back to return to the first dialog in order to modify or review selections.
Otherwise, click Finish. The RTX AppWizard displays a New Project Information
confirmation box, such as the one in the figure below, indicating the choices.
19
RTX User’s Guide
1HZ3URMHFW,QIRUPDWLRQ
4. Click OK. RTX AppWizard generates the RTX workspace and project according to
the options you selected.
Running an Image
After you have built your Win32 or RTSS image, you can run it from:
n A command prompt,
n Windows NT Explorer, or
n Visual Studio (See the procedure that follows for special instructions on changing
Visual Studio settings for RTSS Debug and Release images. You do not need to
change any setting to run Win32 images.)
To run an RTSS image in Visual Studio
Use this procedure to run an RTSS image from within Visual Studio.
Modify project settings for Win32 RTSS Release and Win32 RTSS Debug
1. Select Project | Settings | Debug tab.
2. In the Program Arguments field, copy the executable into the arguments section
box and then add any other arguments.
3. Replace the text in Executable for debug session with:
rtssrun.exe
4. Click OK to save the settings.
20
Chapter 2: Using Software Developmen Tools
Registering an RTDLL
After you have built your RTDLL, you can register it using the RTSSrun utility.
Note: The RTX AppWizard utility provides an easy-to-use alternate for creating a project
workspace for the development of RTX applications and dynamic link libraries
Note: Some projects created for Microsoft Developer Studio 5.0 will have /GZ specified as a
compiler option. This option is incompatible with RTSS and Microsoft Visual Studio 6.0.
Simply remove this option from your project settings in order to migrate a Developer Studio
5.0 project to a Visual Studio 6.0 project. All the link options described in this topic for
Visual Studio 6.0 are appropriate for Developer Studio 5.0 as well.
Use the procedure that follows to direct Microsoft Visual Studio to the RTX include and
libraries files.
Use the procedures that follow to build and run a Win32 image.
21
RTX User’s Guide
3. On the Project menu, choose Settings to open the Project Settings dialog box.
4. In the Settings For box, select All Configurations.
5. On the Link tab, add this library to Object/Library Modules:
rtapi_w32.lib
6. Click OK to save the settings.
To run a Win32 image
After you have built your Win32 image, you can run it from:
A command prompt,
Windows NT Explorer, or
Visual Studio (you do not need to change any settings).
Use the procedures that follow to build and run an RTSS image.
1R&5XQ7LPH6XSSRUW'HEXJ
Versionrtapi_rtss.lib rtx_rtss.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/debug:notmapped /debugtype:both
/entry:_RtapiProcessEntry@8
6LQJOH7KUHDGHG&5XQ7LPH6XSSRUW5HOHDVH9HUVLRQ
startupCRT.obj RTXlibc.lib oldnames.lib rtapi_rtss.lib rtx_rtss.lib
w32_dll.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/RELEASE
/entry:_RtapiProcessEntryCRT@8
6LQJOH7KUHDGHG&5XQ7LPH6XSSRUW'HEXJ9HUVLRQ
startupCRT.obj RTXlibc.lib oldnames.lib rtapi_rtss.lib rtx_rtss.lib
w32_dll.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
22
Chapter 2: Using Software Developmen Tools
0XOWL7KUHDGHG&5XQ7LPH6XSSRUW5HOHDVH9HUVLRQ
startupCRT.obj RTXlibcmt.lib oldnames.lib rtapi_rtss.lib rtx_rtss.lib
w32_dll.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/RELEASE /entry:_RtapiProcessEntryCRT@8
Multi-Threaded C Run-Time Support: Debug Version
startupCRT.obj RTXlibcmt.lib oldnames.lib rtapi_rtss.lib rtx_rtss.lib
32_dll.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/debug:notmapped /debugtype:both
/entry:_RtapiProcessEntryCRT@8
6. Change the file extension in the Output File Name field from exe to rtss.
7. Click OK to save the settings.
To run an RTSS image
After you have built your RTSS image, you can run it from:
A command prompt,
Windows NT Explorer, or
Visual Studio (see the procedure that follows for instructions on changing Visual Studio
settings).
23
RTX User’s Guide
2. Select Win32 Console Application, enter a name, and then click OK.
Specify the project settings
3. On the Project menu, choose Settings to open the Project Settings dialog box.
4. In the Settings For box, select either Win32Release or Win32Debug, based on the
version you are building.
5. On the Link tab, delete all Project Options and replace them with one of the
following option sets.
Project Options on the Link Tab for an RTDLL
1R&5XQ7LPH6XSSRUW5HOHDVH9HUVLRQ
rtapi_rtss.lib rtx_rtss.lib startupDll.obj
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/RELEASE /entry:_RtapiDllEntry@8
1R&5XQ7LPH6XSSRUW'HEXJ9HUVLRQ
rtapi_rtss.lib rtx_rtss.lib startupDll.obj
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/debug:notmapped /debugtype:both
/entry:_RtapiDllEntry@8
&5XQ7LPH6XSSRUW5HOHDVH9HUVLRQ
startupDllCRT.obj RTXlibcmt.lib oldnames.lib rtapi_rtss.lib rtx_rtss.lib
w32_dll.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/RELEASE /entry:_RtapiDllEntryCRT@8
&5XQ7LPH6XSSRUW'HEXJ9HUVLRQ
startupDllCRT.obj RTXlibcmt.lib oldnames.lib rtapi_rtss.lib rtx_rtss.lib
w32_dll.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/debug:notmapped /debugtype:both
/entry:_RtapiDllEntryCRT@8
6. Change the file extension in the Output File Name field from exe to rtdll.
7. Click OK to save the settings.
To register an RTDLL
After you have built your RTDLL, you can register it using the RTSSrun utility:
RTSSrun /d <filename>.[rtdll] [/s]
For further details, see RTSSrun Utility on page 9.
24
Chapter 2: Using Software Developmen Tools
Building an RTDLL
There are two ways to build RTDLLs. You can create them through:
Appropriate compile and link options in a Microsoft Visual Studio project. To build an
RTDLL using this method, follow the applicable procedures in Using the RTX AppWizard in
Microsoft Visual Studio 6.0 on page 17 or Using Microsoft Visual Studio 6.0 on page 21.
Command line invocation of nmake using special rules. This method is illustrated below.
!include <rtx.mak>
all: thandler.dll thankler.rtdll
clean:
-del thandler.obj thandler.dll thandler.rtdll
You create an RTSS DLL with a 'main' entry point that performs any required initialization
routines. The two required files are listed below (see the RTSS DLL Code Example in Code
and File Examples in Appendix A for an example of each file).
NODEBUG =1
!include <rtx.mak>
25
RTX User’s Guide
all: dll.rtss
dll.rtss: dll.obj
lib -nodefaultlib -machine:$(CPU) -out:dll.lib -def:dll.def dll.obj
link $(rtsslflags) -out:dll.rtss dll.exp dll.obj $(rtsslibs)
del dll.exp
clean:
-del *.rtss
-del *.obj
-del *.exe
-del dll.lib
Debugging an RTX Program
Each makefile should include the master makefile, rtx.mak, which builds programs with full
debugging information in a format compatible with Microsoft’s WinDbg.exe. See the
Makefile Sample in Code and File Examples in Appendix A.
You can exclude full debugging information from your release version by using the
procedure that follows.
26
Chapter 2: Using Software Developmen Tools
5. Run NMAKE with your program’s makefile to create an .rtss file. For example, the
following line creates the file srtm.rtss: nmake -f srtm.mak
27
RTX User’s Guide
6. If the program was built on the host system, copy the .rtss file into a working
directory on the target system.
7. Copy the symbol file (.rtss) to the %SystemRoot%\symbols directory on the host
system. For example, at a command prompt, enter: >copy srtm.rtss c:\winnt\symbols
8. On the host system, ensure that the following files are in their correct locations. If
they are not present, copy them from your RTX installation disks.
28
Chapter 2: Using Software Developmen Tools
5. To close the debugging session, cancel from the target system program and then exit
from WinDbg on the host system.
Using Microsoft’s WinDbg 5.0 with RTSS
Microsoft’s WinDbg 5.0 can debug both Windows NT and Windows 2000 systems. In order
to debug using Microsoft’s WinDbg 5.0, you need to install WinDbg 5.0, i.e., the Windows
2000 debugger, on your host system. Your host and target systems can be either a Windows
2000 or Windows NT machine. The procedures for using WinDbg 5.0 with RTSS are the
same as those described above for WinDbg 4.0.
Sample shutdown program that you use to test an RTX program with shutdown handlers by
forcing a Windows NT stop
Gencrash driver which demonstrates RTSS shutdown management
Shutdown Program
Use the shutdown program to see a demonstration of RTSS shutdown handlers. You must
first build this program using the RTX makefile. This program attaches a shutdown handler to
a process and generates a continuous tone. If a Windows NT stop or system shutdown occurs
during this time, then the shutdown handler prints out a message and sleeps for 10 seconds.
The tone will then stop.
Usage
RTSSrun "c:\program files\vci\rtx\bin\samples\shutdown\shutdown"
You can view the shutdown process or stop the shutdown program and its tone without
shutting down Windows NT by using RTSSkill:
7RYLHZWKHVKXWGRZQ 5766NLOO
SURFHVV
7RNLOOWKHVKXWGRZQ 5766NLOOQ
SURFHVVQ
Optionally, you can call the gencrash driver discussed next.
Gencrash Driver
The gencrash driver provides a pop-up warning window and then bug checks (i.e., STOP 0)
the Windows NT system to demonstrate RTSS shutdown management.
29
RTX User’s Guide
Usage
net start gencrash
Caution: Please close all applications before using gencrash. A FAT file system will
generally require checking after a Windows NT stop.
2. Specify the settings on each tab (see below) and then click Apply.
About tab
Displays RTX product and version information.
Settings tab
Startup — Specifies whether RTX is started at system Boot, or Demand. If set to Demand,
RTX does not start until an RTSS process is run. If set to Boot, you cannot start or stop RTX
manually (see the Control tab section below).
Starvation Time Out — Controls the watchdog timer which monitors threads. If enabled,
RTX stops the offending thread, issues a popup exception message, and then allows Windows
NT to resume normal operation. See Starvation Management on page 70.
Free Stack on Terminate Thread — Controls whether RTSS frees the memory used for an
RTSS thread's stack when the thread is terminated via TerminateThread. When selected,
RTSS frees the memory.
HAL Timer Period — Controls the real-time HAL extension timer period. When using
RtSetTimer and RtSetTimerRelative, the value must be a multiple of the HAL extension
timer period.
Time Quantum — The value a thread will be given for its default time quantum. A value of
0 (zero) means run to completion. See RtSetThreadTimeQuantum and
RtGetThreadTimeQuantum in the RTX 5.0 Reference Guide.
RTSS Process Slots — The number of RTSS process slots that can be run on your system.
Minimum value is 10, maximum 999.
Debug tab
30
Chapter 2: Using Software Developmen Tools
Enter Kernel Debugger on RTSS Exception — Controls whether the RTX exception
handler initiates an interrupt to the debugger when a fault is raised. Caution: If selected when
no debugger is available, RTX raises a double fault.
Control tab
Provides buttons for starting and stopping RTX. These are available only when the RTX
Startup option (on the Settings tab) is set to Demand.
31
RTX User’s Guide
32
Chapter 3
Using the RTX Functionality
This chapter presents the RTX functionality along with references to real-time code examples
that demonstrate the use of RTX functions (calls) and illustrates the implementation of
various real-time programming techniques. It also highlights key areas to consider, for both
the RTSS and Win32 environments, while developing your programs.
33
RTX User’s Guide
A process comprises an address space, object handles, and one or more paths of execution
(threads). Threads are used, for example, to respond to interrupts and handle asynchronous
process-related events in thread context. RTSS processes and threads function much like their
Win32 counterparts. RTSS and Win32 processes and threads can access processes and
threads only within their own environment.
Using_Processes
Using_Threads
Thread_Priorities
Using Processes
The sections that follow describe how processes run in the RTSS and Win32 environments.
Loading it as a device driver during system boot (using the RTSSrun /b utility)
Running the RTSS executable from the command line
Starting the RTSS process from Win32 applications
The maximum number of processes that can exist concurrently in the RTSS environment is
equal to the number of RTSS process slots in the registry (the default is 10).
34
Chapter 3: Using Using the RTX Functionality
RTAPI call. RTX then may allocate resources for this process, alter its priorities, and perform
other operations related to its Win32 process status. The number of Win32 processes that can
interact with RTX is dynamic; it depends on your system’s configuration and resources.
Using Threads
The CreateThread function creates either an RTSS or a Win32 thread, depending on the
current execution environment of the process. You can specify the stack size of subsequently
created threads of that process using CreateThread. The returned handle and thread ID are
valid only in the CreateThread caller’s environment. For instance, a Win32 process cannot
manipulate the priority of an RTSS thread because the handle for the thread is valid only in
the RTSS environment. You can, however, use the RTX Inter-Process Communication (IPC)
mechanisms (such as mutex objects, semaphores, events, and shared memory) to synchronize
and communicate between Win32 and RTSS processes and threads.
Timer and Interrupt Objects
Timer and interrupt objects derive from the threads; therefore, the handles for these objects
are valid only in their own (Win32 or RTSS) environment. Similarly, these objects can be
manipulated only by processes in their own environment.
RTSS Environment
An RTSS thread is the unit of execution in the RTSS environment. A ready-to-run RTSS
thread is scheduled before all Windows NT and Windows 2000 threads. An RTSS thread runs
until it gives up the CPU. A thread gives up the CPU when it:
Thread Priorities
The sections that follow describe the priorities of threads in the RTSS and Win32
environments.
RTSS Environment
The RTSS environment has no distinct priority classes, so the threads of all RTSS processes
compete for CPU using the thread priority only. An RTSS thread runs at one of 128 distinct
priority levels. Threads execute in priority order and in "first in, first out" order within any
single priority. If a time quantum is set to 0, the thread will run to completion. If the time
quantum is set to another value, the thread will run for the specified time and then give up the
CPU to another thread with the same priority. RTSS scheduling implements a priority
inversion and deferred priority demotion mechanism to eliminate unbounded priority
35
RTX User’s Guide
inversion.
For example, RTSS mutex objects support a level-one priority promoting mechanism. If a
higher priority thread calls WFSO on a mutex object that is owned by a lower priority thread,
the priority of the mutex owner is promoted to the same priority as the higher priority thread.
An attempt to demote the priority of a mutex owner thread will be deferred until the thread
releases the mutex.
Win32 Environment
A Win32 RTX program starts execution in the real-time priority class. RTX provides a
mapping between RTSS and Win32 subsystem priorities. However, Win32 scheduling may
exhibit unbounded priority inversion.
Table 1, RTSS to Win32 Thread Priority Mapping, shows how RTSS symbolic priority
names translate to requests for a particular Windows NT or Windows 2000 priority when
RtSetThreadPriority is called by a Win32 program.
If a Win32 program calls RtGetThreadPriority, the real-time priority specified in the call to
RtSetThreadPriority returns. There are some restrictions, however. The most likely source
of confusion is when calls to RtSetThreadPriority and SetThreadPriority are mixed. The
library may not always understand the RTSS priority when a duplicated thread handle is used,
and it will return RT_PRIORITY_MIN+5 instead of RT_PRIORITY_MIN+6 through
RT_PRIORITY_MIN+126. Threads that set and get their own RTSS priorities (such as
specifying the thread with GetCurrentThread), will always get the RTSS priority that was
set.
Win32 programs should use the Rt priority calls for the Win32 thread to claim other than the
lowest RTSS scheduling priority when waiting on an RTSS synchronization object. For
instance, a Win32 thread with an RTSS priority of RT_PRIORITY_MAX will own a mutex
36
Chapter 3: Using Using the RTX Functionality
before an RTSS thread waiting for the same mutex with a priority less than
RT_PRIORITY_MAX.
Table 2, Win32 to RTSS Thread Priority Mapping, shows what callers of the Win32 "set" and
"get" thread priority calls should expect in the RTSS environment. This table describes the
inverse of the mapping shown in Table 1.
37
RTX User’s Guide
The following APIs are available to access RTX system memory allocation services:
38
Chapter 3: Using Using the RTX Functionality
See the RTX Process Memory Locking Calls Programming Example in Code and File
Examples in Appendix A. It demonstrates the use of RTX process memory locking calls.
RtLockKernel locks pageable sections of the Windows NT and Windows 2000 kernel
into physical memory.
RtUnlockKernel unlocks sections of the Windows NT and Wndows 2000 kernel
previously locked into physical memory.
Windows` NT device drivers geneˆ ally do not page; device drivers loaded at boot time
never page. In order to make drivers pageable by the system, the developer of that driver
must carefully structure the driver and manually mark the code sections that are to be paged.
Given the complexity, f˘ w drivers are structuˆ ˘ d in this way.
Locking the Windows NT or Windows 2000 kernel and processes reduces the pool of
available physical memory. This can have a detrimental effect on the performance of non-
real-time system operations. Adequate memory should be included in any system to
accommodate the desired performance of any non-real-time operations. For information on
non-paged pool size, go the Microsoft Knowledge Base or MSDN Web site.
See Also
Contiguous Memory Management
39
RTX User’s Guide
Real-time systems require a number of operating system timing services. The operating
system must be able to keep an accurate accounting of the passage of time, schedule threads
at precise times, and suspend threads for precise intervals.
The RTX clock and timer facilities provide the services necessary for threads to perform
periodic tasks that correspond with the external passage of time.
Clock services
Timer services
Sleep services
Clock Services
The RTX clocks are counters of specified intervals that measure the passage of time.
APIs
The following APIs are available to access RTX clock services:
Clock Types
The RTX clocks, available in the Win32 and RTSS environments, are:
You can set the HAL extension timer period using the RTX Settings control panel.
40
Chapter 3: Using Using the RTX Functionality
RTX and Windows NT / Windows 2000 Clock Accuracy (UP Systems Only)
The interval timer hardware (8254 based) on standard PCs cannot be programmed to run at an
even division of seconds (the fundamental interval period is 838.095344 nanoseconds). This
means that the actual timer period is always somewhat different from the specified HAL
extension timer period (the HalTimerPeriod setting in the registry).
In addition, the interval timer is used to update the clock and every interval tick adds a fixed
time increment to the clock. Windows NT and Windows 2000 maintain an internal time
increment resolution of 0.1 microseconds, which leads to an accumulation of rounding errors
and results in a small clock drift relative to the "true" time-of-day. Because of this drift,
Windows NT and Windows 2000 periodically read the CMOS time-of-day clock on the PC
and applies a drift correction.
The RTX clock also has drift, but at a different rate from the Windows NT and Windows
2000 clocks. The RTX clock is designed to run at a rate that maintains synchronization with
the specified timer period (that is, the timer is known to expire at fixed clock times). This
allows a straightforward calculation of timer expiration values and timer response latencies.
The table that follows provides the actual timer periods and associated clock drift rates for the
each of the possible timer periods.
Note: This does not apply to MP systems because they work on different processors.
General Programming Considerations: The RTX clock should not be used as a time-of-
day clock, unless the application is aware of these drift issues.
Timer Services
An RTX Timer is an implicit handling thread that receives notification from RTSS of a timer
expiration and calls the handling routine specified when the timer was created.
Timers are associated with a clock in the system—against which its expiration is measured—
when it is created. A timer begins to count down to its expiration after having been set. Once
the timer has expired and the handling routine returns, the timer can be automatically
rearmed. Timers that have their repeat interval set to zero execute their handling routine only
once and are referred to as "one-shot" timers. Timers that have their repeat interval set to a
valid value will execute their handling routine on an ongoing periodic basis and are referred
to as "repeat" or "interval" timers.
APIs
The following APIs are available to access RTX timer services:
41
RTX User’s Guide
Sleep Services
The sleep services let you suspend the current thread for a specified period of time.
APIs
The following APIs are available to access RTX sleep services:
Sleep suspends the current thread for the specified number of milliseconds.
RtSleepFt suspends the current thread for the specified period of time in 100 nanosecond
units.
Programming Considerations
RtSleepFt is not supported for use within a Win32 timer thread. The rounding policy on
timer expirations including timers, wait functions, and sleep functions is to truncate the
specified interval down to the timer tick count. If the count is zero, then the count is set to
one.
42
Chapter 3: Using Using the RTX Functionality
Inter-Process Communication
Object Names
Named objects provide an easy way for processes to share object handles. The name specified
by the creating process is limited to RTX_MAX_PATH characters, and can include any
character except the backslash path-separator character (\). Once a process has created a
named event, mutex, semaphore, or shared memory object, other processes can use the name
to call the appropriate function (RtOpenEvent, RtOpenMutex, RtOpenSemaphore, or
RtOpenSharedMemory) to open a handle to the object. Name comparison is case-sensitive.
The names of event, mutex, semaphore, and shared-memory objects share the same name
space. If you specify a name that is in use by an object of another type when creating an
object, the function succeeds, but GetLastError returns ERROR_ALREADY_EXISTS.
Therefore, when creating named objects, use unique names and be sure to check function
return values for duplicate-name errors.
For example, if the name specified in a call to RtCreateMutex matches the name of an
existing mutex object, the function returns a handle of the existing object. In this case, the call
to RtCreateMutex is equivalent to a call to RtOpenMutex. Having multiple processes use
RtCreateMutex for the same mutex is therefore equivalent to having one process that calls
RtCreateMutex while the other processes call RtOpenMutex, except that it eliminates the
need to ensure that the creating process is started first. When using this technique for mutex
objects, however, none of the calling processes should request immediate ownership of the
mutex. If multiple processes do request immediate ownership, it can be difficult to predict
which process actually gets the initial ownership.
Shared Memory
The RTSS shared memory object is a region of non-paged physical memory that can be
mapped into the virtual address space of a process. When a shared memory object has a
name, additional processes may map the region of memory. A shared memory object is
accessed with both a handle and a virtual address. In order for a process to completely end its
access to a shared memory object it must close the handle. When all processes end their
access to a shared memory object, the following occur:
Using RtCreateSharedMemory
In order for several processes to use a shared memory object, the object must be first created
43
RTX User’s Guide
using RtCreateSharedMemory. Other processes can then use the shared memory object’s
given name to map the shared memory object. RtCreateSharedMemory returns a handle
and sets a location to the base address of the shared memory.
Using RtOpenSharedMemory
RtOpenSharedMemory maps an already created shared memory object. After the shared
memory object has been created by a process, additional processes may map the shared
memory into their address spaces by calling RtOpenSharedMemory.
RtOpenSharedMemory will fail if the named shared memory object does not exist.
RtOpenSharedMemory returns a handle to the shared memory object and sets a location to
the base address of the shared memory. When a process is finished with the shared memory it
should close the handle to the shared memory object.
Environments
The RTSS shared memory object is always maintained in the RTSS environment. However,
Win32 processes may create and open RTSS shared memory objects.
The RTSS shared memory object is its own named object. The RtCreateSharedMemory
and RtOpenSharedMemory calls implicitly map the shared memory; this eliminates the
explicit Win32 call to the MapViewOfFile call. When the shared memory object is created,
RTSS backs the shared memory object with non-paged memory.
Semaphores
The RTSS semaphore object is a synchronization object that maintains a count between zero
and a specified maximum value. The count is decreased by one each time a thread completes
a wait for the semaphore object; the count is increased by a variable amount at the semaphore
release. When the count reaches zero, the semaphore object’s state is no longer signaled and
no more threads can complete a wait on the semaphore object until some thread increases the
count.
Like usual semaphore objects, the RTSS semaphore objects are used for resource counting.
They give a thread the ability to query the number of resources available; if one or more
resources are available, the count of available resources is decreased. RTSS semaphores
perform this test-and-set operation atomically; that is, when you request a resource from an
RTSS semaphore, the operating system checks whether the resource is available and
decrements the count of available resources without letting another thread interfere. Only
after the resource count has been decreased does the system allow another thread to request a
resource.
Because several threads can affect an RTSS semaphore’s resource count, an RTSS
semaphore, unlike an RTSS mutex, cannot be owned by a thread. This means that waiting for
semaphore objects:
44
Chapter 3: Using Using the RTX Functionality
However, unlike the usual semaphore objects, the RTSS semaphore objects support the
waiting priority. That is, when there are several threads with the different priority waiting for
an RTSS semaphore object, the system guarantees that the order of thread obtaining the
semaphore object is the order of thread priority when the RTSS semaphore object is signaled.
Using RtCreateSemaphore
The first and most common way is for one thread in each process to call
RtCreateSemaphore, passing the identical string for the parameter of RTSS semaphore
name. The first thread to call RtCreateSemaphore will cause the system to create the RTSS
semaphore object. As additional threads call RtCreateSemaphore, the system determines
that an RTSS semaphore object with the specified name already exists; as a result, it does not
create a new RTSS semaphore object but returns a process-relative handle identifying the
existing RTSS semaphore object.
Using RtOpenSemaphore
Another method for obtaining the handle of an RTSS semaphore object involves a call to
RtOpenSemaphore. The dwDesiredAccess parameter is ignored. The lpName parameter is
the zero-terminated string name of the RTSS semaphore object. When the call to
RtOpenSemaphore is made, the system scans all existing RTSS semaphore objects to see if
any of them have the same name indicated by lpName. If the system finds an RTSS
semaphore object with the specified name, it creates a process-relative handle identifying the
RTSS semaphore object and returns the handle to the calling thread. Any thread in the calling
process can now use this handle in any function that accepts an RTSS semaphore handle. If
an RTSS semaphore object with the specified name cannot be found, null is returned.
Environments
The RTSS semaphore object is always maintained in the RTSS environment. However,
Win32 programs may create, open, release, and wait for RTSS semaphores. This allows
cooperation between RTSS and Win32 processes. The semaphore name space is separate
from the Win32 semaphore name space.
45
RTX User’s Guide
Event Objects
An event object is a synchronization object whose state can be explicitly set to signaled by
using RtSetEvent or RtPulseEvent. The two types of event objects are:
Manual-reset event — An event object whose state remains signaled until it is explicitly
reset to nonsignaled by RtResetEvent. While it is signaled, any number of waiting
threads, or threads that subsequently specify the same event object in a call to
RtWaitForSingleObject, can be released.
Auto-reset event — An event object whose state remains signaled until a single waiting
thread is released, at which time the system automatically sets the state to nonsignaled. If
no threads are waiting, the event object's state remains signaled.
An event object is useful in sending a signal to a thread, indicating that a particular event has
occurred.
Using RtCreateEvent
A thread uses the RtCreateEvent function to create an event object. The creating thread
specifies the initial state of the object and whether it is a manual-reset or auto-reset event
object. The creating thread can also specify a name for the event object. Threads in other
processes can open a handle of an existing event object by specifying its name in a call to
RtOpenEvent. For additional information about names for objects, see Object Names on
page 43.
Using RtPulseEvent
A thread can use RtPulseEvent to set the state of an event object to signaled and then reset it
to nonsignaled after releasing the appropriate number of waiting threads. For a manual-reset
event object, all waiting threads are released. For an auto-reset event object, the function
releases only a single waiting thread, even if multiple threads are waiting. If no threads are
waiting, RtPulseEvent simply sets the state of the event object to nonsignaled and returns.
Mutex Objects
The RTSS mutex object is a synchronization object whose state is signaled when it is not
owned by any thread and not signaled when the mutex is owned by a thread. The mutex
object arbitrates exclusive access to a shared resource.
Ownership
A thread owns a mutex between the exit from a wait function and the call to
RtReleaseMutex. No other thread can own the mutex between these calls. If another thread
calls a wait function while the mutex is owned (not signaled), the wait function will not exit
until the mutex owner releases the mutex. When an owning thread terminates, the mutex is
signaled and abandoned. The waiter learns of an abandoned mutex by examining the wait
function's return value. A thread that acquires an abandoned mutex should expect an
inconsistent shared resource.
If more than one thread is waiting for ownership, the thread with the highest priority gets
ownership and is the first thread to return from the wait function. In cases where threads with
46
Chapter 3: Using Using the RTX Functionality
the same priority are waiting to be owners, the earliest request goes first.
A thread can determine whether RtCreateMutex actually created a new RTSS mutex object
by calling GetLastError right after the call to RtCreateMutex. If GetLastError reports
ERROR_ALREADY_EXISTS, a new RTSS mutex object was not created. If you are
expecting to share this RTSS mutex with other processes, you can ignore this last step.
Using RtOpenMutex
Another method for obtaining the handle of an RTSS mutex involves a call to the
RtOpenMutex. The dwDesiredAccess parameter is ignored. The lpName parameter is the
zero-terminated string name of the RTSS mutex object. When the call to RtOpenMutex is
made, the system scans all existing RTSS mutex objects to see if any of them have the same
name indicated by lpName. If the system finds an RTSS mutex object with the specified
name, it creates a process-relative handle identifying the RTSS mutex and returns the handle
to the calling thread. Any thread in the calling process can now use this handle in any
function that accepts an RTSS mutex handle. If an RTSS mutex with the specified name
cannot be found, null is returned.
Environments
The RTSS mutex is always maintained in the RTSS environment. However, Win32 processes
may create, open, and own RTSS mutex objects. The RTSS mutex name space is separate
from the Win32 mutex name space.
47
RTX User’s Guide
Device Management
Interrupts
Real-time systems frequently are required to respond to external devices. In doing so, it is
often desirable to have a real-time process respond directly to the interrupts generated by
these devices. RTX allows a process to directly interface with a device without having to
write a Windows driver.
Interrupt Management
The RTX interrupt management routines provide interfaces that enable an application to
satisfy interrupt requests from devices attached to the computer. These interfaces let you
attach a handling routine to an interrupt, much the same way that the RTX timer routines
allow you to associate a handling routine with a given timer expiration.
There are twelve interrupt levels availale to RTSS. The RtAttachInterruptVector call maps
RTSS priorities into these twelve interrupt levels. These are, in increasing hardware priority:
For example, interrupts that require the highest hardware priority, the user should assign an
RTSS priority of 127 when the interrupt is attached. For hardware interrupts of lesser priority,
the user may choose from a range of 118-126. For the lowest level priorities, use 117 or less.
APIs
The following APIs are available to manage RTX interrupt services:
48
Chapter 3: Using Using the RTX Functionality
processor level.
RtEnableInterrupts enables all interrupts disabled by RtDisableInterrupts.
Using RtAttachInterruptVector
To attach an interrupt vector, use RtAttachInterruptVector. To use this call, you must supply
bus-specific parameters. For buses with automatic configurations, such as PCI you can obtain
the parameter information by calling RtGetBusDataByOffset. For more information, look in
the Bus I/O section of this manual.
Using RtAttachInterruptVectorEx
Use RtAttachInterruptVectorEx to share interrupt vectors. This function lets you associate a
handling routine with a hardware interrupt on one of the supported buses on the computer.
RTSS threads can share a given interrupt vector, and Win32 threads can do the same.
However, an RTSS thread and a Win32 thread cannot share the same interrupt. To determine
what interrupts Windows NT is using, use Windows NT Diagnostics. To determine what
interrupts Windows 2000 is using, look in Device Manager. You should be aware that sharing
of interrupts increases the interrupt latency for the lower priority interrupt service threads;
this occurs because the higher priority interrupt service thread must run and determine that a
shared interrupt is to be passed along to another thread. For situation where very low interrupt
latency is necessary, the extra overhead of interrupt sharing could cause problems. Devices
that require very short interrupt latency should be assigned to unique interrupt lines. If your
device has hard real-time interrupt latency requirements, you probably do not want it to share
an interrupt line with another device.
49
RTX User’s Guide
Level-triggered interrupts cannot be used by Win32 processes because the interrupt will be
reasserted when RTSS tries to return to Windows NT to allow the Win32 service routine to
run. For level-triggered interrupts to operate correctly, the interrupt service routine must clear
the interrupt condition before it unmasks the interrupt line. This limitation is found on
uniprocessor systems only.
Using RtReleaseInterruptVector
Unlike driver unloading, an RTX application can exit and leave a device enabled, with the
device attempting to deliver interrupts to the handling thread. Although the RTX library
usually cleans up after an application exits, there are times when the exiting application can
bypass the library’s attempt to detect the exit. To avoid such a condition, use
RtReleaseInterruptVector; it will release a previously attached interrupt.
Note: Just as in an interrupt service routine in a device driver, a real-time application must be
able to acknowledge an interrupt and control the device that generated it. For further details
on communicating with devices, see the Port I/O and Physical Memory Mapping sections
that follow.
Port IO
Real-time systems require the ability to control, read, and write data to hardware devices. The
RTX port I/O programming interfaces allow data movement in the I/O space of a processor
by a user process without the need to switch to a kernel-mode code. This functionality
eliminates the need for creating a device driver for every device that must be accessed.
Additionally, it eliminates the latencies associated with requesting device driver services for
every device access.
Port I/O provides an alternate method of communicating directly with hardware. The I/O
address space is a feature found on Intel processors where each address represents an 8-bit
"port." Each port typically corresponds to an 8-bit control register on a hardware device.
While sequential addresses can represent the bytes in a multi-byte port, hardware designers
usually employ designs that have a single-byte port, and multi-byte values are entered as
sequential single-byte writes to the port address. For details about a particular device, you
should consult its programming reference documentation.
Access to port I/O devices must be enabled prior to attempting any data transfers. This is
accomplished with the RtEnablePortIo function by passing in the port I/O address range that
will be accessed. Subsequent to enabling access, the RtWrite* and RtRead* functions,
discussed below, may be used to transfer data to and from the enabled port I/O space.
RtEnablePortIo enables the direct Port I/O access for the specified range of I/O
50
Chapter 3: Using Using the RTX Functionality
addresses.
RtDisablePortIo disables the direct Port I/O access for the specified range of I/O
addresses.
Port I/O Data Transfer APIs (described in the section that follows)
Programming Example
See Interrupt Managemet and Port I/O Calls Programming Example in Code and File
Examples in Appendix A. It demonstrates the use of RTX interrupt management and port I/O
calls.
The existence of an I/O space is dependent on the processor architecture. Several Windows
NT and Windows 2000-supported architectures are based on processors that do not have a
separate I/O space. Rather, their ports are mapped into memory addresses. These
architectures can use the memory mapping function to enable access to physical memory on
controllers and other hardware devices.
Physical memory mapping can also be used to give processes access to physical memory
ranges in the CPU’s address space.
The RTX physical memory map interface maps a section of physical memory into an
application’s virtual address space. This enables the application to access a region of physical
memory directly, as if it were a buffer in the application. This interface is useful for
applications that need to access device memory or registers that are mapped into the physical
address space of the CPU.
APIs
The following APIs are available to access RTX memory mapping services:
51
RTX User’s Guide
RtMapMemory maps a physical memory address range into the process’ virtual address
space.
RtUnmapMemory removes a previously mapped physical memory object from the
process’ virtual address space.
Certain devices, particularly devices that perform DMA, require that their buffers reside in
physically contiguous memory in the CPU’s address space. In addition, these devices must
access the memory buffers using the actual physical address, rather than by the virtual
address that is used by a Win32 or an RTSS process.
APIs
The following APIs are available to access RTX contiguous memory allocation services:
Programming Considerations
Contiguous memory is always allocated from the non-paged pool of memory maintained by
Windows NT and Windows 2000. This pool of memory is relatively small and is rapidly
fragmented by the allocations of other drivers and subsystems in Windows NT and Windows
2000 shortly after system boot. To avoid failure of large allocations, you should minimize
their use and/or ensure that they are accomplished shortly after system boot.
52
Chapter 3: Using Using the RTX Functionality
Bus IO
File IO
File IO
RTX allows two options for file input and output (I/O). You can write to the supported file
I/O functions in the Win32 API or to the supported file I/O functions in the C run-time
library. The API delivers low-overhead, fast access to Windows NT and Windows 2000 file
I/O capabilities using standard APIs. A subset of CreateFile flags are supported with file I/O.
Please refer to the RTX 5.0 Reference Guide for more details. File I/O does not include
support for asynchronous file operations.
Because RTSS applications have no current-directory notion, RTSS file I/O requests must use
fully qualified path names, such as:
53
RTX User’s Guide
RTSS file I/O calls are made from the Windows NT or the Windows 2000 kernel
environment: RTX actually translates Win32 names such as c:\MyFile.txt and \\.\MyDevice0
to NT internal names \??\c:\MyFile.txt and \Device\MyDevice0, respectively. You can,
therefore, use Windows NT and Windows 2000 internal names from your RTSS applications,
although such calls fail in Win32. Using an internal Windows NT or Windows 2000 name
lets you access a device object for which Win32 has no symbolic link, such as \Device\beep
or \Device\Harddisk0\Partition1\testfile.txt.
With boot-time file I/O, you may only use paths such as
\\Device\\Harddisk0\\Partition1\foo.txt because paths such as \\??\\C:\\foo.txt and C:\\foo.txt
are not supported.
54
Chapter 4
Developing an Application
This chapter discusses the two types of real-time dynamic link libraries (RTSS DLL and
RTDLL), and provides references to code examples for each type. It also explains how to use
the C run-time library functions and floating point; provides guidance on writing device
drivers; explains exception handling in the RTSS and Win32 environments; and provides
techniques for managing starvation conditions.
55
RTX User’s Guide
Variables
56
Chapter 4: Developing an Application
n Descriptions of the two types of real-time DLLs (RTSS DLL and RTDLL)
n C Run-Time Libraries: Programming Considerations for DLLs
n References to RTSS DLL and RTDLL code examples
For instructions on creating DLLs, see Creating RTX Dynamic Link Libraries on page 25.
There are two types of real-time DLLs (RTSS DLL and RTDLL) that you can use to share
code between processes or make run-time determinations of what libraries need to be loaded
for a given hardware configuration.
RTSS DLLs — An RTSS DLL is actually not a DLL but an RTSS process that exports
functions for use by other RTSS processes. It shares a common address space with RTSS
processes. They can be loaded either at boot time or through a call to Windows NT from
within a C/C++ program (e.g., System("RTSSrun LibName.rtss"). Although similar to
RTSS applications, their entry point is Main, and they are compiled and linked to generate
a library of exported functions that can be linked with RTSS applications. Typically, Main
for an RTSS DLL will simply issue a SuspendThread call. RTSS DLLs allow you to
reference exported functions by name in a calling program, but are cumbersome to load
because they are neither loaded nor unloaded automatically when RTSS applications using
them start running.
RTDLLs — RTDLLs are RTSS objects that can be dynamically loaded and unloaded
using the LoadLibrary and FreeLibrary calls. They are automatically unloaded from
memory when the last RTSS process referencing them terminates. Because RTDLLs do
not require linking to an explicit export library, they provide a convenient, flexible run-
time accommodation of changes to RTDLLs or applications. However, with RTDLLs the
address of each exported function used by a calling process must be explicitly obtained
through a call to GetProcAddress. Additionally, because RTDLLs are not RTX
processes, it is not reliable to use C run-time functions within an RTDLL loaded by more
than one RTX process simultaneously. For further details about the relationship between C
run-time libraries and RTDLLs see C Run-Time Libraries:Programming Considerations
for DLLs below.
The choice of RTSS DLLs or RTDLLs for a particular application depends on the specific
functional requirements of the application. The variation of hardware run-time
configurations that an application must accommodate may also affect your choice.
Programming examples for RTSS DLLs and RTDLLs are provided in the sections that
follow.
C Run-Time Libraries: Programming Considerations for DLLs
This section discusses considerations that you should keep in mind when designing an RTSS
DLL or RTDLL that will be linked with the RTX-supplied C run-time libraries, RTXlibc.lib
or RTXlibcmt.lib (see Using the C Run-time Library Functions on page 59).
The Microsoft C run-time initialization code assumes that global variables have process
57
RTX User’s Guide
scope, i.e., a separate copy of all C run-time global variables and structures exists for each
process using the libraries. This is not true for RTSS DLLs or RTDLLs.
RTSS DLLs
Because RTSS DLLs are RTSS processes which have been linked to generate an export
library, and because they never get unloaded from memory except at shutdown, global
structures created at initialization will persist during the entire life of any process depending
on the RTSS DLL.
Note: A few C run-time routines are unsafe within an RTSS DLL used by multiple processes.
The routines that you should not use are: fprintf(), getenv(), perror(), printf(), vsprintf(), and
wprintf(). Because these routines rely on per-process global variables, they can yield
undefined behavior that may require system reboot. Note that in this context "used by
multiple processes" means used by more than one process at any time between system startup
and shutdown, including the same RTSS image, running twice in succession with the same
RTSS PID.
RTDLLs
RTDLLs are not RTSS processes; they are RTSS objects which can be dynamically loaded
and unloaded. Because other objects created by an RTDLL are always owned by the calling
process, they are destroyed when that process terminates. Among other things, the C run-time
initialization creates heaps used for memory allocation. These heaps persist only until the
process that initially loaded the RTDLL terminates. Since the behavior of C run-time
functions is reliable only in an RTDLL loaded by multiple processes given strict limitations
on the LoadLibrary, FreeLibrary sequence, it is recommended that you never register
RTDLLs linked with the C run-time libraries with the /s switch of RTSSrun.
58
Chapter 4: Developing an Application
For a list of available functions, see the C Run-Time API List in the RTX 5.0 Reference Guide.
If you build RTSS programs using NMAKE, you must add the following line to your
makefile before the line that includes rtx.mak:
RTSS_CRT = 1
The preceding line enables Floating-Point Unit (FPU) support, including the floating-point
math routines and printf with floating-point support.
If you are using Microsoft Visual Studio, follow the procedure to enable C run-time support
as described in Using Microsoft Visual Studio 6.0.
You do not need to follow any special procedures to run an RTSS program that uses floating-
point. The program can simply issue Floating-Point Unit (FPU) instructions and call floating-
point math routines as done by a standard Win32 program.
Devices can be accessed and controlled through three types of functions: Port I/O, Bus I/O,
and mapped memory. Additionally, drivers can respond to devices by providing interrupt
handlers through RtAttachInterruptVector. Unlike Windows NT, where access to drivers
59
RTX User’s Guide
occurs via calls to DeviceIoControl, RTSS drivers can be structured as static libraries, RTSS
DLLs, or RTDLLs. In each case, the driver writer can supply library functions directly to the
RTSS application writer without the need to employ the DeviceIoControl interface.
For many applications, it is not necessary to write a hard real-time (RTSS) device driver for
standard desktop devices. When hard real-time performance is not required for device access,
as is often the case with video, sound, and network devices, the recommended approach is to
develop a Win32 application that communicates with RTSS applications through IPC
mechanisms, and communicates with necessary devices through standard Windows NT
device drivers.
C++_Support
Structured_Exception_Handling
C++ Support
RTX supports the Visual C++ language, with some restrictions discussed in the note below.
RTSS should support any C++ features usable in a Win32 C++ RTX API console application,
including new/delete operators and exception handling.
Note: RTX does not claim support for all C++ libraries. Support is limited to libraries that
depend upon the set of Win32 functions supported in the RTSS environment. You can test
specific libraries to determine whether they are supported by RTX.
RTSS supports Structured Exception Handling and C++ exceptions, as described by the
Win32 Platform SDK, including:
EXCEPTION_DATATYPE_MISALIGNMENT
EXCEPTION_BREAKPOINT
EXCEPTION_ACCESS_VIOLATION
EXCEPTION_ILLEGAL_INSTRUCTION
EXCEPTION_FLT_DENORMAL_OPERAND
60
Chapter 4: Developing an Application
EXCEPTION_FLT_DIVIDE_BY_ZERO
EXCEPTION_FLT_INEXACT_RESULT
EXCEPTION_FLT_INVALID_OPERATION
EXCEPTION_FLT_OVERFLOW
EXCEPTION_FLT_UNDERFLOW
EXCEPTION_INT_DIVIDE_BY_ZERO
Using SEH
To use SEH in an RTSS application, an application must be linked with a Win32 static-
linkage run-time support library (such as RTXlibc.lib or RTXlibcmt.lib which contain run-
time support for the SEH frame-based exception handlers), or with static-linkage run-time
support C++ libraries.
UnhandledExceptionFilter
Win32 UnhandledExceptionFilter semantics provide the option to disable the exception-
related dialog box pop-up via SetErrorMode with the SEM_NOGPFAULTERRORBOX flag.
On an exception, RTSS always displays a pop-up saying that the application has been frozen
or unloaded.
RTSS acts differently; it freezes (or unloads, if so configured) all threads of a process
whenever any of them gets an exception, and produces an informational pop-up. This
behavior is safer and more intuitive in the RTSS context. You can, however, emulate the
Win32 behavior by using per-thread unhandled exception filter functions.
61
RTX User’s Guide
Debugging
For debugging, see the Debug tab in the RTX Properties control panel.
Exception handling is a powerful mechanism with often subtle semantics. It is quite easy to
write code that causes infinite re-assertion of an exception. For example, if a filter expression
always faults, or always dismisses a hardware exception which gets re-executed, the process
continues generating exceptions until it overflows the stack. Miscasting the handler argument
to SetUnhandledException filter may be equally fatal.
Because stack faults in RTSS cause system shutdown, you must be careful when writing
exception handlers. Testing your application in Win32 becomes more important than ever to
avoid stack overflows in RTSS.
Important: All discussions in this chapter ("System Exception Handling") assume that RTSS
applications do not use Structured Exception Handling (SEH). For information on SEH, see
C++ and Structured Exception Handling.
RTX Handler
RTX provides a handler to process exceptions that occur in an RTSS process. (If an exception
occurs in a native Windows NT or Windows 2000 application, the Windows operating
system handles it.) When the RTX handler encounters an error, it initiates one of the
following actions:
62
Chapter 4: Developing an Application
Note: If an exception occurs within an ISR (such as an RTX harware interrupt or RTX timer
interrupt), RTX immediately initiates an RTX Green Screen stop message. If a fault occurs
during exception processing, the RTX handler immediately initiates a double fault and Green
Screen stop message.
Tables of Exceptions
RTX exceptions
Intel exceptions
[([FHSWLRQ :LQ0DSSLQJ
(;&(37,21B',9,'('B%<B=(52 (;&(37,21B,17B',9,'(B%<B=(52
(;&(37,21B)/7B',9,'(B%<B=(52
(;&(37,21B13;B29(5581 (;&(37,21B)/7B,19$/,'B23(5$7,21
(;&(37,21B13;B(5525 (;&(37,21B)/7B'(1250$/B23(5$1'
(;&(37,21B)/7B',9,'(B%<B=(52
(;&(37,21B)/7B29(5)/2:
(;&(37,21B)/7B81'(5)/2:
(;&(37,21B)/7B,1(;$&7B5(68/7
(;&(37,21B)/7B,19$/,'B23(5$7,21
(;&(37,21B,19$/,'B23&2'( (;&(37,21B,//(*$/B,16758&7,21
(;&(37,21B*3B)$8/7 (;&(37,21B$&&(66B9,2/$7,21
(;&(37,21B3$*(B)$8/7
63
RTX User’s Guide
[([FHSWLRQ :LQ0DSSLQJ
(;&(37,21B%281'B&+(&.
(;&(37,21B6(*0(17B127B35(6(17
(;&(37,21B'(%8* (;&(37,21B%5($.32,17
(;&(37,21B$/,*10(17B&+(&. (;&(37,21B'$7$7<3(B0,6$/,*10(17
For most exceptions, the RTX handler performs the following tasks:
Freezes or terminates the errant RTSS process, depending on the state of the
ExceptionDisposition flag
Alerts the user with a popup window
Writes one or more associated entries in the event log
Alert User
The RTX handler alerts the user of an exception with a popup message window. For example,
if the handler terminates processing, RTX might display the following window:
In this example, a memory protection fault has been detected. The message identifies the
application instruction address and the process and thread identification values. The
disposition of the thread is unloaded.
If the RTX handler freezes processing, RTX might display the following window:
In this example, a memory protection fault has been detected. The message identifies the
application instruction address and the process and thread identification values. The
disposition of the thread is frozen. The user is directed to manually terminate the process
using RTSSkill.
64
Chapter 4: Developing an Application
The first 10 entres in the message dump are` specific to the error logging call and are
ignored. The 3 dwords of RTSS fault data are:
Stop messages, presented via an RTX Green Screen or a Windows NT Blue Screen, quickly
provide you with key information about a system crash. A stop message often gives you
sufficient data to determine why a system has crashed and what actions to take to resolve the
problem.
To enable (view) stop messages, you must disable the Windows NT Automatically Reboot
option as shown in the procedure that follows.
65
RTX User’s Guide
Note: Under some conditions, the kernel displays only the top line of the stop message
because the services required to display the rest of the information may not be available.
where
#E = Actual error code.
#1 - #4 = Additional parameters relating to the error.
Text = Best effort interpretation of the error.
66
Chapter 4: Developing an Application
Section 4 - Communication
The Communication section of the Blue Screen provides confirmation of the communication
parameters used by a kernel debugger (if present on the target computer). The following
message then appears:
This message implies that if the computer is restarted, the stop condition may not happen
again. If this message reappears after you restart, contact your system administrator or
technical support group.
67
RTX User’s Guide
For Windows 2000 the traditional "Blue Screen" has been eliminated. The user can still
obtain the same type of information by using the "minidump" or small memory dump option.
All that is needed is a small 2mb paging file on the system drive and configuring the Startup
and Recovery Options for minidump on the System properties screen.
The process information and kernel context (EPROCESS) for the process that
stopped
The process information and kernel context (ETHREAD) for the thread that stopped
68
Chapter 4: Developing an Application
When a non-recoverable exception occurs within an RTSS process, the RTX exception
handler initiates a Green Screen. The RTX Green Screen contains four sections of data.
Sections 1 and 2 are RTX specific. Sections 3 and 4 are similar to those sections of the
Windows NT Blue Screen.
where
#E = Actual error code. Error code numbers and their associated text are:
1. UNHANDLED_EXCEPTION
2. THREAD_STACK_OVERFLOW
3. LOCK_HIERARCHY_VIOLATION
4. LOCK_OWNER_VIOLATION
5. PROXY_DISPATCHER_SANITY
6. PROXY_THREAD_SANITY
7. SERVER1_SANITY
8. EXCEPTION_IN_ISR
9. KERNEL_MODE_EXCEPTION
10. SYSTEM_PROCESS_EXCEPTION
11. NMI_EXCEPTION
12. STACK_OVERFLOW
#1 = Exception code taken from Exception Table.
#2 = Contents of Instruction Pointer Register at the time exception was raised. If the #2
value is outside the address range of the process, the most likely cause of the
exception is a corrupt stack with an illegal value restored to the IP.
#3 = RTSS Thread identification.
#4 = RTSS Process identification.
69
RTX User’s Guide
where
#E = 0 (zero). Indicates that an RTSS process caused the exception. Other codes are
reserved for internal RTX errors.
#1 = Hardware exception vector number.
#2 = Contents of Instruction Pointer Register at time exception was raised.
#3 = Stack pointer at time of fault.
#4 = Base address of the exception frame. For the majority of exceptions, an exception
stack frame containing the system state information is stored on the current stack.
In the case of a double fault, this address will be the base address of the Task State
Segment. For more information, see Volume 3: Architecture and Programming of
the Pentium® Processor Family Developer's Manual.
Text = The text interpretation attempts to match one of the entries in the stop message to
a loaded image base address to determine approximately where the fault was
raised.
Starvation Management
This topic discusses the RTX watchdog timer and programming techniques that you can use
to manage starvation conditions.
Watchdog Timer
When a single RTSS thread becomes CPU bound, it is often the result of a program logic
error (which occurs most frequently during the development phase). When a thread becomes
CPU bound on a single-processor system, Windows NT and Windows 2000 both freeze. On a
multi-processor system, the both Windows operating systems continue to run but cannot
terminate the CPU-bound thread because the lower priority Service Request Interrupt (SRI)
manager threads will not run.
Watchdog Management
For this type of condition, you can use the RTX starvation management watchdog timer. This
timer checks on every timer interrupt (which is normally always enabled) for continuous
running of the same thread and/or RTSS threads to the exclusion of Windows NT (the idle
thread). When the watchdog timer expires, an exception is raised; a popup message notifies
you of the error; and then Windows NT and Windows 2000 resume normal operation. The
offending process is either stopped or terminated, based on the Process Exception Disposition
setting in the RTX Settings control panel. You can use the RTSSkill utility to unload the
stopped process.
70
Chapter 4: Developing an Application
Values are:
0 = Disable the watchdog timer.
N milliseconds = Enable the watchdog timer and set time period (a typical period is tens
of seconds).
Programming Techniques/Considerations
An application may behave correctly, yet it may have one or more threads that become CPU
bound for periods of time. In this case, you could periodically give small amounts of time to
Windows NT during these periods. This might be needed, for example, to allow Windows NT
and Windows 2000 to empty the RS232 UART silo, acknowledge network requests, perform
disk I/O, move the mouse pointer, or display something on the GUI. Since the desired
behavior can be quite complex, an RTX-defined policy of giving Windows NT time slices
may be unnecessary or may interfere with RTSS deterministic behavior.
You can easily manage this type of situation by creating a timer handler that periodically
suspends the CPU bound thread(s) for short periods of time. Take, for example, an
application that runs a thread for 100 milliseconds every second. You could suspend the
thread for .5 milliseconds every 10 milliseconds during the 100 milliseconds that it runs. You
can create an algorithm, as simple or complex as desired, to support starvation management.
Typically, a five percent duty cycle is a reasonable initial setting. You can then use the
algorithm to measure and adjust your starvation management.
The RTX sample program, starve.c, demonstrates the use of the timer approach. It is located
in:
c:\program files\vci\rtx\bin\samples\starvation
Another approach to starvation management is to simply include calls to Sleep, which should
give small amounts of time to Windows NT and Windows 2000 within your application.
RTX Power Management for Windows 2000
If there are RTSS processes running on UP system, system power state transitions from
working state (S0) to any sleeping state (S1-S5) will be blocked by RTX Power Management.
You will see a popup message box telling this fact. However, if there are no RTSS processes
running on UP system, such transitions are not blocked. On MP system, system power state
transitions from working state (S0) to any sleeping state (S1-S5) will be blocked if RTSS is
loaded on one processor.
71
RTX User’s Guide
72
Chapter 5
Performance Overview
Real-time systems have exacting performance requirements, including deterministic response
times for key operations. This chapter covers the sources of interrupt latency, platform-
specific timing factors, and measurement techniques an RTX developer can use to ensure
good response times.
73
RTX User’s Guide
Software causes
Hardware causes
Management of interrupt latencies
Software Causes
Hardware Causes
Bus "hijacking" by peripheral devices. For example, a video card may stall the CPU's attempt
to read the card's I/O space register.
Burst DMA by SCSI controllers.
Cache dirtying by Windows NT and applications.
Power Management features. Some systems, particularly portables, go to a low-power
state after a time-out, and "wake up" with a delay that you can barely notice, but which is
intolerable to a real-time application.
RTX eliminates PIC-level interrupt disabling by isolating interrupts (through the RTX HAL
extension). Windows NT and Windows 2000 and their drivers cannot disable RTSS
interrupts. In addition, all Windows NT and Windows 2000 interrupts are masked when
RTSS is running.
74
Chapter 5: Performance Overview
SRTM is an RTAPI timer latency measurement tool that measures timer latency observed by
an application. Each of the two versions of SRTM, Win32 and RTSS, measures its own
environment. An SRTM histogram often shows a characteristic double peak profile: the first
peak is a near-) and Using RTX Demo (Graphical version of SRTM). See also KSRTM versus
SRTM. best case, the second is the dirty-cache case. The diagram occasionally shows
additional "humps" from processor-level interrupt masking. Among the samples is a
graphical version of SRTM, RTX Demo, which measures results for both RTSS and Win32.
For further details, see Using SRTM (System Response Time Measurement) on page 77.
KSRTM is a driver and a Win32 utility that measures HAL-level timer latency. Short code
paths make it less sensitive to cache jitter than SRTM. It can determine which Windows NT
component or device driver is causing the greatest latency event for a real-time application.
For further details, see Using KSRTM (Kernel System Response Time Measurement) on page
76. See also KSRTM versus SRTM below.
LTP finds misbehaving peripheral devices. This application loops, reading the RTX
CLOCK_FASTEST, detecting latency events caused by peripheral activities (such as burst
DMA), and reporting instances of latencies exceeding a certain threshold. For further details,
see Using LTP (Latency Test Program) on page 82.
The Timer Latency Display tool performs timing measurements and outputs two displays:
Histogram and Latency. For further details and sample outputs, see Using the Timer Latency
Display Tool on page 80.
Both KSRTM (Kernel System Response Time Measurement) and SRTM (System Response
Time Measurement) measure timer latencies. While KSRTM provides detailed information
about the source of the worst-case latency, it measures only the time to the beginning of the
Interrupt Service Routine (ISR). SRTM measures the total time to an RTSS program’s timer
handler (i.e., a full thread context); it is the more realistic measurement of latencies
encountered by RTSS applications.
The worst-case SRTM reported latencies range from 35 to 100 microseconds on most
Pentium-based systems.
75
RTX User’s Guide
This tool exercises the real-time HAL extension, and measures and reports timer response
latencies against a synchronized clock. It can present a histogram of such latencies and report
which kernel component was running when the longest latency event occurred. It can also
provide a list of drivers.
KSRTM optionally measures the latencies associated with kernel (DPC-level) and
multimedia (user-level) timers. It also allows the timer to drive the sound speaker (a 500-
microsecond timer will generate a 1000 Hz square wave). Any timing jitter will produce an
audible frequency wobble.
Usage
ksrtm -s 2
Format
ksrtm [-r] [-k] [-m] [any of the following flags] seconds_to_sample
where
See Also
KSRTM versus SRTM
76
Chapter 5: Performance Overview
By default, this tool generates a 15-second tone and prints a histogram of timer response
latencies. You can run SRTM in the RTSS environment to measure RTSS latencies or in the
Win32 environment to measure Windows NT latencies.
Usage
RTSSrun "c:\program files\vci\rtx\bin\samples\srtm" -h -f -s 15
You can also run SRTM using Windows NT Explorer by double-clicking the srtm.rtss icon
(for RTSS environment) or the srtm.exe icon (for Win32 environment).
Format
srtm [-h] [-s] [-1] [-f] seconds_to_sample
where
cd \program files\vci\rtx\bin\samples\srtm
nmake -f srtm.mak
RTSSrun srtm.rtss -f -h -s 5
There should be no compile, link, or make errors. When you run srtm.rtss, you should hear a
steady 1 KHz tone for five seconds.
See Also
KSRTM versus SRTM
77
RTX User’s Guide
RTX Demo runs an RTSS timer process, a Win32 timer process, or both processes at the
same time. It runs the process using either the fastest timer or a 1 ms timer. The timer can
also be used to drive a sound speaker. The results are plotted to the graphical area where
minimum, average, and maximum latency values are displayed. There are two types of plots:
a plot showing the maximum latency values over time and a plot showing the raw data counts
of maximum latency values for one sample period.
Settings
Run Timer As — Run an RTSS process, a Win32 process, or both processes at once. The
default is an RTSS process.
Sound Options — Choose to hear sound or not. The default setting is sound enabled. If
running both types of processes, you can choose from which process to hear sound. You can
also change the sound options while the timer process is running.
Timer to Use — Choose either the fastest timer available or the 1 ms timer. This option
cannot be changed while the process is running.
Display Options — The Plot option displays graphs in the graphical output area. The default
setting is plot enabled at the start of a run. The Data option writes latency values to the data
area. The default setting is data enabled at the start of a run. You can change these options
while the process is running.
Max Latency Y-axis Scale — This option is used with the Run Max Latency action only.
The selectable values for the plot's y-axis scale are 100 ms, 1000 ms, and 10,000 ms. The
default is 100 ms. You cannot change this selection during data retrieval. This option is
disabled when running the histogram option.
Actions
Run Max Latency — Plots the maximum and average latency values at one-second
intervals. RTSS process results are plotted in cyan, Win32 results in red. The minimum,
average, and maximum latency values are recorded in the data area.
Run Histogram — Plots the number of latency values occurring within 1 ms intervals. RTSS
process results are plotted in cyan, Win32 results in red. The minimum, average, and
maximum values are recorded in the data area, along with the raw data for the histogram.
Add Load — Simulates a disk load on the system in order to show more accurately the
maximum latency times on a busy system. The load consists of a creating a file and writing to
it repeatedly with no buffering.
78
Chapter 5: Performance Overview
57;'HPR0D[/DWHQF\YLHZ
The x-axis shows time in seconds. The y-axis is the response time latency in microseconds.
The solid line plots the maximum latency value in microseconds during a one-second
interval. The dashed line plots the average latency value.
The x-axis shows time in seconds. The y-axis is the response time latency in microseconds.
The solid line plots the maximum latency value in microseconds during a one-second
interval. The dashed line plots the average latency value.
The data area records the minimum, average, and maximum latencies for the interval. It also
shows the greatest maximum value over the course of the data retrieval (from clicking on the
Run Max Latency button until clicking on the Stop button). RTSS latency values are shown
79
RTX User’s Guide
in cyan, Win32 values in red. When Win32 values are too high, they are plotted at the upper
boundary of the window.
The x-axis shows response time latency in microsecond intervals. The y-axis shows a count
from 0 to 2000 when using the fastest timer, 0 to 100 when using the 1 ms timer. The
histogram shows the number of latencies that fell within a particular microsecond interval.
The raw data for the histogram is written to the data area, along with the minimum, average,
and maximum values. The data is refreshed every second. RTSS latency values are shown in
cyan, Win32 values in red.
The RTSS task is similar to SRTM. The main execution thread creates an RTX timer, and
sets it to expire periodically at the fastest available timer rate. The thread then enters a loop,
testing a terminate request flag in shared memory, and sleeping between tests.
The timer function, which is called by RTSS each time the timer expires, reads the RTSS
system clock, and computes the difference between the time observed, and the requested
scheduled time. A histogram of this difference is compiled in shared memory. The RTSS task
also accumulates shortest and longest observed latencies.
Settings
Enable Sound — The timer function toggles the output state of the system speaker port each
time it is called. Since the timer function is called periodically, this results in a tone with a
80
Chapter 5: Performance Overview
period equal to one half of the timer setting value. The system timer is set to 1 ms in the
demo, resulting in a 500 Hz tone.
Latency — View a time sequence of minimum, maximum, and average values observed in a
series of 1-second intervals.
Actions
Reset — Reset accumulated statistics.
Timer Latency Display: Histogram view (Recorded on Gateway G5-233 233 MHz
Pentium)
The horizontal axis represents the time difference between scheduled and observed time, in
microsecond units. The vertical axis represents a count of the number of times this difference
81
RTX User’s Guide
is observed to fall within a particular range, or ’bin.’ Counts are displayed on a logarithmic
axis. The histogram bin size is adjusted automatically to ensure that the highest observed
latency value is visible on the graph.
Timer Latency Display: Latency view (Recorded on Gateway G5-233 233 MHz
Pentium)
The Latency view selects presentation of a time sequence of minimum, maximum, and
average values observed in a series of one-second intervals. Latency is plotted on the vertical
axis. The horizontal axis is set to display the results accumulated over the past one-minute
interval. A bright green vertical bar sweeps from left to right, illuminating the current second.
Usage
RTSSrun ltp -h
Format
ltp [-t <num>] [-s <num>]
where
-t <num> = Watch for latencies greater than this number of microseconds; the default is
10 microseconds.
-s <num> = Run the test for this number of seconds; the default is 20 seconds.
-h = Display message
82
APPENDIX A
/*++
*
* Copyright (c) 1996-1999 VenturCom, Inc. All rights reserved.
*
* Module Name:
*
* RtxLevelIntTest.c
*
* Abstract:
*
* Test code for processing level triggered interrupts
* using the PCI-DIO-96 card. Developed from the pci test
* and gmpt driver.
*
* Author:
*
* Environment:
*
* RTX RTSS application
*
* Revision History:
*
* Version 1 Jun 1 1998
--*/
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
//
// Get and Set Long value macros.
//
#define PTL(x) (*(PLONG)(x))
/* PPI A */
#define PORTA_ADDR ((PUCHAR) BASE_ADDR + 0x00) // Port A (Port 0)
#define PORTB_ADDR ((PUCHAR) BASE_ADDR + 0x01) // Port B (Port 1)
#define PORTC_ADDR ((PUCHAR) BASE_ADDR + 0x02) // Port C (Port 2)
#define CNFG_ADDR ((PUCHAR) BASE_ADDR + 0x03) // Config Register
/* PPI B */
#define B_PORTA_ADDR ((PUCHAR) BASE_ADDR + 0x04) // PPI B Port A (Port 3)
#define B_PORTB_ADDR ((PUCHAR) BASE_ADDR + 0x05) // PPI B Port B (Port 4)
#define B_PORTC_ADDR ((PUCHAR) BASE_ADDR + 0x06) // PPI B Port C (Port 5)
#define B_CNFG_ADDR ((PUCHAR) BASE_ADDR + 0x07) // PPI B Config Port
/* PPI C */
#define C_PORTA_ADDR ((PUCHAR) BASE_ADDR + 0x08) // PPI C Port A (Port 6)
#define C_PORTB_ADDR ((PUCHAR) BASE_ADDR + 0x09) // PPI C Port B (Port 7)
#define C_PORTC_ADDR ((PUCHAR) BASE_ADDR + 0x0A) // PPI C Port C (Port 8)
#define C_CNFG_ADDR ((PUCHAR) BASE_ADDR + 0x0B) // PPI C Config Port
83
RTX User’s Guide
/* PPI D */
#define D_PORTA_ADDR ((PUCHAR) BASE_ADDR + 0x0C) // PPI D Port A (Port 9)
#define D_PORTB_ADDR ((PUCHAR) BASE_ADDR + 0x0D) // PPI D Port B (Port 10)
#define D_PORTC_ADDR ((PUCHAR) BASE_ADDR + 0x0E) // PPI D Port C (Port 11)
#define D_CNFG_ADDR ((PUCHAR) BASE_ADDR + 0x0F) // PPI D Config Port
/* Counter/Timer */
#define CLOCKA ((PUCHAR) BASE_ADDR + 0x10) // Clock or Counter 0
#define CLOCKB ((PUCHAR) BASE_ADDR + 0x11) // Clock or Counter 1
#define CLOCKC ((PUCHAR) BASE_ADDR + 0x12) // Clock or Counter 2
#define CLOCK_CTRL ((PUCHAR) BASE_ADDR + 0x13) // Clock or Counter Control
/* Interrupt control */
#define INTR_CTRL1 ((PUCHAR) BASE_ADDR + 0x14) // First interrupt control reg
#define INTR_CTRL2 ((PUCHAR) BASE_ADDR + 0x15) // Second interrupt control reg
#define INTR_CLEAR (PUCHAR) BASE_ADDR + 0x16) // Interrupt Clear Register
//#define CNFG_VAL 0x80 // 1000 0000 - Port A Output Port B Output Port C Output
//#define CNFG_VAL 0x90 // p 6-10 - Port A Input Port B Output Port C Output
#define CNFG_VAL 0x15 // p 6-10 - Port A Input Port B Input Port C Input
// Note: Standard RTX time units are 100 ns long, or 10 units per microsecond.
#define STOP_TIME 5 // Minutes for shutdown handler to wait
// after stopping before terminating.
// 0 for indefinite.
PCHAR _base_addr;
PCI_SLOT_NUMBER SlotNumber;
PPCI_COMMON_CONFIG PciData;
UCHAR buffer[PCI_COMMON_HDR_LENGTH];
ULONG IntCountDown; // number of ints calls wait for clearing
ULONG IntCountTotal; // total int count
ULONG IntCountCLear; // total int cleared
BOOLEAN IntDone; // when we are done
void
main( int argc, PCHAR *argv )
{
ULONG i; // logical slot number for the PCI adapter
ULONG f; // function number on the specified adapter
ULONG bytesWritten; // return value from RtGetBusDataByOffset
ULONG bus; // bus number
BOOLEAN flag;
84
Appendix A: Code and File Examples
BAR0.QuadPart = 0;
BAR1.QuadPart = 0;
tBAR0.QuadPart = 0;
tBAR1.QuadPart = 0;
//
// Search for the PCI-DIO-96 card
//
for (bus = 0; flag; bus++)
{
for (i = 0; i < PCI_MAX_DEVICES && flag; i++)
{
SlotNumber.u.bits.DeviceNumber = i;
bytesWritten = RtGetBusDataByOffset (
PCIConfiguration,
bus,
SlotNumber.u.AsULONG,
PciData,
0,
PCI_COMMON_HDR_LENGTH
);
if (bytesWritten == 0)
{
// out of PCI buses
flag = FALSE;
break;
}
if (PciData->VendorID == PCI_INVALID_VENDORID)
{
// no device at this slot number, skip to next slot
break;
}
//
// A device is found, if this is our card, then
// print out all the PCI configuration information
// and set the variables.
//
if ((PciData->VendorID == 0x1093) && (PciData->DeviceID == 0x0160))
{
// Set IRQ values for attaching interrupt below
IrqLevel = PciData->u.type0.InterruptLine; // interrupt level
IrqVectr = IrqLevel; // interrupt IRQ
// MITE address
BAR1.QuadPart = PciData->u.type0.BaseAddresses[1];
// new board address
intbusnumb = bus;
printf("\nPCI-DIO-96:\n");
printf("------------------------------------------\n");
printf("BusNumber:\t\t%d\n", bus);
printf("DeviceNumber:\t\t%d\n", i);
printf("FunctionNumber:\t\t%d\n", f);
printf("VendorID:\t\t0x%x\n", PciData->VendorID);
printf("DeviceID:\t\t0x%x\n", PciData->DeviceID);
85
RTX User’s Guide
printf("Command:\t\t0x%x\n", PciData->Command);
printf("Status:\t\t\t0x%x\n", PciData->Status);
printf("RevisionID:\t\t0x%x\n", PciData->RevisionID);
printf("ProgIf:\t\t\t0x%x\n", PciData->ProgIf);
printf("SubClass:\t\t0x%x\n", PciData->SubClass);
printf("BaseClass:\t\t0x%x\n", PciData->BaseClass);
printf("CacheLineSize:\t\t0x%x\n", PciData->CacheLineSize);
printf("LatencyTimer:\t\t0x%x\n", PciData->LatencyTimer);
printf("HeaderType:\t\t0x%x\n",PciData->HeaderType);
printf("BIST:\t\t\t0x%x\n", PciData->BIST);
printf("BaseAddresses[0]:\t0x%08x\n",PciData->u.type0.BaseAddresses[0]);
printf("BaseAddresses[1]:\t0x%08x\n",PciData->u.type0.BaseAddresses[1]);
printf("BaseAddresses[2]:\t0x%08x\n",PciData->u.type0.BaseAddresses[2]);
printf("BaseAddresses[3]:\t0x%08x\n",PciData->u.type0.BaseAddresses[3]);
printf("BaseAddresses[4]:\t0x%08x\n",PciData->u.type0.BaseAddresses[4]);
printf("BaseAddresses[5]:\t0x%08x\n",PciData->u.type0.BaseAddresses[5]);
printf("ROMBaseAddress:\t\t0x%08x\n",PciData->u.type0.ROMBaseAddress);
printf("InterruptLine:\t\t%d\n",PciData->u.type0.InterruptLine);
printf("InterruptPin:\t\t%d\n",PciData->u.type0.InterruptPin);
printf("MinimumGrant:\t\t%d\n",PciData->u.type0.MinimumGrant);
printf("MaximumLatency:\t\t%d\n",PciData->u.type0.MaximumLatency);
printf("\n");
printf(" BAR0: BusRelativeAddress: 0x%08x\n", BAR0.LowPart);
printf(" BAR1: BusRelativeAddress: 0x%08x\n", BAR1.LowPart);
//
// Translate the base port addresses to system mapped addresses.
//
if (! RtTranslateBusAddress(
PCIBus,
0,
BAR0,
&AddressSpace,
&tBAR0
))
{
fail ("tBAR0: RtTranslateBusAddress failed");
}
else
{
printf("tBAR0: SystemMappedAddress: 0x%08x\n", tBAR0.LowPart);
}
if (! RtTranslateBusAddress(PCIBus,
0,
BAR1,
&AddressSpace,
&tBAR1
))
{
fail ("tBAR1: RtTranslateBusAddress failed.");
}
else
{
printf("tBAR1: SystemMappedAddress: 0x%08x\n", tBAR1.LowPart);
}
//
// Map the addresses to virtual addresses the software can use
//
if (vBAR0 == 0)
{
printf(" BAR0: Failure on RtMapMemory\nError=%d\n", GetLastError());
}
else
{
printf(" BAR0: VirtualMemoryAddress: 0x%08x\n",vBAR0);
}
86
Appendix A: Code and File Examples
//
// Set the command parameter so we can access the PCI device’s
// control registers.
//
PciData->Command = (PCI_ENABLE_IO_SPACE |
PCI_ENABLE_MEMORY_SPACE |
PCI_ENABLE_BUS_MASTER |
PCI_ENABLE_WRITE_AND_INVALIDATE);
RtSetBusDataByOffset(PCIConfiguration,
bus,
SlotNumber.u.AsULONG,
PciData,
0,
PCI_COMMON_HDR_LENGTH);
//
// Initialize the card
// No 1 MB limit - no need to remap the memory.
// Note: You need to use the BusRelativeAddress to set the
// window_data_value.
//
window_data_value = ( (0xffffff00 &
(ULONG)BAR1.LowPart) | (0x00000080) );
PTL(vBAR0+0x000000c0) = window_data_value;
}// dio 96
} // max_function
} // max_devices
} // flag
//
// At this point the card has been found, memory mapped, so we go ahead
// and attempt to utilize the card for testing
//
_base_addr=vBAR1; // Memory already mapped
// Disable interrupts from I/O ports
*(INTR_CTRL1) = 0x00;
// Disable interrupts from counters
*(INTR_CTRL2) = 0x00;
//
// Attempt to attach to this interrupt, using data acquired above
//
ihr = RtAttachInterruptVector(NULL, // security attributes (default)
0, // stacksize (default)
respond, // interrupt handler
NULL, // context argument
RT_PRIORITY_MAX,
PCIBus, // interface type (PCI)
intbusnumb, // bus number
IrqLevel, // interrupt level
IrqVectr); // interrupt vector
}
See Also
Bus IO
87
RTX User’s Guide
// Generate an interrupt
// with the digital outs
#include <windows.h>
#include <rtapi.h>
int ihc = 0 ;
int ihc2 = 0 ;
int limit = 30 ;
void RTFCNDCL
InterruptHandler(void * unused)
{
RtWritePortUchar(CT_BASE_PORT_DO(CT_PORT), 0x00) ;
inc + + ;
}
int TestIncrease = 1 ;
main()
{
HANDLE hInterrupt ;
int i ;
InterruptHandler,
(void *)&TestIncrease,
1,
1,
0,
7,
7) ;
if ( NULL == hInterrupt ) {
88
Appendix A: Code and File Examples
See Also
Interrupts
Port IO
89
RTX User’s Guide
Makefile Sample
The following makefile is an annotated version of the one used to build srtm (a sample
program that measures timer response latencies).
#
# Copyright (c) 1996 - 1999 VenturCom, Inc. All rights reserved.
#
# Module Name:
#
# srtm.mak
#
# Abstract:
#
# nmakefile to build the SRTM demo as a RTSS process.
#
# NODEBUG
# Define to remove debugging information in executable
NODEBUG = 1
# RTSS_CRT
# Define to link with RTSS single-threaded C run-time library
# RTSS_CRT = 1
# RTSS_MTCRT
# Define to link with RTSS multi-threaded C run-time library
# RTSS_MTCRT = 1
all: srtm.rtss
See Also
Using the RTX Makefile
Debugging an RTX Program
90
Appendix A: Code and File Examples
!include <rtx.mak>
all: thandler.dll thankler.rtdll
clean:
-del thandler.obj thandler.dll thandler.rtdll
See Also
Creating Dynamic Link Libraries
91
RTX User’s Guide
#define NO_ERRORS 0
#define ERROR_OCCURRED -1
#define SPEAKER_PORT ((PUCHAR)0x61) //Port IO address for speaker
92
Appendix A: Code and File Examples
93
RTX User’s Guide
//the end
return (NO_ERRORS);
}
!include <rtx.mak>
clean:
-del *.rtdll
-del *.lib
-del *.obj
-del *.exp
-del *.dll
-del *.exe
94
Appendix A: Code and File Examples
//
// MAIN - just suspend the main thread for this process until its
// use as a DLL is finished and the process is terminated.
//
int main(int argc, char **argv)
{
SuspendThread( GetCurrentThread());
return 0;
}
//
// The exported DLL function.
//
VOID
_stdcall
Toggle(VOID)
{
UCHAR i;
EXPORTS
Toggle
95
RTX User’s Guide
#define NO_ERRORS 0
#define ERROR_OCCURRED -1
//
// External function prototype.
//
VOID _stdcall Toggle(VOID);
//
// Timer handler -- call the "Toggle" function.
int
RTFCNDCL
TimerHandler(PVOID unused)
{
Toggle(); // Call the DLL exported function
return NO_ERROR;
}
//
// MAIN -- start the timer and wait 10 seconds.
//
int
main(
int argc,
char *argv[])
{
LARGE_INTEGER time;
HANDLE hTimer;
ULONG stackSize = 0;
int waitTime = 10000; //10 seconds
//
// Setup and start the periodic timer.
//
if (!(hTimer = RtCreateTimer(
NULL, // Security - NULL is none
stackSize, // Stack size - 0 is use default
TimerHandler, // Timer handler
NULL, // NULL context (argument to handler)
RT_PRIORITY_MAX, // Priority
CLOCK_FASTEST))) // Always use fastest available clock
{
printf("ERROR: Could not create the RTX timer.\n");
return (ERROR_OCCURED);
}
//
// Wait for 10 seconds.
//
Sleep(waitTime);
//
96
Appendix A: Code and File Examples
return (NO_ERRORS);
}
!include <rtx.mak>
dll.rtss: dll.obj
lib -nodefaultlib -machine:$(CPU) -out:dll.lib -def:dll.def dll.obj
link $(rtsslflags) -out:dll.rtss dll.exp dll.obj $(rtsslibs)
del dll.exp
clean:
-del *.rtss
-del *.obj
-del *.exe
-del dll.lib
#define NO_ERRORS 0
#define ERROR_OCCURRED -1
//
// Standard function to run a utility.
//
LONG
RunUtility(
PCHAR lpCmd
)
{
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
LONG exitCode = 0;
//
// Initialize startup info to all zeros.
//
ZeroMemory(&sinfo, sizeof(sinfo));
sinfo.cb=sizeof(sinfo);
//
// Create the process to run the utility.
//
if (CreateProcess(NULL, lpCmd, NULL, NULL, FALSE, 0, NULL,
97
RTX User’s Guide
//
// Wait for the utility to complete.
//
WaitForSingleObject( pinfo.hProcess, INFINITE);
//
// Get the exit code (RTSSrun returns the process slot) and close handles.
//
GetExitCodeProcess( pinfo.hProcess, &exitCode);
CloseHandle( pinfo.hThread);
CloseHandle( pinfo.hProcess);
return exitCode;
}
//
// MAIN.
//
int
main(
int argc,
char *argv[])
{
LONG dllPid, testPid;
char buf[50];
int sleepTime = 5000;
LONG exitCode = 0;
//
// Load the RTSS DLL first.
//
dllPid = RunUtility("RTSSrun dll.rtss");
if (dllPid<=exitCode)
{
printf("DLL failed to load.\n");
return (ERROR_OCCURED);
}
//
// Now run the test program.
//
testPid = RunUtility("RTSSrun dll-test.rtss");
if (testPid<=exitCode)
{
printf("DLL-TEST failed to run,\n");
return (ERROR_OCCURED);
}
//
// Sleep for 5 seconds and then terminate program and dll.
//
Sleep(sleepTime);
return NO_ERROR;
}
98
Appendix A: Code and File Examples
NODEBUG = 1
!include <rtx.mak>
all: dll.rtss
dll.rtss: dll.obj
lib -nodefaultlib -machine:$(CPU) -out:dll.lib -def:dll.def dll.obj
link $(rtsslflags) -out:dll.rtss dll.exp dll.obj $(rtsslibs)
del dll.exp
clean:
-del *.rtss
-del *.obj
-del *.exe
-del dll.lib
See Also
Creating Dynamic Link Libraries
99
RTX User’s Guide
RTSSkill Examples
RTSSkill Example 1
The following example illustrates information provided by RTSSkill when run with no
arguments for a system running an application called TimerTest which uses a single RTDLL.
RTSSkill
STATE NAME
Loaded timer.rtdll
Not Loaded foo.rtdll
RTSSkill Example 2
The following example illustrates information provided by RTSSkill 001 for the system in the
preceding example.
RTSSkill
STATE NAME
Not Loaded timer.rtdll
Not Loaded foo.rtdll
See Also
RTSSkill Utility
100
Appendix A: Code and File Examples
RTSSview Example
The following example illustrates information provided by RTSSview for a system running
an application called TimerTest, linked with the C run-time library. The unnamed mutexes
are created by the C run-time initialization code.
============== RTSSview v4.3 ==============
Object(ID) Address Information
15
---------- ------- -----------
Command w32_dll.rtss - Supplemental Win32 for C runtime library
Process(010) 806a3c28
Thread(00004) 806a3cc8 Pri=0 Flags=1 State=Suspended
Command rtssview.rtss
Process(002) 805fad28
Thread(0000e) 805fadc8 Pri=0 Flags=1 State=Ready
Mutexes:
805f18f0 Count=0 Owner=0 Name="** UNNAMED **"
805efb70 Count=0 Owner=0 Name="** UNNAMED **"
805ef6d0 Count=0 Owner=0 Name="** UNNAMED **"
805f0b70 Count=0 Owner=0 Name="** UNNAMED **"
805f06d0 Count=0 Owner=0 Name="** UNNAMED **"
805f3690 Count=0 Owner=0 Name="** UNNAMED **"
805f2b70 Count=0 Owner=0 Name="** UNNAMED **"
805f26d0 Count=0 Owner=0 Name="** UNNAMED **"
805f5b70 Count=0 Owner=0 Name="** UNNAMED **"
805f56d0 Count=0 Owner=0 Name="** UNNAMED **"
805d5010 Count=0 Owner=0 Name="** UNNAMED **"
805d5690 Count=0 Owner=0 Name="** UNNAMED **"
805beb70 Count=0 Owner=0 Name="** UNNAMED **"
805bb010 Count=0 Owner=0 Name="** UNNAMED **"
See Also
RTSSview Utility
101
RTX User’s Guide
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
void main(void)
{
maxPhyAddr.QuadPart = 0xFFFFFF;
size= 0x1000; // Size in KB.
// Allocate memory
vAddress = RtAllocateContiguousMemory( size, maxPhyAddr);
if (!vAddress) {
printf("\nFailure on RtAllocateContiguousMemory\t");
printf("Error=%d\n", GetLastError());
break;
}
else {
printf("\nSuccess on RtAllocateContiguousMemory\n");
printf("Virtual memory address = 0x%08X\n", vAddress);
// Free memory
if (!RtFreeContiguousMemory(vAddress)) {
printf("\nFailure on
RtFreeContiguousMemory(0x%08X).\t", vAddress);
printf("Error Code = %d\n", GetLastError());
}
else {
printf("Success on RtFreeContiguousMemory(0x%X).\n", vAddress);
}
}
ExitProcess(0);
}
See Also
Contiguous Memory Mapping
102
Appendix A: Code and File Examples
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
void main(void) {
See Also
System Memory Management
103
RTX User’s Guide
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
// Allocate memory
vAddress = RtAllocateLockedMemory(size);
if (!vAddress) {
printf("\nFailure on RtAllocateLockedMemory\t");
printf("Error=%d\n", GetLastError());
break; // if this fails - no use to continue
}
else {
printf("\nSuccess on RtAllocateLockedMemory\n");
printf("Virtual memory address = 0x%08X\n", vAddress);
// Free memory
if (!RtFreeLockedMemory(vAddress)) {
printf("\nFailure on RtFreeLockedMemory(0x%08X).\t", vAddress);
printf("Error Code = %d\n", GetLastError());
}
else {
printf("Success on RtFreeLockedMemory(0x%X).\n", vAddress);
}
ExitProcess(0);
}
See Also
System Memory Management
104
Appendix A: Code and File Examples
void main(void) {
BOOL success=0;
static PVOID vAddress; // virtual memory address returned
LARGE_INTEGER physAddr; // base physical address
ULONG length; // length to map in
BOOLEAN cacheEnable; // cache accesses to memory ?
physAddr.QuadPart = 0x0000FFFFF;
length = 1024;
cacheEnable = 0;
if (vAddress==NULL) {
printf("Failure on RtMapMemory( 0x%08X, %d, %d ).\n", physAddr.LowPart, length,
cacheEnable );
}
else {
printf("Success on RtMapMemory( 0x%08X, %d, %d ).\n", physAddr.LowPart, length,
cacheEnable );
printf("Virtual memory address = 0x%08X \n", vAddress);
See Also
Physical Memory Mapping
105
RTX User’s Guide
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
void main(void) {
if (!RtLockProcess( dwSections)) {
printf("\nFailure on RtLockProcess.\t");
printf("Error=%d\n", RtGetLastError());
}
else {
printf("\nSuccess on RtLockProcess\n");
if (!RtUnlockProcess( dwSections)) {
printf("\nFailure on RtUnlockProcess.\t");
printf("Error=%d\n", RtGetLastError());
}
else {
printf("\nSuccess on RtUnlockProcess\n", i);
}
}
ExitProcess(0);
}
See Also
System Memory Management
106
Appendix A: Code and File Examples
#include "windows.h"
#include "stdio.h"
#include "rtapi.h"
//
// Local data.
//
LARGE_INTEGER Period; // Timer period
LARGE_INTEGER StartTime; // Start time of sampling run
ULONG TimerCounter = 0; // Counts entries to timer handler
//
//
VOID
main(int argc, char **argv)
{
LARGE_INTEGER x;
HANDLE hTimer;
//
// Set default timer period to 500 micro seconds
//
Period.QuadPart = 5000;
//
// Set to the next to highest real-time priority.
//
if (!RtSetThreadPriority( GetCurrentThread(), RT_PRIORITY_MAX-1))
printf("WARNING: Can’t set to highest RTAPI priority.\n");
//
// Setup and start the periodic timer.
//
if (!(hTimer = RtCreateTimer(
NULL, // Security - NULL is none
0, // Stack size - 0 is use default
TimerHandler, // Timer handler
NULL, // NULL context (argument to handler)
RT_PRIORITY_MAX, // Priority
CLOCK_2))) // RTX HAL Timer
{
printf("ERROR: Could not create the RTAPI timer.\n");
ExitProcess(2);
}
//
// Wait for the sampling time.
//
Sleep(1000);
//
// Stop and delete the timer.
//
RtCancelTimer( hTimer, &x);
RtDeleteTimer( hTimer);
107
RTX User’s Guide
//
// timer handler function
// - increment the tick counter
//
int
RTFCNDCL
TimerHandler(
PVOID unused
)
{
TimerCounter++;
return 0 ;
}
See Also
Clocks and Timers
108
Index
Management, 74
B RTX Management, 74
Book Overview, 33 Interrupt Management, 48
Interrupt Service Routine, 48
C Interrupt Service Thread, 48
C Run-time Library Functions, 59 Interrupts, 48
Using, 59 IPC, 1
CENTer, x ISR, 48
Control Panel, 30 Issue
CreateFile, 53 Green Screen, 63
IST, 48
D attach, 48
Debugging, 4, 21, 30 set, 48
RTSS, 4 K
Developer Studio 5.0, 21
Developing RTX Applications, 4 Kernel System Response Time Measurement,
Device Management, 33 75
DMA, 52, 75 KSRTM, 75
Documentation Updates, x KSRTM versus SRTM, 75
E L
Event Objects, 46 Latency, 75
Exception Handling, 60 Latency Test Program, 75, 82
General User Notes, 60 M
F Max Latency Plot, 78
Floating-Point Support, 59 Interpreting, 78
FreeLibrary, 92 Microsoft Developer Studio 5.0, 21
Microsoft Visual Studio, 21
G Microsoft Visual Studio 6.0, 21
GetCurrentProcess, 34 Mutex, 43
GetExceptionCode, 60 O
GetExceptionInformation, 60
Graphical version Object Names, 43
SRTM, 78 P
H Port I/O Calls, 48
HAL, 30, 40 Power Management, 74
HAL Timer Period, 30 Process Exception Disposition, 70
HalTimerPeriod, 40 Programming, 70
Histogram, 78 Techniques/Considerations, 70
Histogram Plot, 78 R
Interpreting, 78
Real-Time Inter-Process Communication, 1
I RtAllocateContiguousMemory, 102
Interprocess Communication, 33 RTAPI, 95
Inter-Process Communication, 43, 46 RtAttachInterruptVector, 48
Interrupt Latencies, 74 RtCancelTimer, 107
109
RTX User’s Guide
110
Index
U develop, 59
Win32 Platform SDK, 60
Use Win32 SDK Tools, 26
RTSSkill, 70 Win32 Structured Exception Handling, 60
RTX, 70 Win32Debug, 21
Using LTP, 82 WinDbg, 26, 66
Using RTX Demo, 78 WinDbg 4.0, 26
Using Software Development Tools, 7 WinDbg 5.0, 26
V Windows 2000 Stop Messages, 65
Windows 2000 Stop Screens, 68
VenturCom Customer Support Web, ix Windows NT Automatically Reboot, 65
VenturCom Web site, ix Windows NT Blue Screen, 65, 66
W Windows NT Blue Screen Stop Messages, 66
Interpreting, 66
Watchdog Management, 70 Windows NT Control Panel, 65, 66
Watchdog Timer, 70 Write Debugging Information, 66
Win32 application, 59
111