Sunteți pe pagina 1din 121

RTX 5.

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.

 2000 VenturCom, Inc. All rights reserved.

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.

RTX 5.0 User’s Guide


1-015-10
Table of Contents
WELCOME TO RTX 5.0 ................................................................................................IX
Getting Support.............................................................................................................. ix
Technical Support ........................................................................................................................ ix
VenturCom Web Site ................................................................................................................... ix
Documentation Updates.................................................................................................. x
About the User’s Guide ................................................................................................... x
CHAPTER 1
INTRODUCTION TO RTX............................................................................................... 1
The RTX Architecture...................................................................................................... 1
Real-Time Inter-Process Communication .....................................................................................2
HAL Extension...............................................................................................................................2
Uniprocessor and Multiprocessor Systems...................................................................................2
The RTX Application Programming Interface (API) ......................................................... 3
Win32 and Real-Time API.............................................................................................................3
RTX Executable Images ...............................................................................................................3
Run-Time Libraries........................................................................................................................4
Unicode .........................................................................................................................................4
Designing and Developing RTX Applications .................................................................. 4
RTX Device Drivers.......................................................................................................................4
Testing Real-Time Applications ....................................................................................................5
Creating and Starting an RTSS Process ......................................................................................5
Stopping an RTSS Process ..........................................................................................................5
CHAPTER 2
USING SOFTWARE DEVELOPMENT TOOLS .............................................................. 7
Using the RTX Utilities .................................................................................................... 8
Utility Task Table...........................................................................................................................8
RTSSrun Utility (Console and GUI) ..............................................................................................9
RTSSrun GUI ..............................................................................................................................10
RTSSkill Utility.............................................................................................................................11
RTSSview Utility..........................................................................................................................12
RTSSview Example ............................................................................................................................... 12
RTSS Object Viewer ...................................................................................................................13
RTSS Task Manager...................................................................................................................15
RtxServer ....................................................................................................................................16
Using the RTX AppWizard in Microsoft Visual Studio 6.0.............................................. 17
Creating a Project and Setting Options.......................................................................................17
Setting Project Options .......................................................................................................................... 18
Setting Program Options ....................................................................................................................... 19
Running an Image.......................................................................................................................20
Registering an RTDLL.................................................................................................................21

iii
RTX User’s Guide

Using Microsoft Visual Studio 6.0.................................................................................. 21


Setting up Microsoft Visual Studio ..............................................................................................21
Building and Running Images (Win32 Environment) ..................................................................21
Building and Running Images (RTSS Environment)...................................................................22
Building and Registering RTDLLs ...............................................................................................23
Creating RTX Dynamic Link Libraries ........................................................................... 25
Building an RTDLL ......................................................................................................................25
Building an RTSS DLL ................................................................................................................25
Debugging an RTX Program ......................................................................................... 26
Excluding debugging information................................................................................................26
Using Microsoft’s WinDbg 5.0 with RTSS ...................................................................................29
Testing an RTX Program with Shutdown Handlers........................................................ 29
Shutdown Program .....................................................................................................................29
Gencrash Driver ..........................................................................................................................29
Usage .................................................................................................................................................... 30
Using the RTX Properties Contol Panel ........................................................................ 30
CHAPTER 3
USING THE RTX FUNCTIONALITY ............................................................................. 33
Process and Thread Management ................................................................................ 34
Processes and Threads ..............................................................................................................34
Using Processes.................................................................................................................................... 34
Using Threads ....................................................................................................................................... 35
Thread Priorities .................................................................................................................................... 35
System Memory Management ....................................................................................................37
System Memory Allocation .................................................................................................................... 37
System Memory Locking ....................................................................................................................... 38
Clocks and Timers ......................................................................................................................40
Clock Services ....................................................................................................................................... 40
Timer Services....................................................................................................................................... 41
Sleep Services....................................................................................................................................... 42
APIs ....................................................................................................................................................... 42
Programming Considerations ................................................................................................................ 42
Programming Example (RTX Timer and Sleep Calls)............................................................................ 42
Inter-Process Communication ....................................................................................... 43
Object Names .............................................................................................................................43
Shared Memory...........................................................................................................................43
Inter-Process Communication via Shared Memory................................................................................ 43
Environments......................................................................................................................................... 44
Semaphores ................................................................................................................................44
Inter-Process Communication via Semaphores..................................................................................... 45
Environments......................................................................................................................................... 45
Event Objects ..............................................................................................................................46
Using RtCreateEvent ............................................................................................................................. 46
Using RtPulseEvent............................................................................................................................... 46

iv
RTX User’s Guide

Mutex Objects .............................................................................................................................46


Ownership ............................................................................................................................................. 46
Inter-Process Communication via Mutex Objects .................................................................................. 47
Environments......................................................................................................................................... 47
Device Management ..................................................................................................... 48
Interrupts .....................................................................................................................................48
Interrupt Management ........................................................................................................................... 48
APIs ....................................................................................................................................................... 48
General Programming Considerations................................................................................................... 49
Win32 Environment Programming Considerations ................................................................................ 49
Using RtAttachInterruptVector ............................................................................................................... 49
Using RtAttachInterruptVectorEx ........................................................................................................... 49
Using RtReleaseInterruptVector ............................................................................................................ 50
Programming Example (Interrupt Management and Port I/O Calls)....................................................... 50
Port IO .........................................................................................................................................50
Port I/O Control APIs ............................................................................................................................. 50
Port I/O Data Transfer APIs................................................................................................................... 51
General Programming Considerations................................................................................................... 51
Programming Example .......................................................................................................................... 51
Physical Memory Mapping ..........................................................................................................51
APIs ....................................................................................................................................................... 51
General Programming Considerations................................................................................................... 52
Win32 Environment Programming Considerations ................................................................................ 52
Programming Example (RTX Memory Mapping Calls) .......................................................................... 52
Contiguous Memory Mapping .....................................................................................................52
Programming Considerations ................................................................................................................ 52
Programming Example (RTX Contiguous Memory Allocation Calls) ..................................................... 53
Bus IO .........................................................................................................................................53
Programming Example (Bus I/O) ........................................................................................................... 53
File IO..........................................................................................................................................53
File IO .................................................................................................................................................... 53
CHAPTER 4
DEVELOPING AN APPLICATION ............................................................................... 55
Using the RTX Makefile ................................................................................................ 56
Variables .....................................................................................................................................56
Sample Makefile..........................................................................................................................56
Using RTX Dynamic Link Libraries................................................................................ 57
About RTSS DLLs and RTDLLs..................................................................................................57
C Run-Time Libraries: Programming Considerations for DLLs ..................................................57
RTSS DLLs............................................................................................................................................ 58
RTDLLs ................................................................................................................................................. 58
RTSS DLL and RTDLL Code Examples ................................................................................................ 58
Using the C Run-time Library Functions........................................................................ 59
Using Floating Point ...................................................................................................... 59
Enabling Floating-Point Support in RTSS Programs ..................................................................59

v
RTX User’s Guide

Running RTSS Programs Using Floating-Point ..........................................................................59


Writing RTSS Device Drivers ........................................................................................ 59
C++ and Structured Exception Handling ....................................................................... 60
C++ Support ................................................................................................................................60
Structured Exception Handling....................................................................................................60
Using SEH...................................................................................................................................61
Differences Between Win32 and RTSS Exception Handling ................................................................. 61
UnhandledExceptionFilter...................................................................................................................... 61
Exception caused by a thread ............................................................................................................... 61
Nested exceptions and collided unwinds ............................................................................................... 61
Debugging ............................................................................................................................................. 62
General User Notes for Exception Handling ...............................................................................62
System Exception Handling .......................................................................................... 62
About System Exception Handling..............................................................................................62
RTX Handler................................................................................................................................62
Tables of Exceptions...................................................................................................................63
RTX Exception Codes ........................................................................................................................... 63
Intel Exception Codes............................................................................................................................ 63
RTX Exception Handling .............................................................................................................64
Freeze or Terminate Processing............................................................................................................ 64
Alert User............................................................................................................................................... 64
Generate Event Log Entries .................................................................................................................. 65
About RTX and Windows NT / Windows 2000 Stop Messages .................................................65
Interpreting Windows NT Blue Screen Stop Messages ..............................................................66
Section 1 - Stop Message...................................................................................................................... 66
Section 2 - Driver List ............................................................................................................................ 66
Section 3 - System Stack Dump ............................................................................................................ 66
Section 4 - Communication.................................................................................................................... 67
Interpreting Windows 2000 Stop Screens...................................................................................68
Interpreting RTX Green Screen Stop Messages ........................................................................69
Section 1 - RTSS-Specific Stop Message ............................................................................................. 69
Section 2 - HAL-Supplied Stop Message............................................................................................... 70
Starvation Management ..............................................................................................................70
Watchdog Management......................................................................................................................... 70
Setting the Starvation Time Out Period ................................................................................................. 71
RTX Power Management for Windows 2000..............................................................................71
CHAPTER 5
PERFORMANCE OVERVIEW ...................................................................................... 73
Causes and Management of Interrupt Latencies ........................................................... 74
Software Causes .........................................................................................................................74
Hardware Causes .......................................................................................................................74
RTX Management of Interrupt Latencies ....................................................................................74
Reducing Your System’s Latencies: Tools Overview..................................................... 75
SRTM (System Response Time Measurement) and RTX Demo ...............................................75
KSRTM (Kernel System Response Time Measurement) ...........................................................75

vi
RTX User’s Guide

LTP (Latency Test Program).......................................................................................................75


Timer Latency Display.................................................................................................................75
KSRTM versus SRTM.................................................................................................................75
Using KSRTM (Kernel System Response Time Measurement)..................................... 76
Using SRTM (System Response Time Measurement) .................................................. 77
Using RTX Demo (Graphical version of SRTM) ............................................................ 78
Interpreting the Max Latency Plot ...............................................................................................79
Interpreting the Histogram Plot ...................................................................................................80
Using the Timer Latency Display Tool ........................................................................... 80
Interpreting the Histogram...........................................................................................................81
Interpreting the Latency display ..................................................................................................82
Using LTP (Latency Test Program) ............................................................................... 82
APPENDIX A
CODE AND FILE EXAMPLES...................................................................................... 83
Bus IO Programming Example ...................................................................................... 83
Interrupt Management and Port IO Calls Programming Example .................................. 88
Makefile Sample ........................................................................................................... 90
Nmake Input File Example ............................................................................................ 91
RTDLL Code Example .................................................................................................. 92
RTDLL Part 1: sampleRtdll.c.......................................................................................................92
RTDLL Part 2: usingRtdll.c..........................................................................................................92
RTDLL Part 3: rtdll.mak...............................................................................................................94
RTDLL Part 4: Register the rtdll ..................................................................................................94
RTSS DLL Code Example............................................................................................. 95
RTSS DLL Part 1: dll.c ................................................................................................................95
RTSS DLL Part 2: dll.def.............................................................................................................95
RTSS DLL Part 3: dll-test.c .........................................................................................................96
RTSS DLL Part 4: dll.mak ...........................................................................................................97
RTSS DLL Part 5: runtest.c.........................................................................................................97
RTSS DLL Makefile Example........................................................................................ 99
RTSSkill Examples...................................................................................................... 100
RTSSkill Example 1 ..................................................................................................................100
RTSSkill Example 2 ..................................................................................................................100
RTSSview Example .................................................................................................... 101
RTX Contiguous Memory Allocation Calls Programming Example .............................. 102
RTX Kernel Memory Locking Calls Programming Example......................................... 103
RTX Locked Memory Allocation Calls Programming Example .................................... 104
RTX Memory Mapping Calls Programming Example................................................... 105
RTX Process Memory Locking Calls Programming Example ...................................... 106

