nntp2http.com
Posting
Suche
Optionen
Hilfe & Kontakt

Timer unter RTai - rt set periodic mode ist nicht periodisch.

Von: Martin Freiberg (lyki_@web.de) [Profil]
Datum: 26.02.2009 22:03
Message-ID: <go6vr8$lue$03$1@news.t-online.com>
Newsgroup: de.comp.os.unix.programming
Hallo,

Bei meinen Basteleien möchte ich unter Linux mit RTai einen
zyklischen Timer laufen lassen.

Linux Vanilla Kernel 2.6.23
RTai 3.6.1

Stark gekürzt:

include tralala...

RT_TASK my_Timer;           // Zeiger auf Timer-Function
RTIME expected;
RTIME period_counts;
int period = 50000;
int intrcount = 0;          // Zaehlschleife

// hier sonstiges .....

void my_Timertask(long my_Timer) {

++intrcount;

// hier noch anderes Zeug ...
}

int init_module (void) {     // Modul initialisierung

printk (KERN_INFO ": Modul Initialisierung gestartet\n");
// hier noch diverse andere Codezeilen...

rt_task_init(           /* create our measuring task         */
&my_Timer,    /* poiter to our RT_TASK             */
my_Timertask, /* implementation of the task        */
0,            /* we could transfer data -> task    */
5000,         /* stack size                        */
0,            /* priority                          */
0,            /* do we use the FPU? 0 = No         */
0             /* signal? XXX                       */
);
rt_set_periodic_mode ();
period_counts = start_rt_timer (nano2count(period));
expected = rt_get_time();
rt_task_make_periodic (&my_Timer,expected,period_counts);

printk (KERN_INFO "Modul erfolgreich installiert\n");
return (0);
}

void cleanup_module (void) {     // Modul sauber deaktivieren

stop_rt_timer();
rt_task_delete(&my_Timer);

// hier noch div. anderes Zeug ....
printk (KERN_INFO "Modul Resourcen wieder freigegeben\n");
}


:# modprobe mytreiber

:# cat /proc/myTreiber
1

:#


Die Variable intrcount lasse ich über das /proc Dateisystem
anzeigen. Sie wird bei diesem Beispiel nur einmal inkrementiert
was bedeutet, das die Funktion definitiv nur einmal aufgerufen
wird und nicht periodisch. Initialisiere ich intrcount mit 3
wird 4 ausgegeben.

Für einen einmaligen Durchlauf würde normalerweise ein
rt_set_oneshot_mode ();
verwendet.


Sämtliche Beispiele die ich gefunden habe verwenden in der
Timerroutine als Hack eine Endlosschleife mit while (1),

void my_Timertask(long my_Timer) {
while (1) {
++intrcount;
rt_sleep (period);
}
}

und für die Verzögerung ein rt_sleep Kommando.  :(


Aber das kann es ja auch nicht sein. Die Lösung ist sehr
unsauber. Denn der Aufruf erfolgt so definitiv nicht exakt,
sondern schwankt mit der Dauer die diese Funktion selber
benötigt. Wenn ich hier eine Schwankung von +- 1 ms habe,
dann erfolgt der Aufruf ebenfalls mit +- 1 ms (50 ms +
Durchlaufzeit) anstatt wie eigendlich gewünscht exakt alle
50 ms (  0 mal in der Sekunde).

Dieses fehlerhafte Beispiel für die Timerschleife entstammt
übrigend aus einem Demo-Beispiel von rtai
rtai/testsuite/kern/latency/latency-module.c

(Siehe Zeile 150)
Und hier hätte ich ein korrektes Beispiel erwartet.  :(

Wo ich auch noch einen Fehler in dem Beispiel sehe ist,
das ein zweifaches einstellen für periodic verwendet wird,
und im Singledurchlauf einmal oneshot und dann wieder ein
periodic. Der Fehler wird zugleich durch eine geänderte
Berechnung in der Funktion kaschiert (Zeile 162).

Meiner Ansicht nach müsste entweder hier Rtai selber die
Funktion regelmässig aufrufen (wegen dem periodic-Befehl)
oder zumindest in der Funktion durch einen Befehl dies
veranlassen (so wie mit einem normalen Kerneltimer).

Kennt jemand ein korrektes funktionierendes Beispiel
ohne die while(1) Hilfskrücke oder Abhilfe?


Gruß
Martin

[ Auf dieses Posting antworten ]

Antworten