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?
Die Schleife kann auch einfach nur eine bool-Variable abfragen, die beim Timeout durch den Timer gesetzt wird.
Man könnte das auch mit einem RTOS machen. Sobald der Timer abgelaufen ist, killt ein zweiter Überwachungs-task den ersten.
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 | 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.