vii
RTX User’s Guide

RTX Timer and Sleep Calls Programming Example .................................................... 107


INDEX......................................................................................................................... 109

viii
Welcome to RTX 5.0

Document ID: 1-015-10


© 2000 VenturCom, Inc. All rights reserved.

VenturCom’s Real-time Extension (RTX) adds real-time capabilities to Windows NT and


Windows 2000 that are unparalleled in the industry. It offers developers a rich and powerful
real-time feature set — all in a familiar Win32-compatible interface. It also provides tools
and utilities for building and executing real-time programs, along with tools for measuring
and fine tuning the performance of both hardware and software.

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)

ΠEmail your questions to support@vci.com

ΠFax your questions to 617-577-1607

VenturCom Web Site

The VenturCom Customer Support Web page is located at:

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.

About the User’s Guide


The RTX User’s Guide describes the RTX product and explains how to use its features; it is
intended for users who are familiar with developing applications in a Win32 environment.

The following list introduces the chapters in this guide.

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.

Developing an Application — Explains how to use dynamic link libraries, C run-time


library functions, and floating point when developing an application. It also describes
exception handling in the RTSS and Win32 environments and techniques for managing
starvation conditions.

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.

The RTX Architecture


RTX adds a real-time subsystem, known as RTSS, to Windows NT and Windows 2000 (see
the figure below). RTSS is conceptually similar to other Windows NT subsystems (such as
Win32, POSIX, WOW, and DOS) in that it supports its own execution environment and API.
RTSS differs in one important area, though: Instead of using the Windows NT or Windows
2000 scheduler, RTSS performs its own real-time thread scheduling. Furthermore, in a
uniprocessor environment, all RTSS thread scheduling occurs ahead of all Windows
scheduling, including Windows-managed interrupts and Deferred Procedure Calls (DPCs).

1
RTX User’s Guide

57;DQG:LQGRZV17:RUNLQJ7RJHWKHU

Real-Time Inter-Process Communication

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.

Uniprocessor and Multiprocessor Systems

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

executed on the dedicated processor.

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.

The RTX Application Programming Interface (API)


The RTX API is based on the Win32 API, using the same API already familiar to Windows
application developers. This approach allows developers to draw upon their Win32
experience, code base, and development tools, thus expediting hard real-time application
development. Both Win32 and RTSS processes support the full RTX API — albeit with
different response times and performance characteristics — allowing developers to
effortlessly share or move code between environments.
This topic discusses:

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 Executable Images

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.

Designing and Developing RTX Applications


To ensure successful development of a real-time application, designers and developers must
carefully analyze how to efficiently partition the application. They must also establish the
correct balance between non-real-time (Win32) processes and real-time (RTSS) processes
and determine the interface between them. If, for example, there is time-critical processing in
Win32 processes, too much non-time-critical processing in RTSS processes, or too much
synchronization or data flow across the process interfaces, the application’s performance,
usability, and overall ease of development and maintenance will be jeopardized. An initial
investment of time spent analyzing the various tradeoffs and designs in this critical
architecture area will be worthwhile to both developers and their users.

This topic discusses:

ΠRTX_Device_Drivers
ΠTesting Real-Time Applications
ΠStarting an RTSS Process
ΠStopping an RTSS Process

RTX Device Drivers

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

and control) to either Win32 or RTSS applications.

Testing Real-Time Applications

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.

Creating and Starting an RTSS Process

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.

Stopping an RTSS Process

An RTSS process stops when:

ΠThe process calls the ExitProcess function

ΠA user or a Win32 process runs the RTSSkill utility

ΠA user terminates the process through the RTSS Task Manager

The process generates an exception


A Windows NT or Windows 2000 system shutdown occurs (either a normal shutdown
sequence or an exception-initiated Windows NT "blue screen" stop or Windows 2000 stop
screen)
RTSS processes can register shutdown handlers that are called when Windows is shut down
or stopped to allow the final sequencing of equipment and cleanup prior to full system stop
and possible reboot.

5
RTX User’s Guide

6
CHAPTER 2

Using Software Development Tools


This chapter discusses the RTX programs, utilities, drivers, files, and RTX control panel
settings that you work with when developing and testing your real-time programs. It contains
procedures for using Microsoft Visual Studio, by itself or with the RTX AppWizard, for
building RTSS images and dynamic link libraries. This chapter also contains instructions on
debugging your programs using Microsoft’s WinDbg and testing programs with shutdown
handlers.

This chapter contains information on:

n Using the RTX Utilities


Utility Task Table
RTSSrun Utility
RTSSkill Utility
RTSSview Utility
RTSS Task Manager
RTSS Object Viewer
RtxServer
n Using the RTX AppWizard in Microsoft Visual Studio 6.0
n Using Microsoft Visual Studio 6.0
n Creating Dynamic Link Libraries
n Debugging an RTX Program
n Testing an RTX Program with Shutdown Handlers
n Using the RTX Properties Contol Panel

7
RTX User’s Guide

Using the RTX Utilities


Utility Task Table

The table that follows shows which utility to use to perform a particular task.
,I\RXZDQWWR 8VH
5XQDQ5766SURFHVV 5766UXQ FRQVROHRUIURPWKH57;6WDUW
PHQX
/RDGDQ5766'// 5766UXQ FRQVROHRUIURPWKH57;6WDUW
PHQX
5HJLVWHUDQ57'// 5766UXQ FRQVROHRUIURPWKH57;6WDUW
PHQX
7HUPLQDWHDQ5766SURFHVV 5766NLOO FRQVROH
RU
57667DVN0DQDJHURQWKH57;6WDUW
PHQX
8QUHJLVWHUDQ57'// 5766NLOO FRQVROH
RU
57667DVN0DQDJHURQWKH57;6WDUW
PHQX
9LHZDOLVWRIDOOSURFHVVHVDQG 5766NLOO FRQVROH
UHJLVWHUHG57'//V RU
57667DVN0DQDJHURQWKH57;6WDUW
PHQX
9LHZLQIRUPDWLRQDERXW5766SURFHVVHV 5766YLHZ FRQVROH
DQGWKHLUDVVRFLDWHGREMHFWVLQFOXGLQJ RU
7KUHDG7LPHU6HPDSKRUH0XWH[ 57662EMHFW9LHZHURQWKH57;6WDUW
6KDUHGPHPRU\DQG/RDGHG57'// PHQX

8
Chapter 2: Using Software Developmen Tools

RTSSrun Utility (Console and GUI)

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 ]

To register an RTDLL: RTSSrun /d [/s] <filename>[.rtdll]

where

/q = Disables messages indicating success or failure to start the RTSS process.


/b = Runs the RTSS process early in the system boot sequence.
/d = Loads an RTDLL and adds entries to the registry.
/s = Allows an RTDLL to be loaded by several processes at the same time. Otherwise,
only threads within a single process can simultaneously load a particular RTDLL.
/t = Tests loading and unloading of RTDLLs. This switch must be used in conjunction
with the /d switch.
filename = Name of the file to be run.
arguments = Command line arguments passed to the process.

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

Special Mode Options


Run RTSS process — When running an RTSS process, you can elect to start the process
early in the system boot sequence by selecting Register to run at boot time, however RTX
must be set at boot time for this to take effect.

Register RTDLL — When registering an RTDLL, you can elect to:

Share Between Processes — Allows an RTDLL to be loaded by several processes at the


same time. Otherwise, only threads within a single process can simultaneously load a
particular RTDLL.
Perform Load\Unload Test — Performs test loading and unloading of RTDLLs.

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

To terminate process 001: RTSSkill 001

To unregister an ˆ ¯ DLL: RTSSkill myfile.rtdll

Format
To terminate a particular process: RTSSkill [/b] [process number]

To unregister an RTDLL: RTSSkill filename.rtdll

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.

Usage and Format


RTSSview /A (provides internal system processes and WIN32 proxy processes

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

RTSS Object Viewer

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.

File — Provides standard exit option.

Options — Provides extra display options:

Always On Top — Keeps the RTSS Object Viewer window on top.


Check All/Uncheck All — Causes all object to be displayed/removed from the list view.

View — Lets you specify how the information is displayed:

Refresh Now — Refreshes the Explorer view.


Refresh Rate — Lets you specify a Refresh Rate of high (one second), normal (two
seconds), low (five seconds), or Paused (turned off). The default is for automatic refresh to
be turned off.
Compact style — Allows for a more condensed view of object attributes. Object
attributes are displayed in one column instead of each attribute in its own column.
Select Columns — Allows you to select which columns to display and their order. This
option is not available if Compact style is selected.

Help — Provides information about RTSS Object Viewer:

Help Contents — Opens the help contents.


About RTSS Object Viewer — Opens a pop-up with copyright information.

14
Chapter 2: Using Software Developmen Tools

RTSS Task Manager

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

Buttons and Options


The RTSS Task Manager window contains the following buttons and options:

Always On Top — Keeps the RTSS Task Manager window on top.

Start Task — Starts up the RTSSrun graphical user interface.

End Task — Stops/unregisters the selected process or RTDLL.

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.

See the online help for additional information on using RtxServer.

16
Chapter 2: Using Software Developmen Tools

Using the RTX AppWizard in Microsoft Visual Studio 6.0


Use the RTX AppWizard in Microsoft Visual Studio 6.0 to create a project workspace for the
development of RTX applications and dynamic link libraries. The RTX project workspace
contains four configurations: Win32 Release, Win32 Debug, RTSS Release, and RTSS
Debug. The wizard sets the Project Settings for each configuration according to the program
and project options selected from its dialogs. It can also provide a basic C program
framework with which to work. This program framework can include RTX program
elements, which contain C code to create RTX objects and demonstrate their use.

The topic explains how to:

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

Creating a Project and Setting Options

Use the procedure that follows to create an RTX project using the RTXAppWizard in
Microsoft Visual Studio.

To create an RTX project


1. On the Visual Studio menu bar, select File | New.
2. On the Projects tab, select RTX AppWizard from the list box. The New dialog box
opens, as shown below.

57;$SS:L]DUG1HZ3URMHFWV'LDORJ%R[

3. On the right side of the dialog, complete the following fields:


Project name — Enter the name of the project.
Location — Enter the directory in which to build the workspace.

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.

Setting Project 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

Setting Program Options

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.

Run the RTSS image


5. Choose Build | Execute (or click the exclamation point on the toolbar).

20
Chapter 2: Using Software Developmen Tools

Registering an RTDLL

After you have built your RTDLL, you can register it using the RTSSrun utility.

Using Microsoft Visual Studio 6.0


This topic explains how to:

Set up Microsoft Visual Studio


Build and run Win32 images
Build and run RTSS images
ΠBuild and register RTDLLs

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.

Setting up Microsoft Visual Studio

Use the procedure that follows to direct Microsoft Visual Studio to the RTX include and
libraries files.

To set up Microsoft Visual Studio


