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
@ 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?
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?
@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
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.
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.
Daniel G. schrieb:
> Wie kann ich denn ein Register reservieren in C mit GCC?
1
registeruint32_tmyflagasm("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.
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