Timingverhalten in Windows-Treiber

#1499708
Lesenswert?

Hallo,

Ich habe ein Problem das Timingverhalten in einem selbstgeschriebenen 
Windows-Treiber zu verstehen.
Vielleicht kann mir jemand helfen ... oder sagen wonach ich suchen muss.

Unter MinGW habe ich auf einem XP-Rechner einen kleinen Treiber 
programmiert.
Später soll über eine Dauer von 2 sec alle 2,5 microsec der Parallelport 
ausgelesen werden (tickstep=22 entspricht 2,5 microsecs).
Da Windows so große Zeitscheiben nicht sicher zur Verfügung stellen 
kann, sperre ich alle Interrupts und akzeptiere für die Messzeit einen 
"eingefrorenen" Windows-Rechner.

Die Funktion tick256th() gibt das Ergebnis vom Assemblerbefehl "rdtsc" 
zurück. Allerdings werden von den ursprünglich 64 Bit nur Bit 39-8 
zurückgegeben, da es vollkommen ausreicht und ich auf long 
long-Berechnungen verzichten kann. Damit ist der zurückgegebene 
Prozessortakt durch 256 geteilt.
Die vorerst auskommentierte Funktion InPort() führt den Assemblerbefehl 
"inb" aus.

Hier eine kurze Sequenz aus dem Treiber:
1
  unsigned int i, j;                         // counters
2
  unsigned int tickendwait, tickdiff;        // all in ticks256th
3
  unsigned int tickstep=22;                  // this is 2,5 micro secs
4
  unsigned int maxnumber=800000;             // 800000*2,5 => 2sec
5

6
  tickendwait=tick256th()+tickstep;          // when reached tickendwait, a new action is required
7
  asm ("cli");                               // disable interrupts, no system reaction for a specific time
8
  for(j=0; j<maxnumber; j++) {               // main loop to collect data
9
    for (i=0;;i++) {                         // wait for next action
10
      tickdiff=tick256th()-tickendwait;      // if tickdiff is negative: continue waiting
11
                                             // if tickdiff is zero: reached end time exactly now 
12
      if (tickdiff<0x80000000) {             // if tickdiff is positive: end time is in the past, break, action now
13
        tickendwait+=tickstep;               // calculate next tickendwait
14
        break;
15
      }
16
    }
17
    /* ACTION */
18
//    pio_field->i_port[j]=(InPort(0x379)&0xF8)^0x80;  // read port and fill in (bit7-3 without inversion)
19
    pio_field->i_port[j]=i;
20
    pio_field->tickoffset[j]=tickdiff+tickstep;        // fill in tickoffset in tick/256
21
  }
22
  asm("sti");                                // enable interrupts

Grundsätzlich funktioniert das Programm, doch folgende Dinge fallen mir 
auf:
1.) Mit i kann man zählen, wie oft die Warteschleife durchlaufen wurde, 
bis die nächsten 2,5µm verstrichen sind. Es werden bei meinem Prozessor 
(2,3MHz) ca. 309-310 Durchläufe verbraucht (96%). Doch in 4% der Fälle 
zeigt der Schleifenzähler kleinere Werte (235-308)! WARUM? Wenn 
Interrupts gesperrt sind, wer kann denn noch Prozessorticks verbrauchen? 
Dieses Verhalten ist reprodizierbar.
2.) Wenn die Zeile zum Einlesen des Ports (mit InPort()) wieder 
einkommentiert wird, ist der Effekt noch viel größer. Erwartet hätte ich 
eine (konstante) Verringerung der Durchläufe, aber stattdessen kann in 
26 Fällen von 800000 nicht einmal das Timing von 2,5µm eingehalten 
werden! Der Durchlaufzähler bleibt bei 0(!!!) und tickdiff hat einen 
Wert von bis zu 15, was einer Verspätung  von 1,7µm entspricht!!!

Wer oder was klaut Prozessorticks? Kann/muss noch etwas abgeschaltet 
werden?

Vielen Dank schon im voraus für eine hilfreiche Antwort
Persönliche Seite #1499719
Lesenswert?

I/O-Zugriffe auf den Parallelport sind sehr langsam, da hier noch 
Fragmente des alten ISA-Busses in der PC-Architektur fortleben.
Um das auszuprobieren, schreib' mal eine Variante, die nur einen Pin 
hin- und herschaltet und häng ein Oszilloskop daran. Mehr als ein paar 
MHz wirst Du nicht messen können, auch wenn Dein Rechner mit noch so 
vielen GHz Takt betrieben wird.

Nicht nur aus diesem Grund halte ich Dein Unterfangen für einen 
Designfehler.
#1499745
Lesenswert?

Nachmessen ist natürlich das Einzig richtige, doch leider habe ich kein 
Oszilloskop zur Hand. Ich weiß aber, dass beispielsweise alte 
Flasherprogramme für Handys über meinen Parallelport vergleichbare 
Datenraten korrekt übertragen können. -> Tests werden es dann zeigen...

Die Hauptfrage für mich im Moment ist aber, warum das Zeitverhalten 
nicht streng wiederholbar ist, sondern sich offensichtlich trotz 
abgeschalteter Interrupts von Außen verändern lässt.
Wer stört da?
#1499791
Lesenswert?

Danke für den Hinweis.
Ein zweiter XP Rechner mit 2,9MHz zeigt ein vergleichbares Verhalten. 
Die Zeiten sind andere, aber die Effekte ähnlich.
Aber das ist natürlich kein Beweis...

Kann man etwas Konkretes noch abschalten?
Wie gesagt: Es läuft Software auf dem Rechner, der das Timing 
zuverlässig schafft.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren