Kithara »Driver Collection«
Alles zur hardwarenahen Programmierung für ISA, PCI, PCIe, USB und PCMCIA sowie Timer, Tastaturbehandlung und serielle Komunikation in Echtzeit finden Sie in diesem umfassenden Produkt!
Die Beliebtheit der »Driver Collection« zeigt, dass eine Vielzahl von Nutzern der Kithara-Produkte vor allem das breite Anwendungsgebiet der gesamten Produktreihe schätzen.
Hinweis: Eine individuelle Zusammenstellung der Funktionsmodule erhalten Sie in der »RealTime Suite«.
- Zugriff auf alle I/O-Register des PCs aus Anwendung oder DLL
- Einblenden von externem physischen Speicher (Dual-Port-RAM)
- Interner Speicher für Zugriff von PC-Einsteckkarten (DMA Memory)
- Ermittlung der PCI-Konfigurationsdaten und Ressourcen
- Leistungsfähige Mechanismen zur Interrupt-Programmierung
- Generischer WDM-Treiber für Plug&Play-Installation enthalten
- Timer mit programmierbarer Auflösung von 1 Millisekunde
- Zeitgeber in verschiedenen Formaten, bis zu 0,1 Mikrosekunde
- Hochgenaue Kurzzeitverzögerungen in 0,1-Mikrosekunden-Schritten
- Serielle Kommunikation in Echtzeit - schnelle Reaktion auf alle Ereignisse
- Unterstützung von PIC- und APIC-Hardware, Multiprozessor-PCs, Hyperthreading, Dual-Core etc.
- Bereitstellung eines Windows-Programmier-Interfaces für Gerätekommunikation (ReadFile, WriteFile, DeviceIoControl)
- Kommunikation mit USB Geräten über USB 1.1 und USB 2.0 von der Anwendungs- oder Kernel-Ebene,
- USB unterstützt Low-, Full-, High-Speed sowie Control-, Bulk-, Interrupt-, Isochron-Transfer
- USB-Sende- und Empfangsroutinen können direkt aus Echtzeitkontext heraus gerufen werden
- Bereitstellung eines Windows-Programmier-Interfaces für Gerätekommunikation (ReadFile, WriteFile, DeviceIoControl)
- Beliebige Gerätenamen, z.B. für virtuelle Schnittstellen
- Nutzung der Kernel-Ebene unterstützt C/C++ oder Delphi (Win32 native)
- Unterstützt die folgenden Betriebssysteme: Windows 7, Vista, Server 2003, XP, 2000 und NT
- Beschreibung
- Eigenschaften
- Beispiele
- FAQ
- Hardware
Das Base Module ist die Grundlage der gesamten »RealTime Suite«.
Erzeugen Sie alle benötigten Ressourcen, die zum Beispiel für die Kommunikation zwischen Anwendung und Kernel-Ebene sorgen!
Das Base Module stellt Funktionen zur Verwaltung des Kernel-Treibers bereit. Die »RealTime Suite« kann dabei von mehreren Programmen gleichzeitig verwendet werden.
Das Base Module enthält Funktionen zur Erzeugung und Verwaltung folgender Ressourcen:
- Shared Memory
- Daten- und Message-Pipes für schnellen Datenaustausch
- Event-Objekte
- CallBack-Funktionen
- Threads
- Quick-Mutexe
Im Base Module befinden sich mehrere Funktionen, die dem Absetzen von Meldungen an den »Kernel Tracer« dienen. Das erleichtert die Fehlersuche und ist auch für Profiling-Aufgaben einsetzbar.
Beachten Sie auch das Kernel Module, das weitere allgemein gültige Funktionen bereitstellt und für den Zugang zur Kernel-Ebene unverzichtbar ist.
Das Base Module ist immer erforderlich.
- Allgemeine Funktionen
- Öffnen/Schließen des Kernels
- Versionskontrolle, Treiber-Konfiguration
- Threads
- Erzeugen von Threads
- Ermitteln/Setzen beliebiger Stufen der absoluten Thread-Priorität
- Shared Memory
- Shared Memory speziell für Datenaustausch
- geschützt vor Festplatten-Auslagerung (fest im Speicher)
- mehrere Bereiche mit jeweils bis zu über 60 MByte
- Pipes
- Lock-freie und schnelle Daten- und Message-Pipes
- ermöglicht komfortablen und synchronisierten Datenaustausch in beliebiger Richtung zwischen Kernel und Anwendung
- keine weitere Synchronisation benötigt (auch auf Multi-Core-CPUs)
- Signalisierung
- Event-Objekte: Setzen, Rücksetzen und Pulsen aktiviert Anwendungs-Thread
- Callback-Ausführung von Anwendercode auf Kernel- oder Anwendungsebene
- Versenden von Windows-Messages
- Quick-Mutexe
- Schnelle Synchronisation ("Mutex" = Mutual Exclusion)
- Multiprozessortauglich
- Device-Information
- Ermittlung der Geräteinformationen von PCI-, USB-, COM-, HID-Devices etc.
- Debug-Unterstützung
- Absetzen formatierter Text-Meldungen von der Kernel-Ebene aus
- Kompatibel zum »Kernel Tracer« für Profiling und Fehlersuche
Das Base Module stellt vielfältige Werkzeuge bereit, z.B. Shared Memory für den Datenaustausch zwischen Anwendung und Kernel:
err = KS_createSharedMem(
&pAppPtr, // Application-Adresse
&pSysPtr, // Systemadresse des Speichers
"MySharedMem", // Global gültiger Name
40 * MegaBytes, // Länge in Bytes
0); // Flags, hier 0
Zur Vereinfachung für regelmäßigen Datenaustausch ist eine Daten-Pipe ideal, die intern ebenfalls auf Shared Memory basiert:
err = KS_createPipe(
&hPipe, // Adresse des Pipe-Handles
"MyValuePipe", // Name der Pipe
2, // Datengröße (z.B. Messwerte)
1000000, // max. Anzahl Datenelemente
NULL, // reserviert
0); // Flags, hier 0
Nun kann z.B. der Kernel ermittelte Messwerte in der Pipe ablegen:
err = KS_putPipe(
hPipe, // Pipe-Handle
valueBuffer, // Zeiger auf Datenpuffer
valueCount, // Anzahl der Messwerte
NULL, // hier nicht benutzt
0); // Flags, hier 0
Die Anwendung kann nun die Messwerte aus der Pipe lesen:
err = KS_getPipe(
hPipe, // Pipe-Handle
buffer, // Zeiger auf Datenpuffer
bufferSize, // max. Größe des Puffers
&filledSize, // wieviel Werte gelesen?
0); // Flags, hier 0
Daten mit variabler Länge (z.B. Messages) lassen sich optimal mit einer Message-Pipe verarbeiten. Diese ist sehr ähnlich zu verwenden.
- Welche Voraussetzungen müssen allgemein erfüllt sein?
- Unterstützung von Single- oder Dual-Core-, Multi-Core-CPUs, Hyperthreading, SMP etc.
- Unterstützung von Standard-PIC oder APIC, ACPI
- optimal ist ein moderner Dual-/Quad-Core-PC (mit APIC + ACPI)
- Unterstützung von Windows 2000, Windows XP (Embedded), Windows Server 2003, Windows Vista (x86)
- Programmierung der Kernel-Ebene in C/C++ und Delphi (Win32)
- Welche Besonderheiten ergeben sich beim Umgang mit Shared Memory?
- wird nicht auf die Festplatte ausgelagert und ist daher immer verfügbar (auch innerhalb der RealTime-Umgebung)
- ist sowohl von der Anwendungsebene als auch vom Kernel aus ansprechbar
- ist nur einmalig vorhanden und kann daher auch dem Datenaustausch zwischen verschiedenen Anwendungen dienen (es ist jedoch in jedem Programm einmal KS_createSharedMem zu rufen)
- ist anfangs mit 0 initialisiert – durch einen Zähler lässt sich ermitteln, ob der Speicher bereits zuvor von anderen Programmen verwendet wurde
- Zugriffe auf den Speicher sind nicht automatisch synchronisiert (für synchronisierten Zugriff empfehlen wir Daten- und Message-Pipes)
- 32-Bit-CPU
- max. 8 logische Prozessoren (Chips * Kerne * Threads), darüber auf Anfrage
Echtzeitfähigkeit wird nur auf der Kernel-Ebene erzielt.
Bringen Sie Ihren Anwendercode auf die Kernel-Ebene und schaffen Sie sich dadurch den Zutritt zur Echtzeit-Welt unter Windows!
Benötigt werden hierzu C/C++-Compiler oder das Entwicklungstool Delphi (Win32), um nativen x86-Code erzeugen zu können. Beachten Sie jedoch, dass z.B. auch die .NET-Umgebung mit C# unterstützt wird, indem eine native C++- oder Delphi-DLL für den Kernel-Zugang sorgt. Entsprechende sofort compilierbare Projekte befinden sich in jeder Software-Lieferung.
Es gibt zwei verschiedene Wege, um Ihren Anwendercode auf die Kernel-Ebene zu bringen:
- Befehlsweise Relozierung einer Callback-Funktion und ihrer Subroutinen in den Kernel-Adressraum
- Laden einer DLL direkt auf die Kernel-Ebene
Während die erste Methode für kleinere Projekte durchaus Vorteile besitzt, bietet die zweite Variante wesentlich mehr Möglichkeiten und erlaubt z.B. auch die einfachere Erzeugung von Debug-Meldungen, die sich im »Kernel Tracer« für Fehlersuche und Optimierung auswerten lassen.
Außerdem realisieren Sie damit komplexe Steuerungsanwendungen, deren grafische Oberfläche z.B. mit Java oder C#.NET erstellt wird, während nur die zeitkritischen Code-Teile der DLL im Kernel-Modus laufen.
Das Kernel Module ist Voraussetzung, um Anwendercode auf der Kernel-Ebene ausführen zu können.
- Relokation von Callback-Funktionen und deren Subroutinen
- Direktes Laden einer DLL in den Kernel
- DLL zu erstellen mit C/C++ oder Delphi (Win32)
- Callback-Funktionen werden direkt in Interrupt Service Routine (ISR) oder im Echtzeit-Timer-Kontext ausgeführt
- Alle wichtigen Funktionen der »RealTime Suite« auch von der Kernel-Ebene aus aufrufbar, z.B.:
- I/O-Port-Zugriffe
- Zugriffe auf physischen Speicher
- Zeitmessung, genaue Kurzzeitverzögerung
- Senden und Empfangen bei Daten- und Message-Pipes
- Senden und Empfangen bei seriellen Schnittstellen
- Senden und Empfangen bei Ethernet-Controllern
- EtherCAT-Datenaustausch
- Setzen, Rücksetzen, Pulsen von Events
- Ereignisse von Kernel-Ebene: Events und Windows-Messages
- Schneller Datenaustausch zwischen Anwendung und Kernel über Shared Memory oder lock-freie Daten- und Message-Pipes
Angenommen, Ihre Callback-Funktion für den Echtzeit-Timer sieht so aus:
int __stdcall myTimerCallback(
void* pArgs, // Adresse der Referenzdaten
void* pContext); // Adresse der Kontextdaten
Es gibt nun zwei Wege, um den Anwendercode auf die Kernel-Ebene zu bekommen:
err = KS_createCallBack(
&hCallBack, // Adresse des Handles
myTimerCallback, // Adresse der Funktion
pSysAddrOfMyData, // Referenzparameter
KSF_KERNEL_EXEC, // auf der Kernel-Ebene!
0); // Anwendungspriorität, hier 0
Auf diese Weise wird die Funktion in den Kernel-Speicher geladen.
Alternativ lässt sich eine ganze DLL in den Kernel laden:
err = KS_loadKernel(
&hKernel, // Adresse des Handles
"mykernel.dll", // Dateiname der Kernel-DLL
"myInitFunction", // Name der Init-Routine
pArgs, // Referenzparameter
KSF_KERNEL_EXEC); // Flags, in Kernel laden
Einmal in den Kernel geladen, kann nun ganz ähnlich ein Kernel-Callback erzeugt werden:
err = KS_createKernelCallBack(
&hCallBack, // Adresse des Handles
hKernel, // Kernel-Handle
"myTimerCallback", // Name der Funktion
pSysAddrOfMyData, // Referenzparameter
KSF_KERNEL_EXEC, // auf der Kernel-Ebene!
0); // Anwendungspriorität, hier 0
Die Callback-Handles lassen sich nun als Timer oder Interrupt-Handler anmelden oder z.B. zur Echtzeit-Signalisierung bei eintreffenden Ethernet-Frames.
Hinweis: Vollständige Projekte, die eine Rahmenanwendung in einer der Sprachen C++, C# oder Delphi sowie eine in den Kernel geladene DLL in C++ oder Delphi enthalten, sind Bestandteil jeder Software-Lieferung.
- Wie kann der Kernel mit der Anwendung kommunizieren?
- Shared-Memory-Bereiche für nicht synchronisierten Datenaustausch
- Daten- und Message-Pipes basierend auf Shared Memory (Lock-frei, daher sind die lesende und die schreibende Seite gegeneinander synchronisiert)
- Kernel kann Event-Objekte setzen, um Anwendungs-Threads zu aktivieren
- Anwendungsebene kann die Ausführung von Funktionen im Kernel auslösen
- Windows-Messages
- Wie lässt sich Code für die Kernel-Ebene debuggen?
- Anwendercode lässt sich innerhalb der Entwicklungsumgebung debuggen:
- Callback-Funktion wird durch spezielles Flag auf der Anwendungsebene ausgeführt
- Kernel-DLL wird durch spezielles Flag auf die Anwendungsebene geladen
- Shared Memory, Events, Zugriffe auf I/O-Ports und physischen Speicher etc. sind in beiden Kontexten verwendbar
Keine speziellen Hardware-Anforderungen
Das IoPort Module ermöglicht den Zugriff auf I/O-Register des Computers.
Greifen Sie mit dem IoPort Module auf die I/O-Ports des Computers direkt aus der Anwendung heraus zu!
Sowohl bei eingebauten Hardware-Baugruppen als auch Mezzanin- und PC-Einsteckkarten erfolgt die Ansteuerung in den meisten Fällen mittels Zugriffen auf die I/O-Register von Controllern. Hierfür stehen Funktionen für 8-, 16- und 32-Bit-Zugriffe zur Verfügung.
Das IoPort Module ist auch erforderlich, um die Hardware-Ressourcen (z.B. Speicheradressen oder Interrupt-Leitungen) zu ermitteln, die vom Plug&Play-Manager von Windows dynamisch zugewiesen wurden.
Mit dem Begriff "I/O-Ports" sind hier übrigens nicht COM-Ports oder LPT-Ports gemeint, sondern die insgesamt 65536 über I/O-Maschinenbefehle ansprechbaren I/O-Adressen des Systems. Damit lassen sich natürlich auch die I/O-Register der COM- und LPT-Controller ansprechen.
Ergänzen Sie Ihren Custom Driver um das Memory Module, wenn die Hardware, die Sie ansprechen wollen, einen Speicherzugriff bietet.
- I/O-Port-Zugriffe
- Freigabe des Direktzugriffs auf I/O-Ports möglich
- I/O-Zugriffe aus Anwendungsprogramm ohne Kontextwechsel möglich
- Zugriffsschutz des Betriebssystems auf andere als die freigegebenen Adressen weiterhin intakt und aktiv
- Nur eigene Anwendung erhält Zugriff auf Adressen
- Keine Beeinträchtigung des Systems
- Funktionen für direkten und indirekten I/O-Zugriff
- 8-, 16- und 32-Bit-Zugriffe, lesend oder schreibend
- Funktionen kompatibel zu (unter DOS) bekannten C-Makros
- Ressourcen-Ermittlung
- Ermittlung der vom Plug&Play-Manager zugewiesenen Ressourcen (Basisadressen, IRQs)
- Lesen und Schreiben des PCI-Konfigurationsblockes
Wenn der direkte I/O-Port-Zugriff genutzt werden soll, ist zunächst der I/O-Bereich für den Direktzugriff freizuschalten:
err = KS_enableIoRange(
myBaseAddress, // Basisadresse der Hardware
8, // Anzahl der I/O-Register
KSF_SIZE_8_BIT); // Flags, hier byte-weise
Nun können die freigegebenen Hardware-Register direkt adressiert werden:
byte value = KS_inpb(
myBaseAddress + 2); // Adresse, 1 Byte lesen
... // Byte auswerten
KS_outpb(
myBaseAddress + 4, // Adresse, 1 Byte schreiben
value); // Byte schreiben
Wenn die I/O-Basisadresse einer PCI-Karte vom Plug&Play-Manager dynamisch vergeben wurde, kann diese ganz leicht ermittelt werden, indem entweder alle PCI-Baugruppen durchsucht werden, bis die gewünschte (anhand Vendor- und Device-ID) gefunden wird:
err = KS_getBusData(
&pciData, // Adresse der PCI-Struktur
busNumber, // Bus-Nummer
slotNumber, // Gerätenummer und Funktion
0); // Flags, hier 0
if (pciData.vendorID == XXXX && pciData.deviceID == YYYY)
...
Oder es wird sofort die gewünschte ID-Kombination gesucht:
err = KS_getRessourceInfo(
"PCI\\VENxxxx&DEVyyyy", // ID-Kombination
&resourceInfo); // Adresse der Resourcen-Info
Die erhaltenen Datenstrukturen enthalten nun die benötigten Angaben über Interrupt-Leitung und benutzte I/O- oder Speicher-Basisadressen.
- Wie können die vom PCI-Plug&Play dynamisch zugewiesenen Ressourcen ermittelt werden?
- entweder mit 'KS_getBusData': Iterieren über alle im System befindlichen PCI-Geräte, bis anhand der Parameter (Vendor-Id, Device-Id, etc.) das gesuchte Gerät gefunden wurde
- oder mit 'KS_getResourceInfoEx': Übergabe der Parameter des gesuchten Gerätes und Auswertung der beschreibende Datenstruktur
- mit 'KS_getResourceInfo' lassen sich auch die Daten anderer Schnittstellen ermitteln, z.B. serielle ("COM") oder parallele ("LPT") Schnittstellen, Netzwerkkarten ("NET") für das Packet Module sowie USB-Geräte ("USB")
Keine speziellen Hardware-Anforderungen
Das Memory Module dient dem Zugriff auf physischen Speicher.
Greifen Sie auf externen Speicher von Einsteckkarten zu oder stellen Sie internen RAM für den Hardware-Zugriff zur Verfügung!
Das Memory Module ermöglicht die Verwendung von physischem Speicher sowohl von Ihrer Anwendung, als auch von externer Hardware aus. Dafür gibt es zwei verschiedene Arten von Speicherbereichen:
- externe Speicherbereiche von Einsteckkarten (sogenannter Dual-Port-RAM) sollen auch von der Anwendung aus adressierbar sein
- Speicherbereiche aus dem internen Hauptspeicher sollen der externen Hardware zur Verfügung gestellt werden (sogenanntes DMA-Memory)
Das Ergebnis ist in beiden Fällen gleich: Sowohl die Anwendung (und auch die Kernel-Ebene) als auch die externe Hardware (z.B. auf dem PCI-Bus) haben Zugriff auf den Speicher. Dieser wird in den Adressraum der Anwendung eingeblendet – auf diese Weise finden keinerlei unnötige Kopieroperationen statt, was die Eignung für zeitkritische Anwendungen begründet.
Dies kann für bestimmte Applikationen entscheidend sein, da Zugriffe über I/O-Ports in der Regel künstlich stark ausgebremst werden, um Kompatibilität zu älteren Hardware-Komponenten zu wahren (teilweise ? 1 µs!). Bevorzugte Anwendungen sind daher: Messwerterfassung, Kommunikation, Framegrabber für die Bildverarbeitung etc., also alle Applikationen, bei denen große Datenmengen schnell transportiert werden müssen.
Das Memory Module beschränkt sich auf reine Speicherzugriffe. Für die Adressierung von I/O-Ports beachten Sie bitte auch das IoPort Module.
- Externer Speicher
- Einblenden von externem Dual-Port-RAM in den Adressraum der Anwendung
- Getrennte Adressen für Anwendung und Kernel-Ebene
- Direkter Zugriff – keine Software-Emulation oder Kopieroperation
- Interner Speicher
- Bereitstellen von internem Hauptspeicher für externe Hardware auf ISA- oder PCI-Bus
- Physikalisch zusammenhängender Speicher
- Physikalische Adresse kann der externen Hardware auf geeignete Weise übermittelt werden
- Zur Erhöhung allokierbarer Blockgrößen ist Anforderung des Speichers bereits zum Bootzeitpunkt möglich
Das Einblenden externer Speicherbereiche (Dual-Port-RAM) einer PCI-Karte in den Adressraum der Anwendung und des Kernels erfolgt so:
err = KS_mapPhysMem(
&pAppPtr, // Application-Adresse
&pSysPtr, // Systemadresse des Speichers
externalPhysAddr, // physikalische Adresse
externalSize, // Länge des Speicherbereichs
KSF_PCI_BUS); // Flags, hier PCI-Bus
Das Allokieren interner Speicherbereiche des PC-RAM für Zugriffe durch die externe Hardware (sogenanntes "Bus-Master-DMA") einer PCI-Karte erfolgt so:
err = KS_allocPhysMem(
&pAppPtr, // Application-Adresse
&pSysPtr, // Systemadresse des Speichers
&externalPhysAddr, // physikalische Adresse
externalSize, // Länge des Speicherbereichs
KSF_PCI_BUS); // Flags, hier PCI-Bus
Die physikalische Adresse kann nun auf geeignete Weise an die Hardware übermittelt werden, damit diese über den PCI-Bus auf den Speicher zugreifen kann.
Beide Methoden führen dazu, dass sowohl die Anwendung, der Kernel und die externe Hardware direkt (ohne Emulation oder Kopieroperationen) auf den selben Speicher zugreifen können.
- Wie groß ist der maximal zu mappende Bereich externen Speichers?
- im Prinzip so groß wie der externe Speicher ist; es sollte keine Beschränkung geben
- Wie groß ist der maximal zu allokierende Bereich internen Speichers?
- Speicher muss physisch zusammenhängend sein, daher umso geringer, je länger das System läuft. Es sollte daher so früh wie möglich nach dem Boot-Vorgang der Speicher angefordert werden. Der Systemspeicher wird vom Betriebssystem sehr schnell "zerstückelt".
- Memory Module enthält Mechanismen zur Allokation von Speicherbereichen bereits zum Boot-Zeitpunkt, die später von der Anwendung abgefordert werden können
- Außerdem können eher mehrere kleinere statt eines größeren Bereichs allokiert werden. Es bietet sich daher eine sogenannte "Scatter/Gather"-Verwaltung des Speichers an.
Keine speziellen Hardware-Anforderungen
Das Clock Module ermöglicht hochgenaue Zeitmessung.
Ermitteln Sie die genaue Systemzeit in verschiedenen Formaten oder realisieren Sie exakte Kurzzeitverzögerungen!
Für verschiedene Zwecke ist in hardwarenahen Anwendungen eine genaue Systemzeit zu ermitteln. Das Clock Module stellt dafür Funktionen bereit, mit denen die Systemzeit in verschiedenen Formaten geliefert wird. Dazu gehören relative (seit dem Systemstart) und absolute Zeitangaben sowie selbst definierbare Zeitformate für spezifische Anforderungen.
Die Zeitmessung basiert auf verschiedenen, auswählbaren, im jeweiligen System vorhandenen Zeitgebern (z.B. Time Stamp Counter (TSC), PC-Timer, PM-Timer, APIC-Timer, HPET-Timer). Interne Überläufe bei der Umrechnung sind durch 64- und 96-Bit-Berechungen praktisch auch nach Jahren kontinuierlicher Laufzeit ausgeschlossen.
Für hardwarenahe Programmierung werden oft exakte zeitliche Verzögerungen benötigt. Auch dies leistet das Clock Module.
Das Clock Module ist Voraussetzung für das RealTime Module und ist stets eine wertvolle Ergänzung für verschiedene Aufgaben.
- Zeitmessung
- Systemzeit basierend auf verschiedenen internen Zeitgebern
- Interne Berechnungen mit hochoptimierten 64- und 96-Bit-Algorithmen
- Relative Zeitformate seit dem Systemstart
- Absolute Zeitformate in üblichen Formaten:
- Zehntel-Mikrosekunden seit 1.1.1601 (Windows-Systemzeit)
- Mikrosekunden seit 1.1.1970 (Unix-Systemzeit)
- Millisekunden seit 1.1.1980 (DOS-Systemzeit)
- Absolute Zeitangaben nach lokaler Zeitzone oder UTC
- Alle Zeitgeber bei Systemstart gegeneinander kalibriert
- Nutzerspezifische Zeitformate einfach definierbar
- 2-Phasen-Zeitmessung (1. zunächst Erfassung, 2. spätere Umrechnung) für extrem zeitkritische Applikationen
- Kurzzeitverzögerung
- Hochgenaue Kurzzeitverzögerungen, in Zehntel-Mikrosekunden programmierbar
- Aufwändige Kalibrierung beim Systemstart ermöglicht Genauigkeit im Nanosekundenbereich (auf der Kernel-Ebene)
Das Clock Module stellt zwei verschiedene Mechanismen bereit – Zeitmessung und Kurzzeitverzögerung.
Die meist benutzte Funktion zur Zeitmessung liefert 100-ns-Einheiten seit dem Start des Systems:
UInt64 time;
err = KS_getClock(
&time, // Adresse der Variablen
KS_CLOCK_MACHINE_TIME); // 100-ns seit Systemstart
Diese können auch zur einfacheren Weiterverarbeitung in 64-Bit-Werte umgewandelt werden:
__int64 time64 = time.hi;
time64 <<= 32;
time64 += time.lo;
printf("%Ld Mikrosekunden seit dem Systemstart.\n", time64 / 10);
Statt der (Systemstart-) relativen Zeit ist auch der absolute Zeitpunkt seit dem 1.1.1601 ermittelbar:
err = KS_getClock(
&time, // Adresse der Variablen
KS_CLOCK_ABSOLUTE_TIME); // 100-ns seit 1.1.1601
Der erhaltene Wert lässt sich leicht mit Windows-Funktionen weiterverarbeiten.
Die Kurzzeitverzögerung realisiert hochgenaue Verzögerungen, programmierbar in 100-ns-Schritten und mit einer Abweichung von nur wenigen Nanosekunden (auf der Kernel-Ebene):
err = KS_microDelay(
38); // hier 3,8 Mikrosekunden
Dies ist oftmals sehr nützlich beim Zugriff auf Hardware, wenn zeitliche Bedingungen einzuhalten sind.
- Welche Voraussetzungen müssen allgemein erfüllt sein?
- Unterstützung von Single- oder Dual-Core-, Multi-Core-CPUs, Hyperthreading, SMP etc.
Keine speziellen Hardware-Anforderungen
Das System Module meldet besondere System-Ereignisse.
Lassen Sie sich über das Starten und Stoppen von Anwendungen oder kritische Situationen benachrichtigen!
Mit dem System Module ist es möglich, eine Benachrichtigungsfunktion für bestimmte kritische Systemereignisse anzumelden, die dann gerufen wird, wenn die besondere Situation eintritt. In diesem Fall kann zum Beispiel bei einem "Absturz" des Anwendungsprogrammes reagiert werden, um z.B. eine angeschlossene Hardware in den sicheren Ruhezustand zu versetzen.
Die Reaktion erfolgt grundsätzlich auf der Kernel-Ebene.
Erfordert das Kernel Module.
- Anmeldung von Callback-Funktionen für die Kernel-Ebene
- Aufruf der Callback-Funktion bei Eintreten spezieller Ereignisse z.B.:
- Start von anderen Anwendungen, die den Kernel-Treiber ebenfalls benutzen
- Beenden von Anwendungen (sowohl bei regulärem als auch fehlerhaftem Programmende)
- Erfassung von Programmabbrüchen im Debugger, Task Manager oder bei Programmabstürzen
- Signalisierung bei BSOD
Auf einfache Weise können Sie sicherstellen, dass bei einem eventuellen Fehler Ihres Anwendungsprogrammes das System in einen sicheren Zustand überführt werden kann. Erstellen Sie eine Callback-Funktion für die Kernel-Ebene, um dies zu erreichen:
int __stdcall myEmergencyCallback(
void* pArgs, // Adresse der Referenzdaten
void* pContext); // Adresse der Kontextdaten
Hierfür wird nun ein Callback-Objekt erzeugt:
err = KS_createCallBack(
&hCallBack, // Adresse des Handles
myEmergencyCallback, // Adresse der Funktion
pSysAddrOfMyData, // Referenzparameter
KSF_DIRECT_EXEC, // auf der Kernel-Ebene!
0); // Anwendungspriorität, hier 0
Diese Callback-Funktion wird nun als System-Handler angemeldet:
err = KS_installSystemHandler(
KS_SYSTEM_PROCESS_ABORT, // bei Programmabbruch
hCallBack, // Callback-Handle
0); // Flags, hier 0
Falls nun ein unerwarteter Programmabbruch erfolgt, ohne vorher die benutzten Ressourcen ordnungsgemäß abzumelden, wird auf der Kernel-Ebene die Emergency-Callback-Funktion gerufen.
"Unerwartete Programmabbrüche" sind z.B. ein Programmabsturz oder auch das Abbrechen durch den Task Manager oder den Debugger der Entwicklungsumgebung.
- Wie wird sichergestellt, dass die Emergency-Funktion noch gerufen wird, auch wenn die Anwendung nicht mehr existiert?
- Die Emergency-Funktion muss natürlich alle erforderlichen Daten zur Verfügung haben, wenn dieser Fall eintritt. Sämtliche Incodeionen sind also schon vorher vorzubereiten und im Shared Memory zu übergeben. Beim Aufruf der Funktion wird auf Anwendungsdaten oder -code nicht mehr zugegriffen.
Keine speziellen Hardware-Anforderungen
Das Device Module stellt das Windows-Device-API bereit.
Ermöglichen Sie vorhandenen ("Legacy"-) Anwendungen den Zugriff über Windows-Schnittstelle für Geräte, einschließlich "virtuelle COM-Ports"!
Mit dem Device Module melden Sie Callback-Funktionen an, die auf der Kernel-Ebene gerufen werden, wenn eine Fremdanwendung eine bestimmte Geräteschnittstelle öffnet, schließt, Daten liest oder schreibt oder die Einstellungen der Schnittstelle verändert. Dahinter verbergen sich die Windows-Funktionen CreateFile, CloseHandle, ReadFile, WriteFile und DeviceIoControl. Diese 5 Funktionen bilden das sogenannte Device-API, das auch in anderen Betriebssystemen der Ansteuerung von Geräten dient.
Fangen Sie alle Aktionen auf der Kernel-Ebene ab und realisieren Sie Ihre eigene Treiber-Implementierung für USB- oder PCI-Baugruppen. Mit dem Device Module ist auch die Realisierung von "virtuellen COM-Ports" einfach zu gestalten. Dadurch erhält die Fremdanwendung eine serielle Schnittstelle, die von einer physikalischen nicht zu unterscheiden ist.
Für die Manipulation eines seriellen Datenstromes sowie weiter gehende Möglichkeiten an "virtuellen COM-Ports" beachten Sie bitte auch das Filter Module.
Erfordert das Kernel Module.
- Abfangen der Funktionsaufrufe CreateFile, CloseHandle, ReadFile, WriteFile und DeviceIoControl
- Reaktion auf der Kernel-Ebene erlaubt sofortige Reaktion
- Für Datenaustausch mit der Applikation empfehlen sich z.B. die komfortablen Daten- oder Message-Pipes
- Festlegung beliebiger Namen für die Geräteschnittstelle
- "Virtuelle COM-Ports" können einfach erzeugt werden
Für die Realisierung eines "virtuellen COM-Ports" erstellen Sie verschiedene Callback-Routinen für die Ereignisse CREATE, CLOSE, READ, WRITE und CONTROL. Zum Beispiel für CONTROL:
int __stdcall myControlCallback(
void* pArgs, // Adresse der Referenzdaten
void* pContext) // Adresse der Kontextdaten
{ ...
if (pContext->controlCode == SERIAL_SET_BAUD_RATE)
...
Für alle Routinen werden nun Callback-Objekte erzeugt:
err = KS_createCallBack(
&functions.hOnControl, // Adresse des Handles
myControlCallback, // Adresse der Funktion
pSysAddrOfMyData, // Referenzparameter
KSF_DIRECT_EXEC, // auf der Kernel-Ebene!
0); // Anwendungspriorität, hier 0
Anschließend kann das "virtuelle COM-Port" erzeugt werden:
err = KS_createDevice(
&pAppPtr->hDevice_, // Addresse des Handles
"COM77", // Device-Name
&functions, // Struktur mit Callback-Handles
KSF_SERIAL_PORT); // Flags, "virtueller COM-Port"
Damit steht anderen Anwendungen eine weitere serielle Schnittstelle unter dem Namen "COM77" zur Verfügung, die sich von "echten" Schnittstellen nicht unterscheidet. Sie können damit oftmals vorhandene Anwendungen weiter betreiben, ohne diese neu programmieren zu müssen.
- Welche Anwendungen sind mit dem Device Module realisierbar?
- Zum einen dient das Device Module der Bereitstellung einer Programmierschnittstelle für andere Anwendungsentwickler, z.B. für Ihren USB- oder PCI-Treiber. Sie können damit ein Interface anbieten, das sich mit den Funktionen des Win32-API einfach ansprechen lässt. Die Dokumentation des API lässt sich dadurch vereinfachen.
- Zum anderen ist es möglich, eine sogenannte "virtuelle COM-Schnittstelle" bereitzustellen, die von vorhandenen Anwendungsprogrammen aus geöffnet und behandelt werden kann, als ob es sich um ein reales COM-Port handeln würde.
Keine speziellen Hardware-Anforderungen
Tastatureingaben abfangen, manipulieren, simulieren.
Bestimmen Sie selbst, welche PS/2-Tastatureingaben erlaubt sind!
Das Keyboard Module erlaubt die Kontrolle über PS/2-Tastaturen. Es lassen sich zum Beispiel Tastatureingaben einfach sperren (z.B. Ctrl-Alt-Del), die für den Bediener einer Maschine unzulässig sind.
Durch die Registrierung einer Callback-Funktion ist es auch möglich, eine Tastenbetätigung abzufangen und in einen anderen Code umzuwandeln oder eine Tasteneingabe zu simulieren.
Erfordert das Kernel Module.
- Sperren von bestimmten Tastatureingaben, z.B. Ctrl-Alt-Del, Alt-Tab, Ctrl-Esc etc.
- Ändern von Tastencodes
- Simulation von Tastatureingaben
- Ausschließlich in Verbindung mit PS/2-Tastaturen
An einer PS/2-Tastatur ist es einfach möglich, spezielle Tastencodes für eine besondere Kernel-Funktion zu vereinbaren. Angenommen, es soll eine spezielle Behandlung für Ctrl-Shift-Alt-F1 erfolgen:
int __stdcall myKeyboardCallBack(
void* pArgs, // Adresse der Referenzdaten
void* pContext) // Adresse der Kontextdaten
{ ...
if ((pUserContext->modifier & KSF_KEY_SHIFT) != 0 &&
(pUserContext->modifier & KSF_KEY_CTRL) != 0 &&
(pUserContext->modifier & KSF_KEY_ALT) != 0 &&
(pUserContext->key == 0x3B))
specialF1Handler(); // Spezielle F1-Routine
...
Diese Funktion kann nun als Handler angemeldet werden:
err = KS_createKeyHandler(
KSF_KEY_FUNCTION, // nur Funktionstasten abfangen
hSpecialF1CallBack, // Handler, hier Callback
0); // Flags, hier 0
In industriellen Anlagen ist es oftmals erwünscht, spezielle Sondertasten für den Bediener zu sperren. Dazu gehören z.B. die Windows-Tasten, Ctrl-Alt-Del, Ctrl-Esc, Alt-Esc und Alt-Tab. Um diese alle zu sperren, genügt folgender Funktionsaufruf:
err = KS_createKeyHandler(
KSF_KEY_SYSTEM, // Alle Systemtasten
NULL, // Kein Handler benötigt
KSF_IGNORE_KEY); // Tasten sind zu ignorieren
- Welche Arten von Tastaturen lassen sich mit dem Keyboard Module behandeln?
- Derzeit werden ausschließlich Keyboards unterstützt, die über PS/2-Adapter angeschlossen werden.
Keine speziellen Hardware-Anforderungen
Filterung serieller Datenströme mit dem Filter Module.
Protokollieren oder ändern Sie den Datenstrom an seriellen Schnittstellen!
Mit dem Filter Module lässt sich protokollieren, welche Daten über eine serielle (COM-) Schnittstelle übertragen werden. Es erlaubt auch die weit reichende Filterung (Änderung) des gesamten Datenstromes an den seriellen COM-Schnittstellen.
Sie können die Daten auf andere Schnittstellen umlenken, z.B. über eine Netzwerkschnittstelle senden. Auch die Simulation ganzer Geräte ist möglich – beispielsweise zu Testzwecken – oder der vollständige Ersatz, der durch die Leistungfähigkeit des PCs möglich wird.
Ziel ist es, vorhandene, auf eine serielle (COM-) Schnittstelle ausgelegte, Programme weiter zu nutzen, wo sich vielleicht keine COM-Schnittstelle mehr befindet. Dieser Eingriff ist für vorhandene Anwendung vollkommen transparent, da alle Daten und Ereignisse des Datenstromes an den von Ihnen installierten Handler weitergereicht werden.
Beachten Sie für passive Anwendungen auch das Device Module, das ebenfalls die Erzeugung virtueller COM-Ports erlaubt.
Erfordert das Kernel Module.
- Synchroner oder asynchroner Eingriff in den Datenstrom auf der Kernel-Ebene
- "Virtueller COM-Port" zur Vortäuschung von realen COM-Schnittstellen mitgeliefert
- Request- und Complete-Ereignisse getrennt erfassbar
- Mögliche Ereignisse: Open, Close, Read, Write, Control
- Datenpakete lassen sich vollständig verwerfen oder simulieren
Es ist ein Datenstrom an einer seriellen Schnittstelle zu beobachten und zu protokollieren. Dazu müssen alle WRITE-Request- und alle READ-Complete-Aufrufe erfasst werden. Die Daten werden über Message-Pipes geleitet:
int __stdcall mySerialFilterCallBack(
void* pArgs, // Adresse der Referenzdaten
void* pContext) // Adresse der Kontextdaten
{ ...
if ((pUserContext->ctxType == KS_FILTER_WRITE_REQUEST)
err = KS_putPipe(
pData->hWrPipe, // Pipe-Handle
pContext->pBytes, // Daten
pContext->length, // Länge
NULL, 0);
if ((pUserContext->ctxType == KS_FILTER_READ_COMPLETE)
err = KS_putPipe(
pData->hRdrPipe, // Pipe-Handle
pContext->pBytes, // Daten
pContext->length, // Länge
NULL, 0);
...
Ein Filter wird erzeugt, wobei die Schnittstelle noch nicht geöffnet sein darf:
err = KS_createFilter(
&hFilter, // Adresse d. Filter-Handles
"COM1", // Name des Ports
0); // Flags, hier 0
Die Funktion kann nun als Handler angemeldet werden:
err = KS_installFilterHandler(
hFilter, // Filter-Handle
KS_FILTER_WRITE_REQUEST, // Ereignis
hSerialFilterCallBack, // Handler, hier Callback
0); // Flags, hier 0
err = KS_installFilterHandler(
hFilter, // Filter-Handle
KS_FILTER_READ_COMPLETE, // Ereignis
hSerialFilterCallBack, // Handler, hier Callback
0); // Flags, hier 0
- Welche Anwendungen lassen sich mit dem Filter Module realisieren?
- "Virtuelle COM-Ports" bereitstellen (beachten Sie hierfür auch das Device Module, das sich einfacher handhaben lässt)
- Datenverkehr über vorhandene Schnittstellen protokollieren
- Vorhandenen Datenstrom manipulieren
Keine speziellen Hardware-Anforderungen
Das Interrupt Module ermöglicht die Behandlung von Hardware-Interrupts.
Realisieren Sie Handler für Hardware-Interrupts von ISA- und PCI-Bus-Baugruppen unmittelbar in der Anwendungs-Programmierumgebung!
Bei der hardwarenahen Programmierung, beispielsweise der Entwicklung von Gerätetreibern, sind häufig auch Ereignisse der Hardware-Baugruppe in Form von Interrupts auszuwerten. Das Interrupt Module erlaubt die Anmeldung von Interrupt-Handlern für Einsteckkarten am ISA- und PCI-Bus sowie für interne Baugruppen.
Die Interrupt-Behandlung kann im Kernel oder auf der Anwendungsebene erfolgen. PCI-Interrupts sind allerdings bereits auf der Kernel-Ebene zu quittieren. Dafür können auch mehr als ein Handler für einen Interrupt registriert werden – beispielsweise eine kleinere Funktion für die Quittierung des IRQs auf der Kernel-Ebene und zusätzlich eine weitere Funktion auf der Anwendungsebene für die eigentliche Auswertung des Interrupts.
Zum Ansprechen von USB-Hardware beachten Sie bitte auch das USB Module.
Erfordert das Kernel Module.
- Anmeldung von Interrupt-Handlern für ISA- und PCI-Interrupts
- Behandlung auf Anwendungs- oder Kernel-Ebene (Quittierung von PCI-IRQs im Kernel)
- Unterstützung aller PCI-Bustypen einschließlich PCIexpress
- Aufruf der Kernel-Funktionen unmittelbar im Kontext der Interrupt Service Routine (ISR)
- Unterstützung von ACPI-, PIC-, APIC- und Multiprozessor-Computern (Dual-Core, Quad-Core etc.)
- Vorübergehende Sperrung der Interrupt-Behandlung möglich
- Kernel-Treiber der »RealTime Suite« kann selbst als WDM-Treiber für PCI-Plug&Play konfiguriert werden.
Angenommen, es soll folgende Callback-Funktion als Interrupt-Handler fungieren:
int __stdcall myInterruptHandler(
void* pArgs, // Adresse der Referenzdaten
void* pContext); // Adresse der Kontextdaten
Hiermit erstellen Sie ein Callback-Objekt (siehe Kernel Module) mit dem Flag KSF_DIRECT_EXEC.
Zur Anmeldung des Interrupt-Handlers sind zunächst die Ressourcen-Informationen zu ermitteln:
KSResourceInfoEx info;
err = KS_getResourceInfoEx(
"PCI\\VEN_10ec&DEV_8139",// Hardware-ID der PCI-Karte
&info); // Zu füllende Info-Struktur
Damit lässt sich nun der Interrupt-Handler anmelden:
err = KS_createDeviceInterrupt(
&hInterrupt, // Adresse des Handles
&info, // Info-Struktur
hCallBack, // Callback-Handle
KSF_ACCEPT_PENDING |
KSF_PCI_INTERRUPT); // Flags, hier PCI
Es lassen sich auch mehrere Handler beim selben IRQ anmelden, z.B. eine Callback-Funktion für die Kernel-Ebene und eine weitere innerhalb des Anwendungskontexts.
- Wie erfolgt die Unterstützung von Plug&Play-Mechanismen?
- Der jeweilige Treiber der »RealTime Suite« lässt sich selbst als Plug&Play-Treiber verwenden. Hierzu ist die mitgelieferte Installations-Textdatei (*.INF) lediglich um einen Eintrag mit der Spezifikation der PCI-Karte oder des UDB-Gerätes zu erweitern.
- Wie lässt sich ermitteln, welche Interrupt-Leitung verwendet wird (Plug&Play)?
- Die vom PCI-Plug&Play-Manager dynamisch zugeordneten Ressource-Informationen lassen sich einfach ermitteln. Siehe IoPort Module.
Keine speziellen Hardware-Anforderungen
Das Serial Module bietet serielle Kommunikation in Echtzeit.
Realisieren Sie umfassende serielle Kommunikationsprotokolle unter Windows!
Das Serial Module unterstützt zwei verschiedene Betriebsarten: Entweder serielle Kommunikation über alle COM-Schnittstellen des PCs ohne Echtzeit oder serielle Kommunikation in Echtzeit und direkte Hardware-Ansteuerung über UART-16550 oder höher.
Mit dem Serial Module lassen sich Kommunikations-Anwendungen für die seriellen COM-Schnittstellen auf einfache Weise realisieren. Gegenüber dem Windows-API ist es einfacher, zwischen verschiedenen Arten der Signalisierung zu unterscheiden: Blockierung des Aufrufers bis zum Abschluss des Sende- oder Empfangsauftrages, Signalisierung durch Callback oder Event – ein Konzept, das auch in anderen Modulen zu finden ist.
In der Echtzeit-Betriebsart erlaubt das Serial Module die Realisierung nahezu beliebiger, auch komplexer industrieller Kommunikationsprotokolle. Durch Einsatz eines effizienten Kernel-Treibers wird die zeitlich genaue Reaktion auf alle Schnittstellen-Ereignisse und die direkte Beeinflussung der Hardware auf der Kernel-Ebene möglich. Das API beider Betriebsarten ist ansonsten identisch.
Für die Erzeugung sogenannter "virtueller COM-Ports" beachten Sie auch das Device Module, über das vorhandene ("Legacy"-)Anwendungen völlig transparent auf nicht vorhandene serielle Schnittstellen zugreifen können.
Erfordert das Kernel Module.
- Serielle Kommunikation über alle COM-Schnittstellen des PCs über Windows-Mechanismen oder in Echtzeit durch UART-Hardware-Unterstützung von 16450 bis 16950
- Flexible Reaktion auf eintreffende Daten und Ereignisse durch Blockierung, Callback oder Event
- Auflisten aller COM-Schnittstellen im PC (im Base Module)
- Schnelle Reaktion auf eintreffende Daten und Ereignisse
- Direkte Ansteuerung der Handshake-Leitungen
- Handler für alle Ereignisse, z.B. Byte-Handler, LSR-, MSR-Change, Break, Error
- Erkennung von "transmit empty" (z.B. für RS485-Richtungsumschaltung oder 9-Bit-Modus)
- Automatische RS485-Richtungsumschaltung programmierbar
- Endlos-Modus für direktes Senden aus Anwender-Puffer und andere spezielle Szenarien
- Automatische Timeout-Überwachung zuschaltbar
- Automatische Leitungsfehler-Überwachung programmierbar
- Maximale Baudrate detektierbar
- Senden und Empfang sind voneinander unabhängig
- Empfangene Daten werden automatisch im Hintergrund gepuffert
- Überbrückung des Empfangs über mehrere Sekunden
- Liste der unterstützten Zusatzkarten hier
- Unterstützung weiterer Karten kostengünstig zu implementieren
Verwenden Sie folgende Funktion, um alle COM-Ports aufzulisten:
err = KS_enumDevices(
"COM", // nach COM-Ports suchen
i, // Zähler, mit 0 beginnend
portNameBuf, // Puffer für COM-Port-Namen
0); // Flags, hier 0
Die Schnittstelle lässt sich dann wie folgt öffnen:
KSResourceInfoEx info;
err = KS_openSerialPort(
&hPort, // Adresse des Handles
portNameBuf, // Name des Ports (z.B. "COM1")
"9600,n,8,1", // Initialisierung
KSF_KERNEL_EXEC); // Kernel-Implementierung
So senden wir Daten, z.B. eine Messwertanforderung an eine Gerät:
err = KS_xmitPort(
hPort, // Port-Handle
NULL, // Signalisierung (Post Mode)
message, // Pufferadresse
0, // Länge, zu senden (auto)
NULL, // Länge, gesendet
KSF_DONT_WAIT); // Flags: ohne Blockierung
Jederzeit lässt sich ermitteln, wie viele Zeichen bereits empfangen wurden:
err = KS_getPortState(
hPort, // Port-Handle
&state, // Adresse der Status-Struktur
0); // Flags: here 0
printf("Es wurden %d Zeichen empfangen.\n", state.recvAvail);
Der Empfang kann folgendermaßen aussehen (im Wait-Mode auf der Anwendungsebene):
err = KS_recvPort(
hPort, // Port-Handle
NULL, // Signalisierung (Wait Mode)
pBuffer, // Adresse des Datenpuffers
state.recvAvail, // Länge, zu empfangen
&received, // Länge, empfangen
KSF_USE_TIMEOUTS); // Flags: Timeout-Überwachung
- Was ist die "normale" Betriebsart des Serial Modules?
- Flag KSF_USER_EXEC beim Öffnen des Ports
- basiert auf Windows-Treibermechanismen
- unterstützt alle COM-Schnittstellen im System (auch "virtuelle Schnittstellen", z.B. USB-nach-COM-Adapter)
- keine Echtzeit
- Was zeichnet die Kernel-Betriebsart aus?
- Flag KSF_KERNEL_EXEC beim Öffnen des Ports
- Hardware wird mit speziellem Treiber direkt angesteuert
- erfordert UART-16550-kompatible Hardware
- Reaktion auf alle Schnittstellen-Ereignisse innerhalb der Interrupt-Service-Routine
- Welche sind die Voraussetzungen für den Kernel-Modus?
- Schnittstellen-Hardware kompatibel zum UART-16550
- Ressourcen (Interrupt und I/O-Basisadresse) ermittelbar
- entweder eingebaute COM-Ports oder unterstützte Zusatzkarten
- Unterstützung weiterer Karten kostengünstig zu implementieren
- Werden auch höhere Baudraten unterstützt?
- ja, höhere Standard-Baudraten werden automatisch erkannt
- spezielle Baudraten lassen sich vorgeben
- wir realisieren gerne in Ihrem Auftrag eine Erweiterung des Treibers
Das Serial Module erfordert im Kernel-Modus spezielle Hardware.
Um eine hohe Reaktionsfähigkeit zu erreichen, muss der langsame Windows-Treiber der seriellen Schnittstelle ersetzt werden. Aus diesem Grund werden nur bestimmte serielle Schnittstellenbaugruppen unterstützt. Diese Einschränkung gilt nur im Kernel-Modus, da hier eine UART-16550-kompatible Hardware angesprochen werden muss. Dazu gehören:
Standard-Schnittstellen
- Alle im PC eingebauten RS232-Schnittstellen, solche auf ISA-PnP-Karten, PC-Card-Module (PCMCIA 16-Bit)
PCI-Bus
- MOXA: IndustIo CP-132 (2xSER, RS-422/485)
- MOXA: IndustIo CP-114 (4xSER, RS-422/485)
- MOXA: SmartIo C104H/PCI (4xSER)
- MOXA: SmartIo C168H/PCI (8xSER)
- ADDI-DATA: APCI-73xx (1xSER)
- ADDI-DATA: APCI-74xx (2xSER)
- ADDI-DATA: APCI-75xx (4xSER)
- Brainboxes: PCI 4 Port Serial Card (z.B. CC-268) (4xSER)
- TCL: DataBooster (4xSER/8xSER) (über IoPort-Zugriff)
- SUNIX: 4088A/4089A (2xSER,2xPAR)
- LINDY: 70585 (2xSER)
- LINDY: 70616 (2xSER,2xPAR)
- EXSYS: EX-41051 (1xSER)
- EXSYS: EX-41052 (2xSER)
- Wiesemann & Theis: 13812 (2*SER, RS-232, 1kV isolated)
CardBus 32-Bit
- QUATECH: Serial I/O PC Card SSP-100 (1xSER)
- SOCKET: Serial I/O PC Card (1xSER)
Wenn Sie Fragen zur Hardware-Unterstützung haben, kontaktieren Sie uns! Die Unterstützung anderer externer Schnittstellen lässt sich in der Regel leicht hinzufügen. Falls Sie die Funktionstüchtigkeit mit anderen Einsteckkarten getestet haben, würden wir uns über eine entsprechende Information sehr freuen.
Das USB Module erlaubt die Entwicklung von USB-Gerätetreibern.
Erstellen Sie komfortabel USB-Treiber für Windows, ohne sich in die aufwändige Kernel-Programmierung einzuarbeiten!
Mit dem USB Module lassen sich nicht nur USB-Treiber für Windows komfortabel erstellen, sondern auch vorhandene USB-Geräte ansprechen, um eine spezielle Ansteuerung zu realisieren.
Das USB Module enthält einen generischen Treiber für USB-Geräte, der einfach durch einen Eintrag in der mitgelieferten INF-Datei des Treibers konfiguriert wird. Dadurch wird der Treiber aktiviert, sobald der Windows-Plug&Play-Manager den Anschluss des betreffenden USB-Gerätes erkennt.
Kombinieren Sie das USB Module mit dem Device Module, um anderen Anwendungen das USB-Gerät in Form eines "virtuellen COM-Ports" bereitzustellen.
Erfordert das Kernel Module.
- Kommunikation mit USB Geräten über USB 1.1 und USB 2.0 von der Anwendungs- oder Kernel-Ebene
- Unterstützung von Low-, Full-, High-Speed
- Control-, Bulk-, Interrupt-, Isochron-Transfer
- Unterstützt Geräte mit mehreren Interfaces und mehreren Konfigurationen
- Reaktion auf alle Plug&Play und Power-Management-Ereignisse
- Reaktion auf eintreffende Daten direkt auf der Kernel-Ebene möglich
- Sende- und Empfangsroutinen können direkt aus Echtzeitkontext heraus gerufen werden
- Auflisten aller USB-Devices im PC
Verwenden Sie folgende Funktion, um alle USB-Geräte aufzulisten:
err = KS_enumDevices(
"USB", // nach USB-Geräten suchen
i, // Zähler, mit 0 beginnend
deviceNameBuf, // Puffer für Gerätenamen
0); // Flags, hier 0
Mit dem erhaltenen Namen lässt sich der Config-Deskriptor ermitteln, um z.B. nach einem bestimmten HID-Gerätetyp zu suchen:
err = KS_execUsbCommand(
deviceNameBuf, // Gerätename
KS_USB_GET_CONFIG_DESCRIPTOR,
0, // Index des Deskriptors
pBuf, // Puffer
64000, // Puffergröße
KSF_ALTERNATIVE); // Flags
Ein bereits vorhandener Treiber kann ersetzt werden:
strcpy(infPath+GetSystemDirectory(infPath,256),"\\Kdemo.inf");
err = KS_updateDriver(
deviceNameBuf, // Gerätename
infPath, // INF-Datei
0); // Flags, hier 0
Das gefundene Gerät kann nun geöffnet werden. Wenn es bekannt ist, können Sie hier aber auch den Gerätenamen direkt angeben:
err = KS_openUsbDevice(
&hDevice, // Adresse des Handles
"USB\\VID_10CF&PID_5500",// Gerätename
0); // Flags, hier 0
Die eigentliche Kommunikation erfolgt über sogenannte Endpoints. Es gibt bis 15 Sende- und 15 Empfangs-Endpunkte zu einem Gerät:
err = KS_getUsbPort(
hDevice, // Device-Handle
&hPort, // Adresse des Handles
endpointAddress, // Nummer des Endpoints
KSF_INTERRUPT_TRANSFER); // Flags: Transferart
Die Kommunikation selbst erfolgt nun ähnlich der seriellen Kommunikation im Serial Module.
- Sind die USB-Funktionen auch auf der Kernel-Ebene nutzbar?
- Ja. Obwohl die USB-Ankopplung nicht echtzeitfähig ist, können Sie z.B. Sende- oder Empfangs-Aufträge auch aus einer Echtzeit-Timer-Funktion heraus auslösen.
- Wie kann zur Ausnutzung der verfügbaren Bandbreite ein möglichst kontinuierlicher Datenstrom gewährleistet werden?
- mehrere Jobs gleichzeitig möglich, um Bandbreite auszunutzen
- maximale Anzahl gleichzeitiger Jobs einstellbar
Keine speziellen Hardware-Anforderungen
Mit dem Timer Module sind Timer in Millisekundenauflösung realisierbar.
Programmieren Sie anwenderspezifische Timer-Funktionen zur Steuerung und Überwachung des Prozesses!
Für die vielfältigsten Aufgaben sind in Steuerungsanwendungen zyklische Timer zu programmieren. Als auszuführende Aktion kann über ein Event-Objekt ein Anwendungs-Threads aktiviert als auch eine Callback-Funktion auf der Anwendungsebene oder im Kernel gerufen werden.
Die Timer sind ca. in Millisekundenschritten programmierbar. Obwohl die Timer auf den vom jeweiligen Betriebssystem angebotenen Mechanismen beruhen, ist die erreichbare Genauigkeit für viele Überwachungszwecke ausreichend. Um trotzdem eine möglichst hohe Genauigkeit zu erzielen, können Sie auf der Anwendungsebene die Thread-Priorität heraufsetzen und erhalten so Vorrang vor anderen Anwendungen. Eine wesentlich höhere Genauigkeit erzielen Sie mit dem RealTime Module.
Beachten Sie auch das RealTime Module, das hochgenaue Echtzeit-Timer unter Windows bereitstellt.
Erfordert das Kernel Module.
- Timer in Millisekunden-Schritten programmierbar
- Callback- oder Event-Objekte zur Signalisierung
- Callbacks auf der Anwendungs- oder der Kernel-Ebene möglich
- Basierend auf Mechanismen des Betriebssystem-Kerns
- Einmalige oder zyklische Timer
- Theoretisch unbegrenzte Anzahl von Timern
Wenn Sie eine Callback-Funktion erzeugt haben (siehe Kernel Module), können Sie diese als Timer-Callback wie folgt anmelden:
const int ms = 10000; // Millisekunden
err = KS_createTimer(
&hTimer, // Adresse des Handles
period * ms, // Timerperiode in 100 ns
hTimerCallBack, // Callback-Handle
KSF_DONT_START); // Flags: noch nicht starten
Der Timer lässt sich nun für zyklische Ausführung starten:
err = KS_startTimer(
hTimer, // Timer-Handle
0, // Flags, hier 0
period * ms); // Timerperiode in 100 ns
…und jederzeit wieder stoppen:
err = KS_stopTimer(
hTimer); // Timer-Handle
…oder auch erneut starten, z.B. für einmaligen Aufruf:
err = KS_startTimer(
hTimer, // Timer-Handle
KSF_ONE_SHOT, // Flags, einmalig
period * ms); // Timerdauer in 100 ns
Ein laufender Timer kann jederzeit abgebrochen werden, was sich sehr gut für Watchdog-Anwendungen eignet:
err = KS_cancelTimer(
hTimer); // Timer-Handle
In dem Fall beginnt bei zyklischen Timern die Wartezeit erneut.
- Lassen sich mehrere Timer gleichzeitig anmelden?
- ja, Anzahl der Timer praktisch nicht begrenzt
- keine Priorisierung zwischen den Timern, jede Timer-Routine wird abgeschlossen, bevor andere ausgeführt wird
- Welche Genauigkeit ist erreichbar?
- Timer basieren auf Mechanismen des Betriebssystem-Kernels
- Timer daher nicht echtzeitfähig, siehe RealTime Module
- auf Anwendungsebene lässt sich erzielbare Genauigkeit durch Anhebung der absoluten Priorität des Timer-Threads erhöhen
Keine speziellen Hardware-Anforderungen
Plattformen
Echtzeitfähigkeit wird nur auf der Kernel-Ebene erzielt. Dazu werden C/C++ oder Delphi (Win32) benötigt. Dennoch unterstützt die »RealTime Suite« verschiedene Plattformen, wie z.B. auch die .NET-Umgebung:
- C++Builder (Borland/CodeGear) mit VCL-Oberfläche
- Microsoft Visual C++ 6 mit MFC-Oberfläche
- Visual Studio 2005/2008 C++ mit MFC-Oberfläche
- Delphi (Object Pascal) Win32 mit VCL-Oberfläche
- Visual Studio 2005 C# mit WPF-Oberfläche
Die Lösung besteht darin, den zeitkritischen Code in eine DLL zu verlagern, die mit den Funktionen der »RealTime Suite« direkt auf die Kernel-Ebene geladen wird und dadurch in den Echtzeit-Kontext gelangt.
Sofort verwendbare Programmgerüste für die genannten Plattformen befinden sich in jeder Software-Lieferung.
Systemvoraussetzungen
Die Produkte der »RealTime Suite« unterstützen eine breite Palette von Hardware- und Software-Kombinationen:
- CPU: AMD (ab Athlon) oder Intel (ab Pentium 2)
- Single- oder Multi-Core, Hyperthreading, SMP mit insgesamt bis zu 8 CPU-Kernen (darüber auf Anfrage)
- ACPI (Advanced Control and Power Interface) unterstützt, (A)PIC (Advanced Programmable Interrupt Controller) unterstützt (einige Funktionen erfordern APIC-PC)
- Betriebssystem: Windows 2000 (bis SP4), Windows XP (bis SP3), Windows Server 2003 (bis SP1), Windows Vista (SP1), Betrieb bei neueren Service Packs ohne Gewähr
- Compiler für Kernel-Ebene: Microsoft: Visual C++/Visual Studio, CodeGear (Borland): C++Builder, Delphi Win32
Bei Fragen zur Systemunterstützung kontaktieren Sie uns bitte!



