Forum: Compiler & IDEs Timeout über Zeitkritische Funktion


von Daniel G. (motello)


Lesenswert?

Hallo,

ich habe eine 'round robin with interrupts' Architektur und im Taskmode 
eine zeitkritische Funktion die aufgrund von Warteschleifen stecken 
bleiben kann und die ich daher mit einem Timeout versehen will. Wenn die 
Zeit abgelaufen ist, soll die Funktion einfach beendet werden.

Ich möchte aus zeitlichen Gründen nicht in jede Warteschleife einen 
Timeout einbauen und abfragen, sondern nur einen der über einen 
Timer-interrupt gesteuert wird. Der Timer wird normalerweise in 
regelmäßigen Abständen auf null gesetzt.

Ich habe mir Folgendes überlegt:
Ich markiere die Funktion als __attribute__((naked)) und rufe sie statt 
direkt über eine Assembler Routine auf. Diese Assembler Routine stellt 
wiederrum eine Adresse zur Verfügung, die angesprungen werden kann, wenn 
der Timeout Triggert. Es wird das Ende also von einer  also von einer 
Interrupt Routine angesprungen.

Die Interrupt Routine würde also den PC-wert aus dem Link Register 
manipulieren, so dass direkt an das Ende der Assembler Routine 
gesprungen wird.

Was haltet Ihr davon und hat jemand eine bessere Idee? Das Problem was 
ich sehe: Das Programm wird dadurch sehr verkompliziert, so dass eine 
Weiterentwicklung durch andere Entwickler erschwert wird (die 
höchstwahrscheinlich nur nebenbei programmieren).

Grüße
Daniel

von Falk B. (falk)


Lesenswert?

@  Daniel G. (motello)

>Was haltet Ihr davon

Nix. Klingt alles viel zu kompilziert nun nach Hackermist.

> und hat jemand eine bessere Idee? Das Problem was
>ich sehe: Das Programm wird dadurch sehr verkompliziert, so dass eine
>Weiterentwicklung durch andere Entwickler erschwert wird (die
>höchstwahrscheinlich nur nebenbei programmieren).

EBEN!

Mach es DIREKT RICHTIG!

Sprich, deine Funktion jedes Mal den Softwaretimer abfragen. Geht halt 
nicht anders. Ist auch OK. Vergiss das volatile nicht, siehe 
Interrupt.

MFG
Falk

P S Was muss denn das so furchtbar schnell abgearbeitet werden, dass 
eine einfach Variablenprüfung nicht drin ist?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Die Schleife kann auch einfach nur eine bool-Variable abfragen, die
beim Timeout durch den Timer gesetzt wird.

von Klaus F. (kfalser)


Lesenswert?

Man könnte das auch mit einem RTOS machen.
Sobald der Timer abgelaufen ist, killt ein zweiter Überwachungs-task den 
ersten.

von Daniel G. (motello)


Lesenswert?

Es ist eine Schleife die einen knapp 500Byte Datenblock per 
EPP-Handshake ließt und per UDP verschickt. In jedem Handshake (1 Byte) 
sind zwei Schleifen drin, in die noch die Timeout-Flag-Abfrage rein 
müsste. Das läppert sich...

Ich habe noch andere Möglichkeiten der Optimierung (Cache Lockdown, das 
ganze in einen kleinen SRAM Bereich statt SDRAM verschieben, ich glaub 
ich mache es wirklich nicht.

Mir ist gerade beim schreiben noch eine bessere Idee gekommen: Ich 
könnte ein Register nutzen um das Flag zu speichern (auf das auch direkt 
die Interrupt routine zugreift und es ggf. ändert). Aber das wird wohl 
daran scheitern, dass man keine register in C (GCC) reservieren kann, 
oder?

von Falk B. (falk)


Lesenswert?

@Daniel G. (motello)

>sind zwei Schleifen drin, in die noch die Timeout-Flag-Abfrage rein
>müsste. Das läppert sich...

Probier es doch mal REAL aus, sprich Simulator und reale Anwendung. DANN 
reden wir weiter.

>daran scheitern, dass man keine register in C (GCC) reservieren kann,
>oder?

Theoretisch ja, praktisch wird das immer weniger möglich. Aber da du 
eine fetten 32 Bitter scheinbar hast, ist deine Befürchtung 
wahrscheinlich unbegründet.

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

IMHO beißt sich bereits das

> zeitkritische Funktion die aufgrund von Warteschleifen stecken
> bleiben kann und die ich daher mit einem Timeout versehen will.

zeitkritische Funktionen und Warteschleifen passen nur selten zusammen. 
Wobei das Problem auf seiten der Warteschleifen liegt.

von Daniel G. (motello)


Lesenswert?

Das ganze läuft längst REAL und ich habe auch bereits Messungen 
vorgenommen, zumindest an der ganzen Leseroutine. Damals hatte ich 
allerdings mehr als nur eine Flag-Abfrage drin sondern habe einen 
Timer-Wert gelesen, berechnet und verglichen. mit der Flag-Abfrage 
könnte ich es wirklich noch mal probieren. wenn das Flag im Cache liegt, 
hat es vielleicht gar nicht so große Auswirkungen.

Diese Routine ist mit der, die den Datenblock dann sendet (über 
Ethernet/UDP) die einzige Zeitkritische. Das ganze muss so schnell wie 
möglich sein, um eine DFT so schnell wie möglich zu ermöglichen um eine 
möglichst hohe Regelbandbreite zu erzielen. Jedenfalls sind die 
Anforderungen noch nicht klar, daher so schnell es geht :-)

Wie kann ich denn ein Register reservieren in C mit GCC?

Die Wartezeiten sind übrigens so gering, dass selbst ein einfacher 
Kontextswitch um etwas anderes zu machen, in den allermeisten Fällen 
länger dauern würde als das bisschen warten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Daniel G. schrieb:

> Wie kann ich denn ein Register reservieren in C mit GCC?
1
register uint32_t myflag asm("r2");

Dummerweise funktioniert register...asm nicht zusammen mit volatile.
Kann also sein, dass der Optimizer die Zugriffe dann wegoptimiert.
Dann solltest du auf eine normale Speichervariable (volatile!)
zurück greifen.

von Daniel G. (motello)


Lesenswert?

Hallo,

habe Timeouts nun auf "herkömmlichem" Wege eingebaut. Durch geschicktes 
Abfragen hält sich die Geschwindigkeitseinbuße sehr in Grenzen: Der 
Timer wird nur selten zurückgesetzt und hat demnach eine höhere Zeit, 
was hier nicht stört. Das Timeout-flag wird nur abgefragt, wenn die 
Warteschleife überhaupt mal ausgeführt wird, was eher selten der Fall 
ist, weil die Wartebedingung meist nicht erfüllt wird.

So ist der Code schön lesbar und einheitlich geblieben :-) Die 
Weiterentwickler werden es danken. Danke für die Tipps!

Schöne Grüße und frohes fest!
Daniel

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.