Windows Kernelmodetreiber echtzeitfähig?
-
Hallo,
Es geht darum, Hardware über ein abgewandeltes I2C Protokoll zu testen.
Der Bus soll dabei über die parallele Schnittstelle simuliert werden.Da im vorliegenden Fall die Genauigkeit im Mikrosekundenbereich liegen muss
(es soll getestet werden, ob sich die angeschlossene Hardware an die
Spezifikation hält und die schreibt z. B. vor T1 = 50..1000 µsec vor),
scheidet eine Anwendung im Usermode definitiv aus.Das ganze sollte ohne Zusatzhardware unter WinXP laufen, da die Software an mehreren
Rechnern zum Einsatz kommen soll und Platinen lassen sich so schlecht
mittels Copy + Paste verteilen...Hab leider noch nie einen Treiber geschrieben.
Aber wenn ich mir das hier: http://www.c-plusplus.net/forum/viewtopic-var-t-is-178708-and-highlight-is-driver.html
bzw. auch MSDN durchles,
dann müsste sich sowas doch in einer Interrupt Routine (=höchste Priorität) machen lassen.
Man müsste halt in Kauf nehmen, dass der Rechner auf nichts anderes reagiert, solange der Test läuft.Zusammenfassung:
Ist es möglich, einen Pin vom Druckerport für z. B. 70 Mikrosekunden auf 'high' zu setzen.Thx
Martin
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Rund um die Programmierung in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
{EDIT] Müll :
Ein Takrate von 50 us entspricht auf nem 3GHz Proz 167 CPU Takten - hier incl des INT und des IRET(!).
[/EDIT]Das heisst dass Du den IRQ Controller so programmieren musst das er nur noch das LPT-IRQ durchlässt - wenn die CPU nämlich gerade ein INT(R) abarbeitet sind alle anderen INTS blockiert ausse #2 ( = NMI ) und dann wärs schon zu langsam.
{EDIT] Müll :
ABER : Wie will Du das die Taktung über LPT überhaupt realisieren? Vielleicht sthe ich ja grad im Feld aber die hat doch viel höhrere Latenzzeiten, oder?[/EDIT]Grüsse
*this
-
3GHz == 3 Milliarden
=> Die CPU müsste doch im Nanosekundenbereich ihre Befehle abarbeiten?Was die LPT angeht:
Es existiert bereits ein DOS basiertes Tool, welches funktioniert.
Ich muss zugeben, dass ich noch nicht nachgemessen hab, ob das wirklich auf
die Mikrosekunde genau geht, aber es läuft zumindest ausreichend genau.
Drum geh ich davon aus, dass die Geschwindigkeit der Schnittstelle das geringste
Problem darstellt.Dann läßt sich also sagen, dass es mit einem Kerneltreiber funktioniert,
unter der Voraussetzung, dass die Schnittstelle mitspielt?Werd mich dann mal in die Treibergeschichte einlesen und vielleicht um
die eine oder andere Erkenntnis reicher werden.Danke.
-
Windows (egal welche Version) ist ohne eigene "Extensions" nicht Echtzeitfähig. Mit einem Treiber kann man zwar die durchschnittlichen Latenzzeiten deutlich verkürzen, ändert aber Grundsätzlich nix.
Mikrosekundenbereich kannst du IMHO vergessen. Auf ~~1ms ja, vielleicht, mit Bauchweh, aber auch nur wenn nix wichtiges davon abhängt.
Mit selektierter Hardware und selektierten Treibern sollte deutlich weniger als ~~1ms möglich sein, ob man in den Microsekundenbereich kommt ... weiss nicht ... mich würde es wundern. Kritisch darf die Anwendung aber auch mit selektierter Hardware nicht sein.
Nicht selektierte PC Hardware ist - egal welches OS - nicht Echtzeitfähig, da es immer noch das BIOS gibt, und dieses oft den SMI (den du softwaremässig nicht maskieren kannst, zumindest gibt es keinen Standard dafür) verwendet um diverse Hardware Fehler auszubügeln.Dann läßt sich also sagen, dass es mit einem Kerneltreiber funktioniert,
unter der Voraussetzung, dass die Schnittstelle mitspielt?Nein (siehe oben).
EDIT:dann müsste sich sowas doch in einer Interrupt Routine (=höchste Priorität) machen lassen.
Du brauchst keinen ISR, du brauchst wenn dann KeRaiseIrql(). Wenn du damit auf CLOCK_LEVEL oder sowas brutales hochgehst ist das so ziemlich das Beste was du mit Windows hinbekommen wirst.
Aber selbst dann kannst du noch von diversen Dingen für (relativ) kurze Zeit unterbrochen werden.
Wenn dann ein Interrupt getriggert wird, während dein Thread mit z.B. CLOCK_LEVEL läuft, dann wird der zuständige ISR zwar nicht ausgeführt, aber es kann sein dass der Interrupt Handler von Windows selbst noch angesprungen wird, und erst dort dann die Interrupts gesperrt, damit dein Thread weitermachen kann. Das erfordert ein paar Port Zugriffe, und die sind oft ordentlich langsam.
-
probier's einfach aus:
disable alle interrupts, toggle mit hoher frequenz den druckerport und schliess ein oszilloskop an (am besten eins, das auf anomalien triggerbar ist, wie verlängerte pulse oder pausen). wenn ein sauberes signal zu sehen ist, also ohne irgendwelche aussetzer, dann funzt es.

