本文档包括以下内容:
在VS中运行一个RTSS映像
To specify the Configuration Properties settings:
1. From the Configurations drop-down menu, select RTSSRelease.
2. From the Project menu, choose Properties to open the Property pages dialog box, and then choose the Configuration Properties, Debugging node. 项目属性 -> 调试
3. In the Command field, type in RTSSrun.exe. Include the full path, for example: 在 “命令”中输入Rtssrun的路径
C:/Program Files/Ardence/RTX/bin/rtssrun.exe
4. In the Command Arguments field, enter the path to your .rtss image. For example: 在“命令参数”中输入要运行的rtss映像路径
C:/Program Files/Microsoft Visual Studio/MyProjects/Example/RTSSRelease/Example.rtss
- Click OK to save the settings.
要运行RTSS映像:
From the Debug menu, choose Start without Debugging. “调试”-> “开始执行(Ctrl + F5)”
生成和注册RTDLL
生成RTDLL的方法与生成rtss的方法相同。
使用RTSSrun来注册生成的RTDLL。
编码技术
- 使用RTX动态链接库
- 使用C运行时库函数
- 加载rtapi_w32.dll
- 使用浮点数
- 使用MMX 和SSE
- 编写RTSS设备驱动
- C++ 和结构化异常捕获
- 饥饿管理
- 用关机处理程序测试RTX程序
1. 使用RTX动态链接库
本节包括以下内容:
- Descriptions of the two types of real-time DLLs (RTSS DLL and RTDLL)
- C Runtime Libraries: Programming Considerations for DLLs
- References to RTSS DLL and RTDLL code examples关于RTSS DLL和RTDLL
RTSS DLL
RTSS DLL其实并不是DLL,而是一个可以导出供其他RTSS进程使用的RTSS程序。它们共同一个地址空间。可以在启动时加载,也可以从C/C++编写的Windows程序中调用(e.g., System("RTSSrun LibName.rtss")。尽管与RTSS程序类似,但是其入口点为Main,并被编译链接之后产生一个可以供其他RTSS程序调用的导出函数库。一般地,一个RTSS DLL的Main将会简单地产生一个SuspendThread调用。RTSS DLL允许你在一个调用的程序中用名字引用函数,但是加载时比较麻烦,因为其他RTSS程序使用它们时不会自动加载和卸载它们。
RTDLL
RTDLL是可以通过调用LoadLibrary和FreeLibrary动态地加载和卸载的RTSS对象。当引用它们的最后一个进程中止时会自动从内存中卸载。RTDLL不应被静态的加载或延迟加载(delay loaded)。因为RTDLL不需要链接到一个显式的导出库,而是提供一种方便的、弹性的运行时动态适应方法。
C Runtime Libraries: Programming Considerations for DLLs C运行时库:DLL的编程考虑
本小节讨论当你设计一个将要与RTX提供的C运行库(RTXlibc.lib or RTXlibcmt.lib)进行链接的RTSS DLL或RTDLL时,需要一直进行考虑的问题。
MS的C运行库初始化代码假定全局变量有进程范围,比如,会为每一个使用库的进程分配一个所有C运行库的全局变量和结构体的拷贝。但是,在RTSS DLL和RTDLL中不是这样。
RTSS DLL
因为RTSS DLL是一些被链接成产生一个导出库的RTSS进程,也因为它们在关机之前不会从内存被卸载,所以,初始化时产生的全局结构体会在使用RTSS DLL的进程的存活周期内一直保留。
提示:被多个进程使用的RTSS DLL中的少部分C运行时函数会带来不安全因素。
你不应使用的函数有:fprintf(), getenv(), perror(), printf(), vsprintf(), and wprintf()。因为这些函数信赖于每个进程的全局变量,它们会产生可能导致系统重启的结果。注意这里的“被多个进程使用”意思是在系统启动和关闭时被多于一个的进程在任何时刻使用,包括同一个RTSS映像、在一系列里使用同一个RTSS PID运行两次。
RTDLLs
RTDLL不是RTSS进程;他们是可以动态加载和卸载的RTSS对象。因为一个RTDLL产生的对象通常属于调用它的进程,当此进程中止时它们也就被随之销毁。另一方面,C运行库初始化时产生用来内存分配的堆(heaps),这些堆会一直保留到初始加载RTDLL的进程中止之时。因为C运行库函数的行为只在一个RTDLL里可靠,这个RTDLL是多个进程通过有严格限制的LoadLibrary, FreeLibrary 函数调用的。 建议永远不要注册通过C运行库链接得到的RTDLLit,这可以通过 RTSSrun 的 /s 开关来实现。
RTSS DLL 和 RTDLL 代码例程
1. 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:
- Simple dll.c program
- Definition file (dll.def)
- Simple program which imports toggle() from dll.rtss
- Makefile used to link dll.c
- 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 declspec(dllexport) 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.RTSSDESCRIPTION 'DLL RTSS'
EXPORTS
Toggle
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);
//
// 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, 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;
}
2. 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:
- Simple RTDLL program source code
- Simple RTSS application which loads the RTDLL and calls an exported subroutine
- Makefile used to create the RTSS application and RTDLL
- 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;
}
/*** 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);
}
// 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 = 1RTSS_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