Hallo, ich wollte mich hier gerade mal absichern, ob ich nicht doch einen Denkfehler habe. Egal ob folgender Code sinn macht oder nicht, gibt es einen effektiven Unterschied oder ist es völlig egal wie ich es schreibe? Version 1 (die wohl sinnvolle und übliche Schreibweise): sr: push r16 in r16, SREG push r16 //Serviceroutine in der mit r16 gearbeitet wird pop r16 out SREG, r16 pop r16 reti Version 2: sr: rcall up reti up: push r16 in r16, SREG push r16 //Unterprogramm in dem mit r16 gearbeitet wird pop r16 out SREG, r16 pop r16 ret Zusammengefasst: ist es egal ob ich meine Register/SREG vor dem ersten UP oder in diesem aufrufe? Vielen Dank für euer Reindenken! Gruß, Andreas
>ob ich nicht doch einen Denkfehler habe. Was denkst Du denn? >sinnvolle und übliche Schreibweise Welcher Sinn? >ist es egal ob ich meine Register/SREG vor dem ersten >UP oder in diesem aufrufe? In welcher Hinsicht? Ein Blick auf die Beschreibung des Prozessors und der Befehle sollte Dir helfen Deine Frage neu zu formulieren.
>Zusammengefasst: ist es egal ob ich meine Register/SREG vor dem ersten >UP oder in diesem aufrufe? Ich meine natürlich "sichere" anstatt "aufrufe".
Ich bin der Meinung, das beide Schreibweisen das absolut gleiche bewirken. Es also egal ist, ob ich die Register erst im up auf den Stapel lege/später rette, oder schon in der Service-Routine. Oder anders gefragt, hat ein einfacher Unterprogrammaufruf (über rcall oder call und ein logisch später folgender Rücksprung ret) eine auswirkung auf das SREG-Register bzw. sonstige Register? Ich würde sagen nein! Habe ich da recht oder nicht??? Und mit den Rücksprungadressen (durch die SR bzw. UP) dürfte es doch da auch keine Konflickte im Programmablauf geben, oder? Ich arbeite mit einem Atmega 32, wobei das bei dieser Frage relativ unerheblich sein dürfte, oder habe ich unrecht? Gruß, Andreas
Hi, bin zwar nit wirklich fit mehr und habe es auch nur im Kopf schnell überflogen, wie der Stack arbeitet. Aber ich behaupte einfach mal beides geht(warum testest du das nit selber im Avr-Studio ?). Wobei die erste Version schon besser zu lesen war ;-) Gruß
Andreas schrieb: > Ich bin der Meinung, das beide Schreibweisen das absolut gleiche > bewirken. Es also egal ist, ob ich die Register erst im up auf den > Stapel lege/später rette, oder schon in der Service-Routine. Hallo, die Frage lautet: ändert ein Call irgendein Register ausser dem Programmzähler? Wenn nein, ist es egal. Es gibt einfache Prozessoren, bei denen der Programmspeicher segmentiert ist und bei denen daher ein long call ein Pointerregister verändert (oder ohne eine solche Änderung unmöglich ist), aber deiner gehört meines Wissens nicht dazu. RTFM: irgendwo muss es eine Beschreibung geben, in der für jeden Befehl steht, was er verändert. Gruss Reinhard
Es muß immer nur das gerettet werden, was zwischen dem Einsprung in die ISR und dem 'reti' verwendet wird. Ob zwischendurch noch eine Unterroutine aufgerufen wird, ist völlig egal. Hauptsache, es ist alles gesichert und wird später, vor dem 'reti', vom Stack wieder abgeholt. Abgesehen davon sollte man Interrupt-Service-Routinen zeitlich so kurz wie möglich gestalten, also auch unnötige Sprünge vermeiden, um die Hauptschleife nicht zu lange zu blockieren.
Hallo! Ganz trivial ist die Frage nicht abzutun. Die zweite Variante verbraucht mehr Stack-Speicher!!! Bei vielen MC liegen die Interrupt-Einsprungstellen an definierten Adressen. Es kann durchaus Sinn machen, die ganze Interruptroutine nicht dort unterzubringen. Dann sollte man aber mit einem JUMP (evtl. relativ SJMP RJMP JR... -je nach Prozessor) zur eigentlichen Routine SPRINGEN und dort nicht mit RET sondern mit RETI beenden. Das ist z.B. bei ATTinys mit begrenztem (Hardware-)Stack überlebenswichtig.
Hi Ein Unterprogramm macht nur dann Sinn, wenn die Routine mehrfach im Programm benötigt wird. Wenn der Aufruf auch aus dem Programm erfolgt, ist das Sichern von SREG um Unterprogramm sinnlos. Und da das Sichern von SREG (meist) notwendiger Bestandteil einer ISR ist, sollte es auch dort erfolgen. MfG Spess
Noch ein paar weitere Betrachtungspunkte: Die ISR soll kurz und schnell sein. Der AVR hat 32 Register, von denen viele Beginner nur die oberen 16 verwenden, da sie mit den unteren 16 nix anzufangen wissen. ;-( Es lohnt sich daher, ein unteres Register exklusiv für die SREG-Sicherung zu benutzen. *IN r2,sreg* / *out sreg,r2* Ein Unterprogrammaufruf in der ISR ist nur dann sinnvoll, wenn dieses Unterprogramm auch von anderen Stellen des Programms aufgerufen wird. Ansonsten verplempert der Aufruf lediglich 7 Prozessortakte. Das ist erstmal nicht viel, aber es läppert sich zusammen, da ISRs meist recht oft aufgerufen werden können. Bei einer Timer-ISR mit 10ms Intervall ist das unwichtig, bei Intervallen im µs-Bereich zählt aber jeder Takt. Viele Aufgaben lassen sich auch außerhalb der ISR erledigen. In der ISR werden dann nur flüchtige Werte gesichert und ein Merker gesetzt, der von der Mainloop zum bedingten Aufruf eines Jobs ausgewertet wird. Dieser Job löscht dann auch den Merker wieder. Sorgt man dafür, dass die Jobs kurz und schnell bleiben, dann gibt es keine Probleme (verpasste Jobs). Unvermeidliche lange Jobs können ja an geeigneter Stelle die Merker der kleinen, oft auftretenden Jobs zusätzlich prüfen und diese Jobs mal schnell zwischendurch erledigen. Mega32... Nunja, das suggeriert Reserven. Denn das Ding hat viel Flash, ausreichend RAM und auch etwas EEP. Das alles verführt dazu, möglichst viele Funktionen unterzubringen, aber auch dazu, ineffizient zu programmieren. Und betreffs Rechenleistung hat der Mega32 keinerlei Vorteile gegenüber kleineren AVRs. ...
Vielen Dank für die Zahlreichen sinnvollen Antworten. Meine Zweifel sind damit endgültig behoben!
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.