1. On the Visual Studio Tools menu, choose Options and then choose the Directories
tab.
2. In the Show Directories For box, select the following file types and enter their paths
in the Directories box. The following assumes that it was installed with the default
paths. If you changed the default path during installation, specify that path below.
Include files — c:\program files\vci\rtxsdk\include
Library files — c:\program files\vci\rtxsdk\lib
3. Click OK to save the settings.
Building and Running Images (Win32 Environment)

Use the procedures that follow to build and run a Win32 image.

To build a Win32 image


Create a new RTX Win32 project workspace
1. On the File menu, choose New and then choose the Projects tab.
2. Choose Win32 Console Application, enter a name, and then click OK.
Specify the project settings

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).

Building and Running Images (RTSS Environment)

Use the procedures that follow to build and run an RTSS image.

To build an RTSS image


Create a new RTX RTSS project workspace
1. On the File menu, choose New and then choose the Projects tab.
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.
1R&5XQ7LPH6XSSRUW5HOHDVH
Versionrtapi_rtss.lib rtx_rtss.lib
/NODEFAULTLIB /INCREMENTAL:NO /PDB:NONE /NOLOGO
/driver /align:0x20 /subsystem:native,4.00
/RELEASE /entry:_RtapiProcessEntry@8

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

/driver /align:0x20 /subsystem:native,4.00


/debug:notmapped /debugtype:both
/entry:_RtapiProcessEntryCRT@8

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).

To run an RTSS image in Visual Studio


Use the procedure that follows to run the image from within Visual Studio.
Specify the project settings
1. On the Project menu, choose Settings to open the Project Settings dialog box, and
then choose the Debug tab.
2. Complete the following fields:
Settings For — Select either Win32 Release or Win32 Debug, based on the version
you plan to run.
Executable for Debug Session — Enter the path to RTSSrun.exe. For example:
c:\program files\vci\rtx\bin\rtssrun.exe
Program Arguments — Enter the path to your .rtss image. For example: c:\program
files\microsoft visual studio\myprojects\rtsstest\release\rtsstest.rtss
3. Click OK to save the settings.
Run the RTSS image
4. On the Build menu, choose Execute RTSSrun.exe.
Building and Registering RTDLLs

Use the procedures that follow to build and register an RTDLL.


To build an RTDLL
Create a new project workspace
1. On the File menu, choose New and then choose the Projects tab.

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

Creating RTX Dynamic Link Libraries


This topic explains how to:
Build an RTDLL — This type of real-time dynamic link library is an RTSS object which
can be dynamically loaded and unloaded using the LoadLibrary and FreeLibrary calls.
Build an RTSS DLL — This type of real-time dynamic link library is an RTX process that
can be loaded either at boot time or through a call to Windows NT or Windows 2000 from
within a C/C++ program.
For further details about the two types of real-time DLLs, see Using RTX Dynamic Link
Libraries on page 57.

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.

Building an RTDLL through command line invocation


The following is an example of an nmake input file which will build an RTDLL and Win32
DLL from a single source file, thandler.c.

!include <rtx.mak>
all: thandler.dll thankler.rtdll
clean:
-del thandler.obj thandler.dll thandler.rtdll

Building an RTSS DLL

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).

dll.c — Defines the source call for the library


dll.def — Defines the DLL name and exported functions
Once executed in the RTSS environment, RTSS programs can use the RTSS DLL. Note that
the entry point into the RTSS DLL for starting the process is MAIN.

RTSS DLL Makefile Example


The following example shows a typical RTSS DLL makefile for dll.c.

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.

This topic explains how to:

Exclude debugging information from a release version


Use Microsoft’s WinDbg 4.0 with RTSS
Œ Use Microsoft’s WinDbg 5.0 with RTSS

Excluding debugging information

You can exclude full debugging information from your release version by using the
procedure that follows.

To exclude debugging information from release version files


At a command prompt, enter:
Set NODEBUG=1
nmake -nologo -f MyProgram.mak
or
Add NODEBUG=1 to MyProgram.mak (as illustrated in the Makefile Sample for
srtm.mak in Code and File Examples)

Using Microsoft’s WinDbg 4.0 with RTSS


In order to debug using Microsoft’s WinDbg 4.0, you need two systems: a host system on
which to run WinDbg and a target system on which to run your driver. WinDbg 4.0 can
debug Windows NT systems only. The procedures that follow show how to:

Prepare the host and target systems for WinDbg


Prepare the program for debugging
Set up the WinDbg environment on the host system
ΠStart the debug session

26
Chapter 2: Using Software Developmen Tools

To prepare the host and target systems for WinDbg


Connect the host system to the target system
1. Connect the two systems by inserting a null modem cable into the corresponding
serial ports on each (COM1 or COM2).
2. Test the connection using an available serial communications package (such as
terminal.exe) to ensure that data is transmitted and received on both sides. For more
information on null modem cables and testing a serial connection, refer to the section
on using a serial cable for kernel debugging in the Microsoft Windows NT DDK
documentation.
Set up the target system
3. Ensure that the target system has free builds of Windows NT and RTSS installed. If
any of one of these is not installed on the target, install it according to its installation
instructions.
Modify the boot.ini file to enable kernel debugging
4. Change the attributes of boot.ini to permit editing.
5. Open the file in an editor and locate the line under the "[operating systems]" section
that contains the operating system on which you run. Modify this line to contain one
of the following lines of information:
/DEBUG [ /BAUDRATE=<baud rate> ]
/DEBUGPORT=<com port> [ /BAUDRATE=<baud rate> ]
where com port = Serial port through which the host and target are connected. baud
rate = Highest rate used by the machines.
Note: Using /DEBUG assumes that the default serial port is COM2. Using
/DEBUGPORT allows you to specify which serial port to use. If baud rate is not
given, the system uses a default rate. For example, the line "multi (0) disk (0) rdisk
(0) partition(1) \WINNT="Windows NT Version 4.00" /DEBUGPORT=COM2"
/BAUDRATE=19200" sets the communications port to COM2 and the baud rate to
19200. For more information on using these switches, refer to the section on
enabling kernel debugging on the target in the Microsoft Windows NT DDK
documentation.
6. Save the file and exit the editor.
7. Reset the file attributes in boot.ini to their original states: > attrib +r +s +h boot.ini
8. Reboot the target system.
To prepare the program for debugging
1. At the start of the source code, insert a hard break instruction: _asm int 3

2. To include debug information in the program, perform one of these steps:

3. In the program’s makefile, comment the line NODEBUG=1 (if it is there).

4. At a command prompt, enter: Set NODEBUG=

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.

9. RTX debug information files in %SystemRoot%\symbols\ rtx_halext.dbg in


SystemRoot%\symbols\ rtx_rtss.dbg in %SystemRoot%\symbols\ hal.dbg in
%SystemRoot%\symbols\

To set up the WinDbg 4.0 environment on the host system


1. On the Start menu, choose Programs | Win32 SDK Tools | WinDbg.
2. On the File menu, open the program’s source file.
3. On the View | Options tab, set the following options.
Workspace Tab — Set the Logging option, if desired.
Symbols Tab — In the Symbol Search Path text box, enter the location of the .rtss
file (this is required only if the file is not in the %SystemRoot%\symbols
directory). In the Load Time box, select the Defer radio button.
Kernel Debugger Tab — Select the Enable Kernel Debugger check box. Under
Communications, ensure that the values for Baud, Port, Cache, and Platform are
correct.
Debugger Tab — Select the desired Radix and Registers settings and other desired
options. This set of options is recommended: Ignore Case, Disconnect on Exit, Go
on Thread Terminate, Debug Child Process, Verbose Output, and Abbreviated
Context.
4. Click OK to save the options.
To start the debug session
1. On the host Run menu, choose Go (or press F5).
2. On the target system, run the application. For example, at a command prompt, enter:
> RTSSrun srtm
The following message appears in the WinDbg command window.
Thread Create: Process 0 Thread 0
Kernel debugger waiting to connect on com2 @ 19200 baud
Kernel Debugger connection established on com2 @ 19200 baud
Kernel Version 1381 Free loaded @ 0x80100000
Module load: NT (symbols loaded)
Hard coded breakpoint hit
3. At this point, the target system will not respond until WinDbg receives a "GO"
command. Add breakpoints, as desired.
4. To continue the debugging session, choose Go on the Run menu (or press F5). Refer
to the Microsoft WinDbg documentation for details on using WinDbg.

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.

Testing an RTX Program with Shutdown Handlers


This topic describes the:

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.

Note: The message is visible only for unexpected NT stops (RT_SHUTDOWN_NT_STOP).


For an orderly NT shutdown (RT_SHUTDOWN_NT_SYSTEM_SHUTDOWN), the
message is not visible.

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

Use the gencrash driver to see a demonstration of RTSS shutdown management.

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.

Using the RTX Properties Contol Panel


You use the RTX Properties control panel to set configurable RTX registry parameters. It
contains four tabs: About, Settings, Debug, and Control.

To set RTX properties


1. In the system Control Panel, double-click the RTX Settings icon to open the RTX
Properties control panel.

2. Specify the settings on each tab (see below) and then click Apply.

3. When finished, reboot your system to apply the change(s).

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

Process Exception Disposition — Controls the disposition of faulting RTSS processes.


When Freeze the Faulting Process is selected, you can debug the process and then unload it
using RTSSkill.

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.

Kernel Debugger — Specifies which debugger is used, Microsoft's WinDbg or NuMega's


SoftICE. See Debugging an RTX Program on page 26.

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.

This chapter contains:

n Process and Thread Management


Processes and Threads
System Memory Management
Clocks and Timers
n Interprocess Communication
Object Names
Shared Memory
Semaphores
Event Objects
Mutex Objects
n Device Management
Interrupts
Port IO
Physical Memory Mapping
Contiguous Memory Mapping
Bus IO
n File IO

33
RTX User’s Guide

Process and Thread Management


Processes and Threads

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.

This topic discusses:

Using_Processes
Using_Threads
ΠThread_Priorities

Using Processes
The sections that follow describe how processes run in the RTSS and Win32 environments.

Processes in the RTSS Environment


A process running in the RTSS environment consists of a set of handles to objects, process
address space, at least one thread, and an executable. When a process is created, RTSS
performs the following tasks:

Loads the executable as a driver


Allocates process heap from the non-paged pool
ΠCreates the primary thread

A process can be started by either one of these methods:

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

A process exits under one of these conditions:

The last thread has exited


One thread calls ExitProcess
ΠThe process is killed with the RTSSkill utility or the RTSS Task Manager

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).

Processes in the Win32 Environment


A process running in the Win32 environment starts interacting with RTX when it makes an

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:

Waits for a synchronization object


Lowers its own priority or raises another thread’s priority
Suspends itself
Returns from the timer or interrupt handler (applicable to timer and interrupt threads) routines
Calls Sleep with an argument of 0
Recevives a notification that a time quantum is set
ΠIs interrupted by a higher priority

The initial thread of a process has an 8 KB stack.

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.

Table 1. RTSS to Win32 Thread Priority Mapping


