Hallo an alle,
durch Push Befehle können Register Inhalte auf den Stack gesichert
werden und durch Pop Befehle können diese wiederhergestellt werden.
Ich habe eine Interrupt Routine, die sehr zeitkritisch ist und möchte
diese daher so effizient wie möglich gestalten.
Hardwareseitig habe ich ein MyAVR MK2 Board mit einem ATmega8 @8MHz
µProzessor.
Generell programmiere ich in C und Nutze AVR Studio.
Die Interrupt Routine ist aber bereits in Assembler geschrieben.
Mein Gedanke war, dass ich doch eigentlich nur meinen Compiler mitteilen
müsste, dass dieser bestimmte Register des Prozessors außerhalb des
Interrupts nicht benutzen darf.
Bei mir sind es im Ganzen nur 5 Stück (siehe Code).
Wenn diese Register außerhalb der Interrupt Routine nicht genutzt werden
würden, wäre es dann nicht möglich auf Push und Pop zu verzichten?
Gibt es dafür vielleicht einen Weg, den man gehen kann, ohne den
kompletten Code in Assembler schreiben zu müssen?
1
ISR(SCL){
2
push r1
3
push r0
4
in r0, 0x3f ; 63
5
push r0
6
eor r1, r1
7
8
push r24//
9
push r25//
10
push r26//Die hier würde ich gerne weglassen
11
push r27//
12
push r28//
13
14
lds r24, 0x006D
15
lds r25, 0x006E
16
lds r26, 0x006F
17
lds r27, 0x0070
18
19
lsr r27
20
ror r26
21
ror r25
22
ror r24
23
24
sbic 0x13, 0 ; 19
25
ori r27, 0x80 ; 128
26
27
lds r28, 0x0069
28
29
inc r28
30
sts 0x0069, r28
31
32
sts 0x006D, r24
33
sts 0x006E, r25
34
sts 0x006F, r26
35
sts 0x0070, r27
36
37
pop r28//
38
pop r27//
39
pop r26//und die hier würde ich auch gerne weglassen
Philipp D. schrieb:> Mein Gedanke war, dass ich doch eigentlich nur meinen Compiler mitteilen> müsste, dass dieser bestimmte Register des Prozessors außerhalb des> Interrupts nicht benutzen darf.
Das ist keine so gute Idee.
Dadurch beraubst du den Compiler um Möglichkeiten im restlichen Code und
zweitens benutzt er ja auch vorübersetzte Routinen, die natürlich nichts
davon wissen, das bestimmte Register tabu sind.
> Hardwareseitig habe ich ein MyAVR MK2 Board mit einem ATmega8> @8MHz µProzessor.
Auf 16Mhz hochgehen bringt dir schon mal Zeitgewinn.
Ich kenne die verwendete Plattform jetzt nicht, aber meist müssen die
Arbeits- und Statusregister bei einer ISR gesichert werden, z.B. Akku
oder W-Register. Wenn möglich, lieber mit der Taktfrequenz hochgehen.
@Philipp
also r0 und r1, sowie die oberen 6 Register kannst du keinesfalls
'sperren'
r0&r1 enthalten z.B. das Ergebnis einer Multiplikation
r26..r31 sind gleichzeitig die 16-Bit Register
ich programmiere ja nicht in C, aber es gibt da glaube ich eine
Möglichkeit eine Variable an ein bestimmtes Register zu binden? (an die
C'ler hier?). Dann könntest du zumindest dein '32-Bit-Register'
dauerhaft halten und brauchst auch die 8 SRam-Zugriffe nicht - das spart
auch noch mal ne Menge Zeit.
Sascha
Hey,
danke für die schnellen Antworten.
Karl Heinz Buchegger schrieb:> Das ist keine so gute Idee.> Dadurch beraubst du den Compiler um Möglichkeiten im restlichen Code und> zweitens benutzt er ja auch vorübersetzte Routinen, die natürlich nichts> davon wissen, das bestimmte Register tabu sind.
Ich verstehe nicht ganz welche vorübersetzten Routinen?
Und ich will ja nicht den Compiler seiner Möglichkeiten berauben,
in jedem anderen Programmteil bin ich Zeit-unkritisch,
da kann der Compiler von mir aus machen was er will solange er meine 5
Register in Ruhe lässt :).
Ich hab einfach nur gedacht es könnte sowas geben in der Art.
1
main(){
2
/*Pseudo Code*/
3
asm("don't use r24");
4
asm("don't use r25");
5
...
6
7
}
Ich will halt nicht den Kompletten Code in assembler schreiben müssen.
Karl Heinz Buchegger schrieb:> Auf 16Mhz hochgehen bringt dir schon mal Zeitgewinn.
Jop, habe schon den ATmega88 bestellt :), mein ATmega 8 kann nur 8Mhz.
Geht mir generell nur um die Möglichkeiten die Ich habe da ich noch neu
bei der ganzen Sache bin.
Vielen Dank für die Antworten!
Mit freundlichen Grüßen
Philipp D.
Sascha Weber schrieb:> ich programmiere ja nicht in C, aber es gibt da glaube ich eine> Möglichkeit eine Variable an ein bestimmtes Register zu binden? (an die> C'ler hier?)
Das wäre ja auch stark, da ist doch noch richtig Potential dahinter.
War da nicht irgendwie was mit volatile oder so ...
Wenn ich die 32 Bit Variable an die Register könnte ich mir ja ohnehin 4
der 5 Push und Pops sparen, die betreffen ja "nur diese 32 Bit Variable.
Wäre toll wenn jemand ein kleines Beispiel von diesem Variablen-binden
hätte :).
Vielen Dank!
Mit freundlichen Grüßen
Philipp D.
Sascha Weber schrieb:> ich programmiere ja nicht in C, aber es gibt da glaube ich eine> Möglichkeit eine Variable an ein bestimmtes Register zu binden? (an die> C'ler hier?)
Es gibt in C nur das Schlüsselwort register was dem Compiler empfiehlt
(nicht befehlt!) die Variable in einem Register zu speichern. Eventuell
gibt es beim GCC ein passendes attribut, so auf die Schnelle konnte ich
aber nichts finden.
http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html#Variable-Attributes
Register 24 kannst du nicht reservieren; -ffixed-24 wird dir komplett
alles zerschiessen, auch wenn der Compiler es zulässt.
Stattdessen kannst du die ISR komplett als naked implementieren und
eigenen Prolog/Epilog schreiben, etwa so:
A. K. schrieb:> Wer es unbedingt drauf anlegt:
Was ist damit jetzt gemeint?
Ich verstehe nicht ganz, anscheinend scheint diese Art der
Programmierung verpöhnt zu sein :).
Da ich wie schon erwähnt noch wenig Erfahrung damit habe lasse ich mich
natürlich gerne Überzeugen das nicht zu tun.
Aber für mich (womöglich auch durch meinen jugendlichen Leichtsinn :) )
überwiegt hier momentan der Vorteil,
dass ich mir in jedem Fall enorm viel Zeit spare, da ich weder Register
durch Push und Pop Befehle sichern müsste, noch die Variable im SRam
speichern bzw. laden müsste.
Es ist mir schon klar, dass ich diese Register damit dem Compiler
wegnehmen würde, aber der hat doch ohnehin 30 stk und ich will ja nur 4
davon haben :).
Was spricht denn nun dagegen dies in einem übersichtlichen Programm zu
tun um Zeit zu sparen?
Vielen Dank für die Antwort!
Mit freundlichen Grüßen
Philipp D.
Philipp D. schrieb:> Ich verstehe nicht ganz>> Extreme care should be taken that the entire application is>> compiled with a consistent set of register-allocated variables,>> including possibly used library functions
und
> noch wenig Erfahrung damit habe
gehen halt selten gut...
Philipp D. schrieb:> dass ich mir in jedem Fall enorm viel Zeit spare, da ich weder Register> durch Push und Pop Befehle sichern müsste
Wirklich enorm viel oder glaubst du es würde dir Zeit sparen?
Philipp D. schrieb:> Was spricht denn nun dagegen dies in einem> übersichtlichen Programm
Hauptsache es bleibt auch für alle Zeit so übersichtlich
> zu tun um Zeit zu sparen?
Für gesparte Zeit gibt es genau sowenig Geld zurück wie für gesparten
Ram oder gesparten Flash.
Am meisten sparen tut man indem man sich solche Tricks spart und
stattdessen nicht am Algorithmus/Konzept/Programmstruktur spart
(besonders als Anfänger).
Philipp D. schrieb:>> Das ist keine so gute Idee.>> Dadurch beraubst du den Compiler um Möglichkeiten im restlichen Code und>> zweitens benutzt er ja auch vorübersetzte Routinen, die natürlich nichts>> davon wissen, das bestimmte Register tabu sind.>> Ich verstehe nicht ganz welche vorübersetzten Routinen?
Na zum Beispiel Stringfunktionen. Zum Beispiel Arithmetikfunktionen, wie
zb 16 Bit Mutliplikationen oder Division oder .....
Läubi .. schrieb:>>> Extreme care should be taken that the entire application is>>> compiled with a consistent set of register-allocated variables,>>> including possibly used library functions
1
registerunsignedchardata_1asm("r24");
2
registerunsignedchardata_2asm("r25");
3
registerunsignedchardata_3asm("r26");
4
registerunsignedchardata_4asm("r27");
5
6
main(){
7
}
Heißt dass wenn ich obigen Code schreibe muss ich mich selbst darum
kümmern, dass nicht doch ein Code compiliert wird, der mir in die
reservierten Register schreibt?
Oder ist das schon erfolgt indem ich die Variablen über der main()
definiert habe?
Vllt. Lasse ich dann doch lieber die Finger davon,
danke für die Warnung Läubi und entschuldige wenn ich dich verärgert
haben sollte.
Mit freundlichen Grüßen
Philipp D.
Philipp D. schrieb:> wenn ich dich verärgert> haben sollte.
Woher den? Sollte nur eine Antwort auf deine Frage sein.
Philipp D. schrieb:> Heißt dass wenn ich obigen Code schreibe muss ich mich selbst darum> kümmern, dass nicht doch ein Code compiliert wird, der mir in die> reservierten Register schreibt?
Ja z.B. wie von Karl Heinz Buchegger geschrieben wissen ggf. vor
kompilierte Bibliotheken nix von deiner Reservierung.
Also wenn eine Interruptroutine so kritisch ist , das solche Konstrukte
notwendig sind, heißt das das die komplette Systemauslegung Müll ist.
Damit meine ich Logik, Programmablauf, ausgewählte µC ,.......
==> leg die Tastatur zur Seite und nimm ein leeres Blatt Papier.
Beginne dann noch mal von vorne.
Ein System mit solch knappen Resourcen wird niemals auf Dauer stabil
laufen. Du wirst immer Ärger wegen seltsamen Verhalten haben.
Philipp D. schrieb:> Ich habe eine Interrupt Routine, die sehr zeitkritisch ist
Dann nimm das, was da so zeitkritisch ist, RAUS aus dem Code und
verlagere es in Hardware...
Philipp D. schrieb:> ISR(SCL){
Interpretiere ich das Richtig als I2C-Clock?
1 Minute später und ein Googlen mehr und ich fass es nicht:
die Suche bringt mir den
Beitrag "Re: Realisierung eines I²C-Sniffers mit ATmega8"
Hey,
Ralph schrieb:> Ein System mit solch knappen Resourcen wird niemals auf Dauer stabil> laufen. Du wirst immer Ärger wegen seltsamen Verhalten haben.
Das ist richtig. Ich sehe das ganze trotzdem positiv, da ich wieder ein
Stückchen mehr über µ-Controller Programmierung gelernt habe. Ich will
das fertige Ding am Ende ja nicht verkaufen oder so.
Übrigens habe ich gerade meine verwendeten Bibliotheken überflogen und
bereits mehrere Verwendungen der besagten Register gefunden.
Es kommt auch eine herrliche Warnung wenn ich das ganze kompilieren
will.
Kurz gesagt die Sache ist mir doch zu heiß.
Ich lasse also ab von diesem Unterfangen und warte darauf, dass mein
ATmega88 zugeschickt wird.
Aber jetzt weis ich wenigstens warum ich es nicht mache.
Vielen Dank an Alle!
Mit freundlichen Grüßen
Philipp D.
Lothar Miller schrieb:> 1 Minute später und ein Googlen mehr und ich fass es nicht:> die Suche bringt mir den
sry, wenn ich das nicht erwähnt habe.
Mir gings in diesem Fall aber nicht um den Sniffer sondern um die
generelle effiziente Gestaltung von Interrupt Routinen.
Mit freundlichen Grüßen
Philipp D.