btw: i2c ist sowieso nicht besonders zeitkritisch.
-
anonymus schrieb:
3GHz == 3 Milliarden
=> Die CPU müsste doch im Nanosekundenbereich ihre Befehle abarbeiten?Aeehh, ja, kleiner Rechenfehler von mir...
Vergiss also am besten mein Geschwätz von gestern.
Grüsse
*this
P.S.: Wer lacht da? Einstein hat sich afaik mal um über 60 Grössenordnungen verschätzt - bei mir waren's nur drei!
-
Gast++ schrieb:
anonymus schrieb:
3GHz == 3 Milliarden
=> Die CPU müsste doch im Nanosekundenbereich ihre Befehle abarbeiten?Aeehh, ja, kleiner Rechenfehler von mir...
Vergiss also am besten mein Geschwätz von gestern.
Grüsse
*this
P.S.: Wer lacht da? Einstein hat sich afaik mal um über 60 Grössenordnungen verschätzt - bei mir waren's nur drei!
Sind denn 3GHz nicht 3 Milliarden Takte pro sekunde?
kilo = tausend.
mega = millionen
giga = milliarden1 Nanosekunde = 1000 Picosekunden = 10^-9 Sekunden
also 3 Takte pro Nanosekunde. Oder verrechne ich mich auch?oder etwa nicht?
-
Ja es sind genau 333,3... pikosekunden pro takt:
3Ghz = 3.000.000.000 Hz
1 Takt = 3,333... * 10^-10 sekunden | *1000
1 Takt = 3,333... * 10^-7 ms | *1000
1 Takt = 3,333... * 10^-4 µs | *1000
1 Takt = 0,333... ns | *1000
1 Takt = 333,3... ps
-
hustbaer schrieb:
Windows (egal welche Version) ist ohne eigene "Extensions" nicht Echtzeitfähig. Mit einem Treiber kann man zwar die durchschnittlichen Latenzzeiten deutlich verkürzen, ändert aber Grundsätzlich nix.
Mikrosekundenbereich kannst du IMHO vergessen. Auf ~~1ms ja, vielleicht, mit Bauchweh, aber auch nur wenn nix wichtiges davon abhängt.
Mit selektierter Hardware und selektierten Treibern sollte deutlich weniger als ~~1ms möglich sein, ob man in den Microsekundenbereich kommt ... weiss nicht ... mich würde es wundern. Kritisch darf die Anwendung aber auch mit selektierter Hardware nicht sein.
Nicht selektierte PC Hardware ist - egal welches OS - nicht Echtzeitfähig, da es immer noch das BIOS gibt, und dieses oft den SMI (den du softwaremässig nicht maskieren kannst, zumindest gibt es keinen Standard dafür) verwendet um diverse Hardware Fehler auszubügeln.Dann läßt sich also sagen, dass es mit einem Kerneltreiber funktioniert,
unter der Voraussetzung, dass die Schnittstelle mitspielt?Nein (siehe oben).
EDIT:dann müsste sich sowas doch in einer Interrupt Routine (=höchste Priorität) machen lassen.
Du brauchst keinen ISR, du brauchst wenn dann KeRaiseIrql(). Wenn du damit auf CLOCK_LEVEL oder sowas brutales hochgehst ist das so ziemlich das Beste was du mit Windows hinbekommen wirst.
Aber selbst dann kannst du noch von diversen Dingen für (relativ) kurze Zeit unterbrochen werden.
Wenn dann ein Interrupt getriggert wird, während dein Thread mit z.B. CLOCK_LEVEL läuft, dann wird der zuständige ISR zwar nicht ausgeführt, aber es kann sein dass der Interrupt Handler von Windows selbst noch angesprungen wird, und erst dort dann die Interrupts gesperrt, damit dein Thread weitermachen kann. Das erfordert ein paar Port Zugriffe, und die sind oft ordentlich langsam.Das macht natürlich wenig Hoffnung.
Wenn da nicht weniger als eine Millisekunde drin ist.
5-6 ms Reaktionszeit kriegt man ja schon im Usermode hin
(gut, nicht garantiert, aber gemessen hab ich nie mehr...)Von einem Treiber hätt ich mir doch einiges mehr erwartet.
Sorry, was ist "selektierte Hardware"? Google bringt mich ned wirklich weiter.
Najo, jetzt geht's erstmal a paar Tage nach Italien.
Und dann mal schaun, wie's weitergeht.
Aber schaut dann wohl ned so gut aus...mfg
Martin
-
selektiert: ausgewählt.
-
gerade neue News bei tecchanel, da musste ich gleich hieran denken

http://www.tecchannel.de/news/themen/entwicklung/470000/index.htmlschirrmie
-
schirrmie schrieb:
gerade neue News bei tecchanel, da musste ich gleich hieran denken

http://www.tecchannel.de/news/themen/entwicklung/470000/index.htmlHab mich da mal a bissl eingelesen und das schaut ganz vernünftig aus.
Allerdings macht das von Hustbaer vorgeschlagene "KeRaiseIrql()"
auch eine ganz gute Figur.Da werd ich jetzt einfach mal viel lesen müssen.
Anhaltspunkte hab ich jetzt zumindest schon mal.Thx @all.
-
hallo
WIndows XP ist grundsätzlich nicht Echtzeitfähig, allerdings kann mit einigen Tricks schon sehr zeitkritische Anwendungen realisieren. Dein Problem sollte sich mit einem Kernelmodetreiber eigentlich locker realisieren lassen, sofern die Hardware mitspielt. Als beispiel kann man im Kernelmode Timer Initialisieren (XP), welche in 100 ns Intervall angegeben werden.
Millisekunden sollten da ebenso möglich sein.
Allerding ist die einarbeitung in dieses Thema schon recht aufwendig und die Dokomentatinen recht rar, ausser das Windows DDK.
-
IIRC kann man zwar in 100ns Schritten das Timeout angeben, der Timer wird aber dadurch nicht genauer. D.h. die Genauigkeit mit der der dann feuert ist genauso durch die Frequenz mit der der Scheduler aufgerufen wird begrenzt. Also üblicherweise ~15ms bzw. minimal 1ms wenn man die Frequenz "runterdreht".
-
Hab mir das Protokoll nochmal genauer angeschaut und muss sagen, dass es eigentlich keine Echtzeitimplementierung in dem Sinne ist, dass innerhalb einer bestimmten Zeit auf ein Ereignis reagiert werden muss.
Vielmehr ist es so, dass es (fast) egal ist (ca. 10 ms dürfen vergehen, und die sollte man sogar im Usermode hingekommen, zumindest warens über RS232 mal ~6ms) wann eine Funktion abgearbeitet wird,
es muss nur sichergestellt sein, dass sie, wenn sie mal arbeitet, nicht mehr
unterbrochen wird.
Und das müsste mit dem "KeRaiseIrql()" doch möglich sein, mit allen Einschränkungen die sich draus ergeben (hab ein Dokument gefunden, wo drin steht,
dass man z. B. drauf achten muss, dass man keinen Speicher verwendet, der
ausgelagert werden kann, falls das Level höher als XX gewählt wird).Was ich dann allerdings brauch ist eine Counter, den man abfragen kann, wieviel Zeit vergangen ist, so dass man in einer Schleife eine bestimmte Zeit warten kann.
Der Time Stamp Counter wäre zwar so ein Kandidat, aber was ich so gelesen hab, ist der nicht allzu verlässlich (grade in Systemen mit mehr als einem Kern weil dann zwei Counter laufen, die nicht zwingend gleiche Werte haben, auch Hyperthreading soll da schon Probleme machen... oder falls die Taktfrequenz von der Last abhängt)
Auf der anderen Seite, wenn der Code nicht unterbrochen wird, dann müsste doch sichergestellt sein, dass er nur auf einem Kern läuft und somit müsste der TSC trotzdem OK sein.APIC timer wäre evtl. eine Alternative, aber da hab ich noch nix gefunden, wie man da rankommt...
-
anonymus schrieb:
APIC timer wäre evtl. eine Alternative, aber da hab ich noch nix gefunden, wie man da rankommt...
http://www.microsoft.com/whdc/system/CEC/mm-timer.mspx
http://rtg.informatik.tu-chemnitz.de/docs/vortraege/def-sa-wiet.pdf
http://plan9.bell-labs.com/sources/plan9/sys/src/9/pc/apic.c