57666\PEROLF3ULRULW\ 5766 :LQGRZV17:LQGRZV :LQ
1DPH 9DOXH 6\PEROLF3ULRULW\1DPHIRU5HDO 9DOXH
7LPH3ULRULW\&ODVV
57B35,25,7<B0,1  7+5($'B35,25,7<B,'/( 
57B35,25,7<B0,1  7+5($'B35,25,7<B/2:(67 
57B35,25,7<B0,1  7+5($'B35,25,7<B%(/2:B1250$/ 
57B35,25,7<B0,1  7+5($'B35,25,7<B1250$/ 
57B35,25,7<B0,1  7+5($'B35,25,7<B$%29(B1250$/ 
57B35,25,7<B0,1  7+5($'B35,25,7<B+,*+(67 
57B35,25,7<B0$;  7+5($'B35,25,7<B7,0(B&5,7,&$/ 

Table 1 shows, for example, that RtSetThreadPriority(Thread, RT_PRIORITY_MIN+1)


will result in a call to SetThreadPriority(Thread, THREAD_PRIORITY_LOWEST) by the
Win32 version of the RTX interfaces.
Any value from RT_PRIORITY_MIN+5 to RT_PRIORITY_MIN+126 will set the thread at
THREAD_PRIORITY_HIGHEST and RT_PRIORITY_MAX will result in
THREAD_PRIORITY_TIME_CRITICAL priority. These mappings are fixed and designed
to preserve relative ordering among thread priorities.

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.

Table 2. Win32 to RTSS Thread Priority Mapping


:LQGRZV17:LQGRZV 9DOXH 57666\PEROLF 9DOXH
6\PEROLF3ULRULW\1DPHIRU5HDO 3ULRULW\1DPH
7LPH3ULRULW\&ODVV
7+5($'B35,25,7<B,'/(  57B35,25,7<B0,1 
7+5($'B35,25,7<B/2:(67  57B35,25,7<B0,1 
7+5($'B35,25,7<B%(/2:B1250$/  57B35,25,7<B0,1 
7+5($'B35,25,7<B1250$/  57B35,25,7<B0,1 
7+5($'B35,25,7<B$%29(B1250$/  57B35,25,7<B0,1 
7+5($'B35,25,7<B+,*+(67  57B35,25,7<B0,1 
7+5($'B35,25,7<B7,0(B&5,7,&$/  57B35,25,7<B0$; 

There are no additional priorities between THREAD_PRIORITY_IDLE and


THREAD_PRIORITY_HIGHEST. If you need finer grain priorities, you should use the
RTSS priority spectrum instead. Just as in Win32, this value specifies a thread priority that is
higher than all other priorities.

Win32 Environment Programming Considerations


WIn32 RTX program starts execution in the normal priority class, then calls the first
RtGetThreadPriority, RtSetThreadPriority, or any other real-time priority function. This is the
desired behavior for most applications because it gives the process the best possible real-time
performance. This does, however, cause problems when the Win32 threads have GUI
components. When a thread in the REALTIME_PRIORITY_CLASS interacts with the GUI
side of Windows NT and Windows 2000, slowdowns and lock-ups occur. You can avoid this
problem when writing a Win32 application that has a GUI component (and links to
rtapi_win32.lib), by making sure that your program first makes this call:
SetPriorityClass( GetCurrentProcess(), NORMAL_PRIORITY_CLASS)

System Memory Management

This topic discusses:

System memory allocation


ΠSystem memory locking

System Memory Allocation


A process frequently must allocate additional memory to perform its operations. The RTX
memory allocation routine always allocates memory that is locked, thus eliminating any
chance of latencies due to page faults.

Memory Allocation APIs

37
RTX User’s Guide

The following APIs are available to access RTX system memory allocation services:

RtAllocateLockedMemory allocates memory that is backed by physical memory and


locked, then maps the memory into the virtual address space of the process.
RtFreeLockedMemory frees a previously allocated locked memory region.

RTSS and Win32 Programming Considerations


Locked memory is always allocated from a non-paged pool of memory that is 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.

Programming Example (RTX Locked Memory Allocation Calls)


See the RTX Locked Memory Allocation Calls Programming Example in Code and File
Examples in Appendix A. It demonstrates the use of RTX locked memory allocation calls.

System Memory Locking


To prevent page faults, and hence unpredictable delays in critical sections of code, real-time
applications need to lock data and code in memory, including code and data in the operating
system itself.

Process Locking APIs


The following APIs are available to access RTX process memory locking services:

RtLockProcess locks all pageable sections of a process into physical memory.


RtUnlockProcess unlocks sections of a process’s virtual address space previously locked
into physical memory.
RtCommitLockProcessHeap commits and locks the process’s heap.
RtCommitLockHeap commits and locks the specified heap.
RtCommitLockStack commits and locks the specified stack.

RTSS Environment Programming Considerations


By default, all process and memory objects in the RTSS environment are locked into physical
memory to avoid page faults in RTSS processes. The Rt*Lock (Process, Heap, Stack)
functions will always complete with success in the RTSS environment but will perform no
actual operations.

Win32 Environment Programming Considerations


Unless explicitly locked into physical memory, all Windows NT and Windows 2000
processes and services are paged. In the Win32 environment, the RtLockProcess function
should be utilized to prevent your real-time process from incurring page faults.

38
Chapter 3: Using Using the RTX Functionality

Programming Example (RTX Process Memory Locking Calls)

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.

Kernel Locking APIs


The following APIs are available to access RTX kernel memory locking services:

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.

RTSS Environment Programming Considerations


By default, all processes and memory objects in the RTSS environment are locked into
physical memory.

Win32 Environment Programming Considerations


Certain Windows NT operating system components are paged, including most of the kernel
and the Win32 subsystem. In order to prevent delays of your real-time processes due to
kernel page faults, use the RtLockKernel function.

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.

Programming Example (RTX Kernel Memory Locking Calls)


See the RTX Kernel Memory Locking Calls Programming Example in Code and File
Examples in Appendix A. It demonstrates the use of RTX kernel memory locking calls.

See Also
Contiguous Memory Management

39
RTX User’s Guide

Clocks and Timers

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.

This topic discusses:

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:

RtGetClockTime delivers the current value of the specified clock.


RtSetClockTime sets the value of the specified clock.
RtGetClockResolution delivers the resolution of the specified clock.
RtGetClockTimerPeriod delivers the minimum timer period for the specified clock.
The clock values are delivered and set in 100ns units (ticks) and are reported as the number of
ticks since 12:00 AM January 1, 1601.

Clock Types
The RTX clocks, available in the Win32 and RTSS environments, are:

CLOCK_1 (alias CLOCK_SYSTEM) — CLOCK_1 services are provided by the real-time


HAL extension and have a resolution of 1 ms. Threads in both the Win32 and RTSS
environments may schedule timers with periods in increments of ´ ms on this clock.

CLOCK_2 (alias CLOCK_FASTEST) — CLOCK_2 services are provided by the real-time


HAL extension and have a resolution of 1 µS. The period for timers scheduled on this clock
is variable and can be set to 100, 200, 500, or 1000 µS.

You can set the HAL extension timer period using the RTX Settings control panel.

Relationship to Win32 Clocks


The RTX clocks are updated by services provided in the real-time HAL extension. The RTX
clocks are synchronized with the RTX timer services. However, the RTX clocks are not
synchronized with either the Windows NT or Windows 2000 system clock or the battery-
backed time-of-day clock.

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.

6SHFLILHG7LPHU $FWXDO7LPHU3HULRG :LQGRZV17 57;&ORFN'ULIW


3HULRG :LQGRZV
&ORFN'ULIW
—6 —6  
—6 —6  
—6 —6  
—6 —6  

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:

RtCreateTimer creates a timer associated with a specified clock.

41
RTX User’s Guide

RtDeleteTimer deletes a previously created timer.


RtCancelTimer cancels the expiration of the specified timer.
RtSetTimer sets the absolute expiration time and repeat interval of the specified timer.
RtSetTimerRelative sets the relative expiration time and repeat interval of the specified
timer.
Relationship to Windows NT Timers
RTX timers are not synchronization objects which means threads cannot wait for single
objects with an RTX timer handle. This is in contrast to the Windows NT waitable timer,
which is an object on which a thread can wait, or against which a thread can receive
notification.

Win32 and RTSS Programming Considerations


If your application needs to inform other threads of a timer expiration, you should use the
appropriate notification object in the handling routine to indicate the event.

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.

Programming Example (RTX Timer and Sleep Calls)


See RTX Timer and Sleep Calls Programming Example in Code and File Examples in
Appendix A. It demonstrates the use of RTX timer and sleep calls.

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:

The memory region is returned to the pool of non-paged kernel memory.


ΠThe object ceases to exist.

Inter-Process Communication via Shared Memory


RTSS shared memory objects allow you to share blocks of data among multiple processes,
including RTSS processes and Win32 processes. To do this, a thread in each process must
have its own process-relative handle to a single RTSS shared memory object and its own
process-relative pointer to a location where the virtual address of the mapping will be stored.
These handles and pointers can be obtained by calling either RtCreateSharedMemory or
RtOpenSharedMemory.

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.

RtCreateSharedMemory fails if the amount of memory requested cannot be allocated or if


the named shared memory object already exists. When RtCreateSharedMemory fails, no
memory is mapped and no handles are returned. RtCreateSharedMemory does not default
to RtOpenSharedMemory if a shared memory object of the same name already exists. Only
one process can successfully create the shared memory object.

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

Will never return WAIT_ABANDONED


ΠMay lose semaphore resources if threads are terminating

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.

Inter-Process Communication via Semaphores


To synchronize threads running in multiple processes, including RTSS processes and Win32
processes, a thread in each process must have its own process-relative handle to a single
RTSS semaphore object. These handles can be obtained by calling either
RtCreateSemaphore or RtOpenSemaphore.

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.

A thread can determine whether RtCreateSemaphore actually created a new RTSS


semaphore object by calling GetLastError immediately after the call to
RtCreateSemaphore. If GetLastError reports ERROR_ALREADY_EXISTS, a new RTSS
semaphore object was not created.

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.

Inter-Process Communication via Mutex Objects


To synchronize threads running in multiple processes, including RTSS processes and Win32
processes, a thread in each process must have its own process-relative handle to a single
RTSS mutex object. These handles can be obtained by calling either RtCreateMutex or
RtOpenMutex.
Using RtCreateMutex
The first and most common way is for one thread in each process to call RtCreateMutex,
passing the identical string for the parameter of RTSS mutex name. The first thread to call
RtCreateMutex will cause the system to create the RTSS mutex object. As additional
threads call RtCreateMutex, the system determines that an RTSS mutex with the specified
name already exists; as a result, it does not create a new RTSS mutex object but returns a
process-relative handle identifying the existing RTSS mutex object.

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.

Win32 and RTSS processes can attach to an interrupt handler using


RtAttachInterruptVector. The priority assigned to the interrupt handler thread determines
the priority execution order of the interrupt handler in both the RTSS and Win32
environments.

When an interrupt handler is attached to a particular interrupt, a thread is created which


responds to the interrupt. This handling thread is analogous to an Interrupt Service Thread
(IST). When the interrupt occurs, the interrupt source is masked; the interrupt’s thread is
resumed; and, if its priority is greater than the priority of the currently executing thread, it
becomes the currently executing thread. After the interrupt handler returns, the interrupt
source is unmasked and the thread is suspended.

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:

0-117, 118, 119, ...127

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:

RtAttachInterruptVector attaches an IST to a specified interrupt.


RtAttachInterruptVectorEx can attach an IST and/or an Interrupt Service Routine (ISR)
to a specified interrupt. You can also share interrupts exclusively attached within either the
RTSS or Win32 environments (but not both) with this call.
RtReleaseInterruptVector releases an interrupt previously attached with
RtAttachInterruptVector or RtAttachInterruptVectorEx.
RtDisableInterrupts under the Win32 environment disables interrupt handling for all
interrupts attached to a process. In the RTSS environment, all interrupts are disabled at the

48
Chapter 3: Using Using the RTX Functionality

processor level.
RtEnableInterrupts enables all interrupts disabled by RtDisableInterrupts.

General Programming Considerations


As with any thread, an interrupt thread can be preempted at any time by a thread that runs at a
higher thread priority level.
Time slicing effects the execution of ISTs if there is a time quantum set for the IST.
ΠInterrupt processing can be disabled for the set of interrupts attached to the RTX process
by raising the thread priority level of the currently executing thread. The level must be
higher than all of the thread priority levels specified for the RTSS Interrupt Service
Threads. An interrupt handler that signals an object may satisfy the wait conditions of a
higher priority thread. Resuming the higher priority thread will delay the completion of
the interrupt handler and delay the time at which the interrupt source will be unmasked.
High priority threads never mask timer interrupts; thus, the timer interrupt is effectively
the highest priority interrupt. To mask timer interrupts, use RtDisableInterrupts.

Win32 Environment Programming Considerations


All processing in the RTSS environment takes priority over all processing in the Win32
environment. Therefore, any time-critical interrupt processing that must be accomplished
should be done with a handler running an RTSS process, rather than a Win32 process. In the
Win32 environment, the Windows NT and Windows 2000 schedulers service RTX interrupt
threads. This can lead to non-deterministic scheduling latencies for the handling thread to
receive and process the interrupt.

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.

Programming Example (Interrupt Management and Port I/O Calls)


See the Interrupt Management and Port I/O Calls Programming Example in Code and File
Examples. It demonstrates the use of RTX interrupt management and port I/O calls.

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.

Port I/O Control APIs


The following APIs are available to access Port I/O control services:

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)

Port I/O Data Transfer APIs


The following APIs are available to access Port I/O data transfer services:

RtReadPortUchar,RtReadPortUshort,RtReadPortUlong directly reads a one-, two-, or


four-byte datum from the specified I/O port.
RtWritePortUchar,RtWritePortUshort,RtWritePortUlong directly writes a one-, two-,
or four-byte datum to the specified I/O port.
RtReadPortBufferUchar,RtReadPortBufferUshort,RtReadPortBufferUlong copies a
series of one-, two-, or four-byte datum from the specified I/O port to a buffer.
RtWritePortBufferUchar,RtWritePortBufferUshort,RtWritePortBufferUlong copies
a one-, two-, or four-byte datum from the specified I/O port to a buffer.

General Programming Considerations


The RTX interfaces are coded in assembly and use the __stdcall convention, indicating that
the subroutines handle the stack cleanup. You should not use other calling conventions.

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.

Physical Memory Mapping

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.

General Programming Considerations


There are no restrictions or protections on the mapped memory region. The mapping will
provide precisely the base address and length specified, if successful. You should take care
not to map in and modify Windows NT or Windows 2000 address space as this may lead to
corruption of either operating system.

Win32 Environment Programming Considerations


Accesses beyond the address range allocated in the mapping will result in an exception.

Programming Example (RTX Memory Mapping Calls)


See the RTX Memory Mapping Calls Programming Example in Code and File Examples in
Appendix A.

Contiguous Memory Mapping

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.

The RtAllocateContiguousMemory and RtGetPhysicalAddress functions are used to


allocate physically contiguous memory and to translate the virtual address of the memory to a
physical address, respectively.

APIs

The following APIs are available to access RTX contiguous memory allocation services:

RtAllocateContiguousMemory allocates a physically contiguous memory address range


and maps that memory into the process’ virtual address space.
RtFreeContiguousMemory frees a previously allocated physically contiguous memory
region.
RtGetPhysicalAddress returns the physical address for the virtual address of a previously
allocated physically contiguous memory region.

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

In the Win32 environment, RtGetPhysicalAddress operates only with addresses returned by


RtAllocateContiguousMemory.

Programming Example (RTX Contiguous Memory Allocation Calls)


See the RTX Contiguous Memory Allocation Calls Programming Example in Code and File
Examples in Appendix A. It demonstrates the use of RTX contiguous memory allocation
calls.

Bus IO

RtGetBusDataByOffset, RtTranslateBusAddress, and RtSetBusDataByOffset facilitate


the development of RTSS hardware drivers. Each function eases the gathering of specific
hardware information and/or setting hardware.

RtGetBusDataByOffset is used primarily in support of attaching a driver to a hardware


device by obtaining device information required for input to RtAttachInterruptVector, such
as the bus number, interrupt level, and interrupt vector. For example, by issuing a call to
RtGetBusDataByOffset, a PCI bus can be scanned, detect a particular device, and then
return the bus number where the device resides, the bus interrupt level, and interrupt vector.

For further information, see RtAttachInterruptVector and RtAttachInterruptVectorEx in


the RTX 5.0 Reference Guide.

Setting hardware is accomplished with a call to RtSetBusDataByOffset. This function is


useful when device initialization requires clearing or setting of status registers, slot, and so
on.

RtTranslateBusAddress is used to translate a device-specific memory address range into the


logical address space of a driver.

Programming Example (Bus I/O)


See the Bus I/O Programming Example in Code and File Examples in Appendix A. The code
fragment illustrates each of the Bus I/O calls in a PCI driver.

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:

c:\temp\MyFile.txt (for a file system object)

53
RTX User’s Guide

\\.\MyDevice0 (for a device object)

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.

This chapter contains information on:

Using the RTX Makefile


Using RTX Dynamic Link Libraries
Using the C Run-time Library Functions
Using Floating Point
Writing RTSS Device Drivers
C++ and Structured Exception Handling
System Exception Handling
About System Exception Handling
RTX Handler
Tables of Exceptions
RTX Exception Handling
About RTX and Windows NT / WIndows 2000 Stop Messages
Interpreting Windows NT Blue Screen Stop Messages
Interpreting RTX Green Screen Stop Messages
Starvation Management
Power Management

55
RTX User’s Guide

Using the RTX Makefile


You can use the RTX master makefile (rtx.mak) to build both RTSS and Win32 versions of a
particular program. Rtx.mak contains rules to compile C files and link the resulting objects.
You can specify Win32 executable (.exe) files in a makefile using rtx.mak because rtx.mak
includes win32.mak.

Variables

The master makefile uses the following variables:

NODEBUG — Calls the link using the /RELEASE option.


RTSS_CRT — Includes the RTSS C run-time library for single-threaded applications in
the final link of the RTSS executable.
RTSS_MTCRT — Includes the RTSS C run-time library for multi-threaded applications
in the final link of the RTSS executable.
USER_LIBS — Additional user-specified libraries that will be included in the link stage.
RTSS_OBJS, RTDLL_OBJS — List of object files linked by rtss link or rtdll link
makefile rules, respectively.
Sample Makefile

See the Makefile Sample in Code and File Examples in Appendix A.

56
Chapter 4: Developing an Application

Using RTX Dynamic Link Libraries


This topic provides:

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.

About RTSS DLLs and RTDLLs

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.

RTSS DLL and RTDLL Code Examples


See RTSS DLL Code Example and RTDLL Code Example in Code and File Examples in
Appendix A.

58
Chapter 4: Developing an Application

Using the C Run-time Library Functions


RTX provides support for C run-time library functions. The RTX-supplied C run-time
libraries are based on the Microsoft Visual C++, C run-time libraries. The RTX libraries,
named RTXlibc.lib and RTXlibcmt.lib (indicating single and multi-threaded libraries),
provide improvements to the efficiency of memory allocation (malloc). Other than this
improvement, they do not differ substantially from the Microsoft libraries.

For a list of available functions, see the C Run-Time API List in the RTX 5.0 Reference Guide.

Using Floating Point


Threads that run in the RTSS environment always run in kernel mode. Whereas the Windows
NT and Windows 2000 kernel does not support floating-point operations in kernel-mode code
(such code causes the system to crash), RTX allows RTSS threads to use the Floating-Point
Unit (FPU) to perform floating-point operations.

Enabling Floating-Point Support in RTSS Programs

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.

Running RTSS Programs Using Floating-Point

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.

Writing RTSS Device Drivers


RTX provides a number of features that enable you to quickly and easily develop device
drivers. The RTX device driver model is simpler than that of Windows NT and gives you
greater flexibility in design. Because Windows NT and Windows 2000 device drivers are
often user-mode drivers and rely on user-mode Windows NT and Windows 2000 services,
they cannot be used "as-is" with RTSS applications. Furthermore, since even kernel-mode
drivers are often accessed through user-mode libraries supplied by hardware vendors, it is
generally not possible to access standard Windows NT and Windows 2000 device drivers
from within an RTSS application.

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++ and Structured Exception Handling


RTX supports Microsoft C++ exceptions (catch/throw), Win32 Structured Exception
Handling (SEH) API, and C frame-based exception handling (try/except/finally), all as
defined by the Win32 Platform SDK.

This topic discusses:

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.

Structured Exception Handling

RTSS supports Structured Exception Handling and C++ exceptions, as described by the
Win32 Platform SDK, including:

Win32 Structured Exception Handling calls, which include RaiseException,


SetUnhandledExceptionHandler, UnhandledExceptionFilter, AbnormalTermination,
GetExceptionCode, GetExceptionInformation
Frame-based exception handlers: try-except and try-finally.
C++ exception handling: try-catch.
ΠHandling for the following software exceptions in RTSS:

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.

Differences Between Win32 and RTSS Exception Handling


The RTSS implementation follows Win32 SEH semantics where possible. This section
describes the differences.

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.

Exception caused by a thread


When a thread of a multithreaded application causes an exception in Win32, the system
displays a dialog box. Until the user responds to the box, other threads of the application
continue running. Once the user has responded, all threads of the application terminate.

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.

Nested exceptions and collided unwinds


RTSS follows Win32 rules for nested exceptions and "collided" unwinds, with a few minor
differences:

Non-continuable exceptions — Non-continuable exceptions caused by the program


directly or by exception handling run-time itself. Win32 repeatedly re-asserts those; but
repeated re-assertion of exceptions consumes stack space. A stack fault in RTSS causes a
system shutdown (the "green screen"), so for robustness, RTSS terminates a process that
has generated a non-continuable exception.
Hardware exceptions — RTSS exception codes for hardware exceptions are tied to
Pentium interrupt codes, thus differing from Win32 exception codes caused by similar
errors.
For example, an errant Win32 application gets an EXCEPTION_ACCESS_VIOLATION

61
RTX User’s Guide

as defined by Win32, an RTSS application gets EXCEPTION_PAGE_FAULT as


described in the RTX Reference Guide. A Win32
EXCEPTION_ILLEGAL_INSTRUCTION is equivalent to the RTSS
EXCEPTION_INVALID_OPCODE.
Reads/writes of address 0 — Win32 explicitly guarantees that the first 64K of a user
process's address space is unmapped, so any access of that area causes an exception.
However, Windows NT and Windows 2000 occasionally make this area valid for kernel
processes and device drivers (and, therefore, for RTSS). This means that a write to/read
from address 0 from an RTSS process may occasionally succeed, rather than cause an
exception.

Debugging
For debugging, see the Debug tab in the RTX Properties control panel.

General User Notes for Exception Handling

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.

System Exception Handling


About System Exception Handling

An exception is a forced transition from normal program execution to a specialized


procedure, called a handler, which processes the exception. An exception is raised (occurs)
when the CPU encounters an error condition during program execution. Each exception is
assigned an error code or vector number. For example, if the CPU encounters a divide by 0,
exception 0 is raised. For a complete discussion of exception handling, see Volume 3:
Architecture and Programming of the Pentium® Processor Family Developer's Manual.

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:

Freezes and/or terminates the process

62
Chapter 4: Developing an Application

Modifies the application environment and continues


ΠExecutes an orderly shutdown, known as a "Green Screen"

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

This topic contains tables of the following types of exceptions:

RTX exceptions
ΠIntel exceptions

RTX Exception Codes


The table that follows lists the exception name, the vector number or error code, and the
exception handler response.

([FHSWLRQ (UURU&RGH 57;ZLOO


(;&(37,21B13;B127B$9$,/$%/( ; $OORZIRUIORDWLQJSRLQW
FDSDELOLW\DQGFRQWLQXH
H[HFXWLQJWKHDSSOLFDWLRQ
(;&(37,21B,17 [ (QWHUWKHGHEXJJHU,IQR
GHEXJJHULVSUHVHQW57;IUHH]HV
WKHSURFHVV
(;&(37,21B10, [ ,VVXHD*UHHQ6FUHHQVWRS
(;&(37,21B'28%/(B)$8/7 [ PHVVDJH
(;&(37,21B5(6(59('B75$3 [)
(;&(37,21B,19$/,'B766 [$

Intel Exception Codes


Following Win32 behavior, RTSS maps the Intel (x86) exception code to the Win32 one, and
then invokes Structured Exception Handling. RTX will alert the user via a popup message,
make an entry to the event log, and freeze or terminate the thread and associated process.

[([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

RTX Exception Handling

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

The sections that follow describe each of these tasks.

Freeze or Terminate Processing


The ExceptionDisposition registry flag, settable from the RTX Properties Control Panel,
controls the disposition of faulting RTSS processes. Possible values are:

0 = Terminates processing (default)


1 = Freezes the thread and processing

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:

RTX Exception - Memory Access Fault at loc FEBEB229


(Proc=80452448, Thread=804526F8)
Process image has been * unloaded *

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:

RTX Exception - Memory Access Fault at loc FEBDF229


(Proc=80452448, Thread=804526F8)
Process image has been * frozen *
Debug and/or use "RTSSkill" command to unload all processes

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

Generate Event Log Entries


The event log message includes an information entry, which is the text portion of the popup
window, and an error entry that provides details about the error. The error entry contains two
parts: a description and binary detail. The binary detail consists of 10 dwords of message data
and 3 dwords of RTSS fault data, as illustrated in the sample that follows.

The description for Event ID (12) in Source (Rtx_rtss)


could not be found. It contains the following
insertion string(s):
\Device\Rtx_rtss, RTX Exception - Memory Access Fault
0000: 00100000 00620002 00000000 c004000c
0010: 00000000 c0000183 00000000 00000000
0020: 00000000 00000000 feac12e8 febdf229
0030: 80452448 804526f8

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:

Instruction pointer value (febdf229 in the sample)


RTSS process identification (80452448 in the sample)
ΠRTSS thread identification (804526f8 in the sample)

Caution: To preserve event log information, do not filter event entries.

About RTX and Windows NT / Windows 2000 Stop Messages

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.

To enable stop messages


1. In the Windows NT Control Panel, double click the System icon and then open the
Startup/Shutdown tab.
2. In the Recovery section, deselect the Automatically Reboot option.
Note: You should select the Automatically Reboot option only if you want to disable
stop messages and have the system reboot automatically when there is a system
failure.
Click OK to save the settings.

65
RTX User’s Guide

Interpreting Windows NT Blue Screen Stop Messages

When a non-recoverable exception occurs within a native Windows NT application,


Windows NT initiates a Blue Screen. The Windows NT Blue Screen contains four sections of
data, with the most important information contained in the first two lines. These two lines
contain the stop error code, its four parameters, and the text of the stop error message. You
should always record the first few lines, along with the driver list (in the second Blue Screen
section), before rebooting the computer. With this data, you can often diagnose the source of
a stop condition.

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.

Section 1 - Stop Message


The Stop Message section provides the bugcheck data in the form:

***STOP: #E(#1, #2, #3, #4)


Text interpretation of the error

where
#E = Actual error code.
#1 - #4 = Additional parameters relating to the error.
Text = Best effort interpretation of the error.

Section 2 - Driver List


The Driver List is a two-column display that lists all drivers loaded on the computer at the
time the stop message occurred, along with their base addresses in memory and date stamps
of the driver file dates. This section is important because many stop messages contain the
address of the instruction that caused the error. If the address falls within the base address of
one of the drivers on this list, then that driver may be the cause of the crash.

Section 3 - System Stack Dump


The System Stack Dump lists some of the calls on the stack that preceded the stop message.
Sometimes, the first few lines indicate what component or driver caused the error. You
should note, however, that the last calls on the stack are not always the cause of the problem.
The stack dump also provides the names of modules along with their starting addresses. To
get a more detailed stack trace, use a kernel debugger such as WinDbg.

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:

Restart and set the recovery options in the system


control panel or the /CRASHDEBUG system start option.
If the error persists enable the Kernel Debugger in
either DEBUG or CRASHDEBUG mode on your computer.
Consult the Windows NT Debugger documentation for
instructions on configuring the computer for debugging

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.

To obtain additional information about a system stop


1. In the Windows NT Control Panel, double-click the System icon and then open the
Startup/Shutdown tab.
2. In the Recovery section, select the Write Debugging Information option and then
click OK to apply the change.
Note: When this option is selected, the system memory dump will be written to
%SystemRoot%\memory.dmp after a crash.
3. Copy the system symbol files (*.dbg) from the Windows NT installation CD and the
RTX-supplied *.dbg files to %SystemRoot%\symbols.
4. Install the dumpexam.exe utility (also on the installation CD).
5. Reboot your system and then run the dumpexam utility.
For more detailed system information concerning the crash, consult the dumpexam text
output.

67
RTX User’s Guide

Interpreting Windows 2000 Stop Screens

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.

This dump file type includes the following information:

The stop message and parameters, as well as other data


A list of loaded drivers

ΠThe processor context (PRCB) for the processor that stopped

ΠThe process information and kernel context (EPROCESS) for the process that
stopped

ΠThe process information and kernel context (ETHREAD) for the thread that stopped

ΠThe Kernel-mode call stack for the thread that stopped


This kind of dump file can be useful when space is limited. However, because of the limited
amount of information included, errors that were not directly caused by the thread running at
the time of the problem may not be discovered by an analysis of this file. The Windows 2000
support tool dumpchk.exe will be required to generated text from the binary dump. Refer to
the following Microsoft documentation:

Reading Small Memory Dump Files Created by Windows 2000

Windows 2000 Memory Dump Options Overview

68
Chapter 4: Developing an Application

Interpreting RTX Green Screen Stop Messages

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.

Section 1 - RTSS-Specific Stop Message


This Stop Message section provides the bugcheck data in the form:

*** RTX/RTSS Stop : #E(#1, #2, #3, #4)


Text interpretation of the error

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

Section 2 - HAL-Supplied Stop Message


This Stop Message section provides the bugcheck data in the form:

*** STOP: #E(#1, #2, #3, #4)


*** Address XXXXXXXX has base at YYYYYYYY-Kernel Image

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

Setting the Starvation Time Out Period


You can set the Starvation Time Out period using from the Settings tab of the RTX Properties
control panel.

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.

This chapter contains:

Causes and Management of Interrupt Latencies


Reducing Your System’s Latencies: Tools Overview
KSRTM versus SRTM
Using KSRTM (Kernel System Response Time Measurement)
Using SRTM (System Response Time Measurement)
Using RTX Demo (Graphical version of SRTM)
Using the Timer Latency Display Tool
Using LTP (Latency Test Program)

73
RTX User’s Guide

Causes and Management of Interrupt Latencies


Interrupt latency is of particular concern to real-time systems developers. This topic examines
its causes and RTX techniques for managing them. It includes:

Software causes
Hardware causes
ΠManagement of interrupt latencies

Software Causes

Software causes of interrupt latencies include:

PIC (programmable interrupt controller)-level masking of interrupts. Windows NT and


Windows 2000 kernels and drivers change interrupt masking via HAL IRQL manipulation
calls. Drivers routinely mask interrupts for several µs.
Processor-level masking of all interrupts. The Windows NT and Windows 2000 kernel, HAL,
and special system drivers may mask interrupts for up to 100ms.
ΠInterrupt-processing overhead.

Hardware Causes

Hardware causes of interrupt latencies include:

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 Management of Interrupt Latencies

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

Reducing Your System’s Latencies: Tools Overview


An RTX developer should be mindful of platform factors. The performance-measurement
tools introduced in this topic will help you analyze your system and determine whether it is
performing as expected.

SRTM (System Response Time Measurement) and RTX Demo

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 (Kernel System Response Time Measurement)

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 (Latency Test Program)

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.

Timer Latency Display

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.

KSRTM versus SRTM

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

Using KSRTM (Kernel System Response Time Measurement)


Use KSRTM to measure timer response latencies and obtain reports and histograms of the
results.

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.

Note: KSRTM only works in uniprocessor systems.

Usage
ksrtm -s 2

Format
ksrtm [-r] [-k] [-m] [any of the following flags] seconds_to_sample

where

-r = Real-time HAL extension timer (default).


-k = Kernel (DPC-level) timer.
-m = Multimedia (user-level) timer.
-h = Histogram of latencies (in addition to summary).
-n = No use of real-time priorities.
-s = Sound output (square wave driven by timer).
-i = IRQL HIGH stalls (test interrupt isolation).
-c = Cache flush/dirty and TLB shoot down stalls.
-d = Display loaded driver information.
-l = Longest latency event information.
-u minutes = Minutes between display updates.
seconds_to_sample = Duration in seconds to sample timer response latencies.

See Also
KSRTM versus SRTM

76
Chapter 5: Performance Overview

Using SRTM (System Response Time Measurement)


Use SRTM to measure timer response latencies.

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

-h = Display histogram (in addition to summary).


-s = Turn on sound (square wave driven by timer).
-1 = Use a 10 ms timer period (default is 1 ms).
-f = Use fastest available timer (1 ms or better).
seconds_to_sample = Duration in seconds to sample timer latencies.

To build SRTM on your system


Optionally, you can build SRTM on your system (provided that you have a compiler on it) by
entering the following commands at a command prompt:

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

Using RTX Demo (Graphical version of SRTM)


RTX Demo graphically illustrates response time latencies in the Win32 and RTSS
environments. It measures the total time to an RTSS, Windows NT, or Windows 2000
program’s time handle (i.e., full thread context). It is a realistic measurement of latencies
encountered by an application.

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.

Stop — Stops the process.

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

Remove Load — Stops the "load" process.

Exit — Terminates the program.

To run RTX Demo

1. Start RTX Demo using one of these methods:


Choose RTX Demo from the RTX menu, or
Open the tool from the following directory: c:\program
files\vci\rtx\bin\samples\rtxdemo
2. Select the type of process to run and which type of timer to use.
3. Click on either Run Max Latency or Run Histogram.
4. Once the process is running, you can change sound, plot, and data options. You can
also click:
Stop to terminate the SRTM process.
Add Load (if enabled) to simulate a disk load, and then Remove Load to stop it.
Exit to terminate RTX Demo.
Interpreting the Max Latency Plot

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.

Interpreting the Histogram Plot

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.

Using the Timer Latency Display Tool


The Timer Latency Display tool consists of:

A control and presentation application, which runs as an ordinary Windows NT task


ΠAn RTSS application, which performs the timing measurements

These two tasks communicate through shared memory.

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.

Histogram — View the data as an accumulated histogram.

Latency — View a time sequence of minimum, maximum, and average values observed in a
series of 1-second intervals.

Actions
Reset — Reset accumulated statistics.

To run the Timer Latency Display tool


1. Open the following directory:
c:\program files\vci\rtx\bin\samples\latencydisplay
2. Double-click NtRTSS.rtss to start the timer program. The program starts with the
sound enabled.
3. Double-click the display program, RTSSDisplay.exe. You can change settings for
sound and view while the timer program is running.
4. Follow these steps, as appropriate:
To end the program — Terminate the client process and then exit from the display
process.
To end the display process — Click the X button at the far right of the title bar.
To terminate the timer process — Obtain the RTSS Process ID and then kill the
process by typing the following command at a command prompt: RTSSkill
To obtain a list of the current RTX processes — Find the PID associated with
NtRTSS.rtss and then type: RTSSkill ### (where ### is the PID).

Interpreting the Histogram

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.

Interpreting the Latency display

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.

Using LTP (Latency Test Program)


Use LTP to find misbehaving peripheral devices.
This tool counts the number of instances in a given period of time that the time between clock
reads exceeds a threshold value, using approximately 20% of the CPU time for the duration
of the test. The latency is expected to be two to five microseconds. Higher latencies probably
indicate non-CPU related blocking.

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

Code and File Examples


Bus IO Programming Example
The following code fragment illustrates the Bus I/O calls in a PCI driver.


/*++
*
* 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))

/* DO NOT CHANGE PARAMETERS BELOW THIS POINT */


#define BASE_ADDR _base_addr

/* 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.

#define BASE_ADDR _base_addr

/* respond: the interrupt handler */


void _stdcall respond(PVOID addr);

/* fail: utility routine for fatal errors. */


void fail(char *mesg);

/* shutdownh: the shutdown handler */


void _stdcall shutdownh(PVOID dummy, long cause);

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;

LARGE_INTEGER BAR0; // base port address of the MITE


LARGE_INTEGER BAR1; // base port address of the board registers
LARGE_INTEGER tBAR0, tBAR1; // translated base addresses (system
// mapped addresses) returned by
// RtMapMemory
ULONG AddressSpace = 0; // indicates memory space
ULONG window_data_value = 0; // not really needed...
PCHAR vBAR0=NULL, vBAR1 = NULL; // pointer virtual memory addresses
// returned by RtMapMemory
ULONG IrqLevel; // interrupt level
ULONG IrqVectr; // interrupt vector
PVOID ihr; // interrupt handler

84
Appendix A: Code and File Examples

ULONG intbusnumb; // Interrupt bus number

BAR0.QuadPart = 0;
BAR1.QuadPart = 0;
tBAR0.QuadPart = 0;
tBAR1.QuadPart = 0;

PciData = (PPCI_COMMON_CONFIG) buffer;


SlotNumber.u.bits.Reserved = 0;
flag = TRUE;

//
// 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;

for (f = 0; f < PCI_MAX_FUNCTION; f++)


{
SlotNumber.u.bits.FunctionNumber = f;

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

// Put the BusAddresses into other variables


BAR0.QuadPart = PciData->u.type0.BaseAddresses[0];

// 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
//

vBAR0=RtMapMemory( tBAR0, 4*1024, 0); // 4K, cache disabled

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

vBAR1=RtMapMemory( tBAR1, 4*1024, 0); // 4K, cache disabled


if (!vBAR1)
{
printf(" BAR1: Failure on RtMapMemory\nError=%d\n", GetLastError());
}
else
{
printf(" BAR1: VirtualMemoryAddress: 0x%08x\n", vBAR1);
}

//
// 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

Interrupt Management and Port IO Calls Programming Example


The following programming example demonstrates the use of RTX interrupt management
and port I/O calls.


// Generate an interrupt
// with the digital outs

// Jumper any digital out [3-10] to IR INPUT [1]


// Jumper GND [11] to IR ENABLE [2]

#include <windows.h>
#include <rtapi.h>

#define CT_PORT ((unsigned char *) 0x340)


#define CT_PORT_9513DATA&#9;(CT_PORT + 0)
#define CT_PORT_9513CMD&#9;(CT_PORT + 1)
#define CT_PORT_9513STATUS&#9;(CT_PORT + 1)
#define CT_PORT_DI&#9;(CT_PORT + 2)
#define CT_PORT_DO&#9;(CT_PORT + 3)
#define CT_PORT_SPACE (CT_PORT_DO - CT_PORT_9513DATA + 1)

#define CT_BASE_PORT_9513DATA(BASE) ((unsigned char *)((BASE) + 0))


#define CT_BASE_PORT_9513CMD(BASE) ((unsigned char *)((BASE) + 1))
#define CT_BASE_PORT_9513STATUS(BASE) ((unsigned char *)((BASE) + 1))
#define CT_BASE_PORT_DI(BASE) ((unsigned char *)((BASE) + 2))
#define CT_BASE_PORT_DO(BASE) ((unsigned char *)((BASE) + 3))

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 ;

printf("Simple Interrupt Attach Handler Functional Test") ;


// Enable CT range of ports
if ( !RtEnablePortIo(CT_PORT, CT_PORT_SPACE)) {
(void)printf("RtEnablePortIo(0x%x, 0x%x) failed\n",
CT_PORT, CT_PORT_SPACE);
return 1 ;
}

// Attach the interupt vector to the interrupt handler


hInterrupt = RtAttachInterruptVector(NULL,
0,

InterruptHandler,
(void *)&TestIncrease,
1,
1,
0,
7,
7) ;
if ( NULL == hInterrupt ) {

88
Appendix A: Code and File Examples

printf("Could not register interrupt handler (%d)\n", GetLastError()) ;


return 2 ;
}

for(i=0; i<limit; i++) {


Sleep;
// Pulse the interrupt
RtWritePortUchar(CT_BASE_PORT_DO(CT_PORT), 0xff) ;
}
// Determine what happened.
if ( limit != ihc ) {
printf("FAIL\n") ;
else {
printf("Got %d interrupts\n", limit) ;
}
RtReleaseInterruptVector(hInterrupt) ;
RtWritePortUchar(CT_BASE_PORT_DO(CT_PORT), 0) ;
}


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

# Include rtx.mak for rules and linking flags necessary making


# RTSS executable files
!include <rtx.mak>

all: srtm.rtss


See Also
Using the RTX Makefile
Debugging an RTX Program

90
Appendix A: Code and File Examples

Nmake Input File Example


The following is an example of an nmake input file which will build an RTDLL and Win32
DLL from a single source file, thandler.c.


!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

RTDLL Code Example


This example implements the same functionality as the RTSS DLL example above using an
RTDLL to provide the toggle() function. It is shown in four parts:

1. Simple RTDLL program source code


2. Simple RTSS application which loads the RTDLL and calls an exported subroutine
3. Makefile used to create the RTSS application and RTDLL
4. RTSSrun command used to register the RTDLL
RTDLL Part 1: sampleRtdll.c

#include "windows.h"
#include "rtapi.h"

#define SPEAKER_PORT ((PUCHAR)0x61) //Port IO address for speaker


#define GATE_BIT 0x02

//exported Rtdll Function


__declspec ( dllexport )
int _stdcall Toggle(int argc, char* argv[])
{
UCHAR i;
// Read PIT PORTB register
i = RtReadPortUchar( SPEAKER_PORT);

// Check GATE bit


i^= GATE_BIT;

// Write it to PIT PORTB


RtWritePortUchar( SPEAKER_PORT, i);
return 0;
}

//DllMain must Explicitly return True


BOOL WINAPI _stdcall DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
return TRUE;
}


RTDLL Part 2: usingRtdll.c



#include <windows.h>
#include <stdio.h>
#include <rtapi.h>

#define NO_ERRORS 0
#define ERROR_OCCURRED -1
#define SPEAKER_PORT ((PUCHAR)0x61) //Port IO address for speaker

FARPROC FunctionPtr = NULL;

int RTFCNDCL TimerHandler(PVOID unused)


{
//call Function Toggle
FunctionPtr(0, NULL);
return NO_ERRORS;
}

92
Appendix A: Code and File Examples

/*** MAIN ****/


int main(int argc, char* argv[])
{
HANDLE hLibModule = NULL;
HANDLE hTimer = NULL;
LARGE_INTEGER time;
LPCSTR lpLibFileName = "sampleRtdll.dll";
LPCSTR lpProcName = "_Toggle@8";
ULONG sleepTime = 10000;

//*********** Sample Code: usingRtdll ***********\\

//load Library sampleRtdll


hLibModule = LoadLibrary(lpLibFileName);

//check if loadLibrary returned correctly


if(hLibModule==NULL)
{
//error caused by loading a corrupt or unregistered Rtdll
RtPrintf("UsingRtdll: ERROR: LoadLibrary() failed. Get last Error =
%d\n",GetLastError());
RtPrintf("%s maybe corrupt or not registered with RTSS\n", lpLibFileName);
return (ERROR_OCCURED);
}

//Get function from Rtdll


FunctionPtr = GetProcAddress(hLibModule, lpProcName);

//check if function was found


if(FunctionPtr == NULL)
{
//error caused by nonexistent function name
RtPrintf("UsingRtdll: Error: GetProcAddress() failed. Get Last Error =
%d\n",GetLastError());
RtPrintf("The Function %s does not exist\n", lpProcName);
//free library before exit
FreeLibrary(hLibModule);
return (ERROR_OCCURED);
}

//Enable so Win32 can use PortIO


if (! RtEnablePortIo(SPEAKER_PORT, 1))
{
printf("UsingRtdll: Error: Could not enable Port IO\n");
FreeLibrary(hLibModule);
return (ERROR_OCCURED);
}

// Setup and start the periodic timer.


hTimer = RtCreateTimer(NULL, 0, TimerHandler, NULL,
RT_PRIORITY_MAX,CLOCK_FASTEST);
//check if timer was created
if(hTimer == NULL)
{
RtPrintf("UsingRtdll: ERROR: RtCreateTimer failed. Get Last Error =
%d\n",GetLastError());
//free library before exit
FreeLibrary(hLibModule);
return (ERROR_OCCURED);
}

time.QuadPart = 10000; // 1 milliscond interval

if (!RtSetTimerRelative( hTimer, &time, &time))


{
RtPrintf("UsingRtdll: ERROR: Could not set and start the RTAPI timer.\n");
//free library before exit
FreeLibrary(hLibModule);
return (ERROR_OCCURED);
}

93
RTX User’s Guide

// Wait for 10 seconds.


Sleep(sleepTime);

// Stop and delete the timer.


if(!RtDeleteTimer(hTimer))
{
RtPrintf("UsingRtdll: ERROR: RtDeleteTimer failed. Get Last Error =
%d.\nGetLastError());
//free library before exit
FreeLibrary(hLibModule);
return (ERROR_OCCURED);
}

//free the Library before exiting Process


if(!FreeLibrary(hLibModule))
{
//error caused by an invalid Library handle
RtPrintf("UsingRtdll: Error: FreeLibrary() failed. Get Last Error =
%d\n",GetLastError());
return (ERROR_OCCURED);
}

//the end
return (NO_ERRORS);
}


RTDLL Part 3: rtdll.mak



NODEBUG = 1
RTSS_CRT = 1

!include <rtx.mak>

all: sampleRtdll.rtdll usingRtdll.rtss \


sampleRtdll.dll usingRtdll.exe

clean:
-del *.rtdll
-del *.lib
-del *.obj
-del *.exp
-del *.dll
-del *.exe


RTDLL Part 4: Register the rtdll



C:\> RTSSRun /dll sampleRtdll


94
Appendix A: Code and File Examples

RTSS DLL Code Example


This programming example demonstrates a simple RTSS DLL that exports one function,
toggle(), which toggles the state of the PC speaker. A timer is used to control the frequency
with which toggle() is called in order to generate a tone with a constant pitch. This example is
shown in five parts:

1. Simple dll.c program


2. Definition file (dll.def)
3. Simple program which imports toggle() from dll.rtss
4. Makefile used to link dll.c
5. Win32 program to start the DLL and the application that uses it
RTSS DLL Part 1: dll.c

#include "windows.h"
#include "rtapi.h"

#define SPEAKER_PORT ((PUCHAR)0x61) // Port IO address for speaker


#define GATE_BIT 0x02

//
// 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;

i = RtReadPortUchar( SPEAKER_PORT); // Read PIT PORTB register

i ^=GATE_BIT; // Change GATE bit

RtWritePortUchar( SPEAKER_PORT, i); // Write it to PIT PORTB


}

RTSS DLL Part 2: dll.def

LIBRARY DLL.RTSS

DESCRIPTION ’DLL RTSS’

EXPORTS
Toggle


95
RTX User’s Guide

RTSS DLL Part 3: dll-test.c



#include "windows.h"
#include "stdio.h"
#include "rtapi.h"

#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);
}

time.QuadPart = 10000; // 1 milliscond interval

if (!RtSetTimerRelative( hTimer, &time, &time))


{
printf("ERROR: Could not set and start the RTAPI timer.\n");
return (ERROR_OCCURED);
}

//
// Wait for 10 seconds.
//
Sleep(waitTime);

//

96
Appendix A: Code and File Examples

// Stop and delete the timer.


//
if (!RtDeleteTimer( hTimer))
{
printf("ERROR: Could not Delete timer.\n");
return (ERROR_OCCURED);
}

return (NO_ERRORS);
}


RTSS DLL Part 4: dll.mak



NODEBUG = 1

!include <rtx.mak>

all: dll.rtss dll-test.rtss RunTest.exe

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

dll-test.rtss: dll.lib dll-test.obj


link $(rtsslflags) -out:$*.rtss $*.obj dll.lib $(rtsslibs)

clean:
-del *.rtss
-del *.obj
-del *.exe
-del dll.lib


RTSS DLL Part 5: runtest.c



#include "windows.h"
#include "stdio.h"

#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

NULL, &sinfo, &pinfo)==FALSE)


{
return (exitCode-1);
}

//
// 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);

sprintf( buf, "RTSSkill %d", testPid);


RunUtility( buf);

sprintf( buf, "RTSSkill %d", dllPid);


RunUtility( buf);

return NO_ERROR;
}


98
Appendix A: Code and File Examples

RTSS DLL Makefile Example


The following example shows a typical RTSS DLL makefile for dll.c.


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

RTSS process list:

PID START STATE COMMAND


001 R TimerTest.rtss Timer_test2
002
003
004
005
006
007
008
009
010 /boot R w32_dll.rtss - Supplemental Win32 for C runtime library

RTSS Registered Dlls:

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

RTSS process list:

PID START STATE COMMAND


001 R TimerTest.rtss Timer_test2 (terminated)
002
003
004
005
006
007
008
009
010 /boot R w32_dll.rtss - Supplemental Win32 for C runtime library

RTSS Registered Dlls:

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 timertest.rtss Timer_test2


Process(001) 805d6008
Thread(0000c) 805d60a8 Pri=0 Flags=1 State=Sleeping
Thread(0000d) 805ef490 Pri=15 Flags=0 State=WaitInternal
Timer 805f9f10 Clock=1 Remain=7000us Interval=12000us

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 **"

Dynamically Loaded Libraries:


805fa6b0 Count=-2141245552 Owner=805f2f98 Name="Timer.dll"

============== End RTSSview ==============




See Also
RTSSview Utility

101
RTX User’s Guide

RTX Contiguous Memory Allocation Calls Programming Example


The following programming example demonstrates the use of RTX contiguous memory
allocation calls.


#include <windows.h>
#include <stdio.h>
#include <rtapi.h>

static PVOID vAddress; // virtual memory address returned by


// RtAllocateContiguousMemory
static LARGE_INTEGER pAddress; // physical memory address returned by
// RtGetPhysicalAddress

void main(void)
{

LARGE_INTEGER maxPhyAddr; //highest physical memory address


ULONG size=0; //bytes to allocate

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);

// Get the physical address


pAddress = RtGetPhysicalAddress(vAddress);
if (!pAddress.QuadPart) {
printf("\nFailure on RtGetPhysicalAddress(0x%08X).\t, vAddress");
printf("Error=%d\n", GetLastError());
}
else {
printf("Success on RtGetPhysicalAddress(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

RTX Kernel Memory Locking Calls Programming Example


The following programming example demonstrates the use of RTX kernel memory locking
calls.


#include <windows.h>
#include <stdio.h>
#include <rtapi.h>

void main(void) {

DWORD dwSections = RT_KLOCK_ALL;


if (!RtLockKernel( dwSections)) {
printf("\nFailure on RtLockKernel.\t");
printf("Error=%d\n", RtGetLastError());
}
else {
printf("\nSuccess on RtLockKernel\n");
if (!RtUnlockKernel( dwSections)){
printf("\nFailure on RtUnlockKernel.\t");
printf("Error=%d\n", RtGetLastError());
}
else {
printf("\nSuccess on RtUnlockKernel\n");
}
}
ExitProcess(0);
}


See Also
System Memory Management

103
RTX User’s Guide

RTX Locked Memory Allocation Calls Programming Example


The following programming example demonstrates the use of RTX locked memory allocation
calls.


#include <windows.h>
#include <stdio.h>
#include <rtapi.h>

static PVOID vAddress; // virtual memory address returned by


RtAllocateLockedMemory
void main(void) {

ULONG size=4096; // bytes to allocate

// 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);

// Write to the memory


*vAddress= 0;
}

// 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

RTX Memory Mapping Calls Programming Example


The following programming example demonstrates the use of RTX memory mapping calls.

#include <windows.h>
#include <stdio.h>
#include <rtapi.h>

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;

vAddress=RtMapMemory( physAddr, length, cacheEnable);

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);

success = RtUnmapMemory( vAddress);


if (!success) {
printf("Failure on RtUnmapMemory( 0x%08X)\t", vAddress);
}
else {
printf("Success on RtUnmapMemory( 0x%08X)\n\n", vAddress);
}
}
ExitProcess(0);
}


See Also
Physical Memory Mapping

105
RTX User’s Guide

RTX Process Memory Locking Calls Programming Example


The following programming example demonstrates the use of RTX process memory locking
calls.


#include <windows.h>
#include <stdio.h>
#include <rtapi.h>

void main(void) {

DWORD dwSections = RT_PLOCK_ALL;

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

RTX Timer and Sleep Calls Programming Example


The following example demonstrates the use of RTX timer and sleep calls.


#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);
}

if (!RtSetTimerRelative( hTimer, &Period, &Period))


{
printf("ERROR: Could not set and start the RTAPI timer.\n");
ExitProcess(2);
}

//
// Wait for the sampling time.
//
Sleep(1000);

//
// Stop and delete the timer.
//
RtCancelTimer( hTimer, &x);
RtDeleteTimer( hTimer);

printf(" Value of number of timers counter is %d\n",TimerCounter);


ExitProcess(0);

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

RtCreateTimer, 95, 107 RTX Green Screen, 62, 65


RtDeleteTimer, 95, 107 RTX HAL Timer, 107
RTDLLs, 8, 15, 57, 100 RTX Inter-Process Communication, 34
Register, 8 RTX Kernel Memory Locking Calls, 37
Unregister, 8 RTX Locked Memory Allocation Calls, 37
RtFreeContiguousMemory(vAddress, 102 RTX Makefile, 29, 56
RtGetBusDataByOffset, 83 RTX Memory Mapping Calls, 51
RtGetLastError, 103, 106 RTX Power Management, 71
RtGetPhysicalAddress, 102 Windows 2000, 71
RtLockKernel, 103 RTX Process Memory Locking Calls, 37
RtLockProcess, 106 RTX Settings, 70
RtMapMemory, 83 RTX Settings icon, 30
RtSetThreadPriority, 107 RTX Startup, 30
RtSetTimerRelative, 107 RTX Timer, 107
RTSS, 4, 7, 34, 78 RTX Utilities, 7
building, 7 RTX-defined, 70
debugging, 4 RtxServer, 16
launch, 4 Run
Running, 34 Timer Latency Display tool, 80
starting, 4, 34
use, 34 S
Win32 Thread Priority Mapping, 34 Select, 65
RTSS application, 59 Automatically Reboot, 65
RTSS Device Drivers, 59 Semaphores, 8, 44
Writing, 59 Service Request Interrupt, 70
RTSS DLLs, 25, 57, 59 SetErrorMode, 60
Building, 25 Setting
create, 25 Starvation Time Out, 70
designing, 57 Starvation Time Out Period, 70
use, 25 SetUnhandledExceptionHandler, 60
RTSS Exception Handling, 60 Shutdown Handlers, 29
RTSS Object Viewer, 13 Shutdown Program, 29
RTSS Process, 4, 15 Sleep Calls, 40
Starting, 4 Sleep Calls Programming Example, 107
Stopping, 4 Sleep Services, 40
RTSS Programs, 59 SRTM, 75, 77
RTSS Task Manager, 4, 15, 34 Starvation Management, 70
RTSS Task Manager window, 15 Structured Exception Handling, 60, 62, 63
RTSS Thread Priority Mapping, 34 Support ID, ix
RTSSkill, 4, 30, 34 System Exception Handling, 62
RTSSkill Examples, 100 System Memory Allocation, 37
RTSSkill Utility, 11 System Memory Locking, 37
RTSSrun, 11, 34, 77, 95 System Memory Management, 37
RTSSrun Console, 9 System Response Time Measurement, 75
RTSSrun GUI, 9
RTSSrun Utility, 9 T
RtTranslateBusAddress, 83 Technical Support, ix
RtUnlockKernel, 103 Technical Support Area, ix
RTX API, 60 Testing, 4
RTX AppWizard, 7 Real-Time Applications, 4
RTX Demo, 75 Thread Management, 33
RTX Device Drivers, 4 Timer Latency Display, 75
RTX Exception Codes, 63 Timer Latency Display Tool, 75, 80
RTX Exception Handling, 64 TimerHandler, 95
RTX Functionality, 33 Tools Overview, 75
Using, 33

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

S-ar putea să vă placă și