-
Für "muss in 10ms erledigt sein" wird's KeRaiseIrql wohl tun, aber ganz "ununterbrochen" läuft man auch dann nicht - wenn ein Interrupt auftritt kann das schnell mal ein Unterbrechung von ein paar hundert oder tausend nanos sein, selbst wenn der Interrupt einen niedrigeren IRQL hat als der mit dem man gerade läuft. Nur zur Info. (Wie lange solche Unterbrechungen genau sein werden, und wie oft man damit rechnen muss kann niemand so genau sagen, das hängt u.A. auch von der verwendeten Hardware ab, und was das System gerade noch tut).
Vonwegen Timer ... warten kannst du mit KeStallExecutionProcessor (busy wait). Längere Zeiten kann man mit KeDelayExecutionThread warten, allerdings nur auf PASSIVE_LEVEL, und nur mit sehr grober Auflösung.
Ansonsten gibt es noch KeQueryInterruptTime (was wahrscheinlich zu ungenau sein wird) und KeQueryPerformanceCounter. Ob KeQueryPerformanceCounter für dich funktionieren wird kann ich nicht sagen, ich hab' mit dem performance counter auf jeden Fall schlechte Erfahrungen gemacht, allerdings war das im Usermode.
-
kann mir jemand sagen was es mit den isa/pci-steckkarten auf sich hat die eigene timer haben? kann man die für sowas gebrauchen oder sind die nur zum zeitmessen da um den wert dann auszulesen?
-
Zur Info:
Hab's jetzt nachgemessen:Die Signalzeiten werden auf ca. 2µsec genau eingehalten.
=> gut so.Falls die Reaktionszeit interessiert:
Wenn sich an einem Pin der parallelen Schnittstelle ein Wert ändert,
läßt sich innerhalb von 3µsec ein anderer Pin ändern.
=> auch gut.Übrigens waren 3µsec auch die minimalen Signalzeiten, weniger war nicht möglich.
Dazu Interrupts mittels _asm{cli} deaktiviert, im Anschluss mit _asm{sti} wieder aktiviert.
Ab IRQL 28 auch brauchbare Ergebnisse in ähnlicher Größenordnung,
alles unter 28 ist grauenhaft
mfg
Martin