Forum: Mikrocontroller und Digitale Elektronik Push und Pop Befehle weglassen


von Philipp D. (peacefish)


Lesenswert?

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
40
pop  r25//
41
pop  r24//
42
43
}
44
pop  r0
45
out  0x3f, r0  ; 63
46
pop  r0
47
pop  r1
48
reti


Mit freundlichen Grüßen
Philipp D.

von Valentin B. (nitnelav) Benutzerseite


Lesenswert?

Du modifizierst das Register.
Was auch immer da vorher drin gestanden hat, soll nach der ISR wieder so 
sein.
Also nein, das kann man nicht weglassen.

von spess53 (Gast)


Lesenswert?

Hi

Wenn du Register nur in der ISR oder in Programmteilen bei denen 
Interrupts gesperrt sind benutzt brauchst, du sie auch nicht sichern.

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

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.

von Jens P. (picler)


Lesenswert?

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.

von Sascha W. (sascha-w)


Lesenswert?

@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

von Philipp D. (peacefish)


Lesenswert?

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.

von Philipp D. (peacefish)


Lesenswert?

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.

von alarm (Gast)


Lesenswert?

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

von (prx) A. K. (prx)


Lesenswert?


von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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:
1
ISR(SCL){  
2
push  r24
3
in  r24, __SREG__
4
push  r24
5
;; Prolog
6
7
lds  r24, 0x006D+3
8
lsr  r24
9
sbic  0x13, 0  ; 19
10
ori  r24, 0x80  ; 128
11
sts  0x006D+3, r24
12
13
lds  r24, 0x006D+2
14
ror  r24
15
sts  0x006D+2, r24  
16
17
lds  r24, 0x006D+1
18
ror  r24
19
sts  0x006D+1, r24  
20
21
lds  r24, 0x006D
22
ror  r24
23
sts  0x006D, r24  
24
           
25
lds  r24, 0x0069
26
inc  r24    
27
sts  0x0069, r24
28
      
29
;; Epilog
30
pop  r24
31
out  __SREG__, r24
32
pop  r24
33
reti

von Philipp D. (peacefish)


Lesenswert?

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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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).

von Karl H. (kbuchegg)


Lesenswert?

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 .....

von Philipp D. (peacefish)


Lesenswert?

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
register unsigned char data_1 asm("r24");
2
register unsigned char data_2 asm("r25");
3
register unsigned char data_3 asm("r26");
4
register unsigned char data_4 asm("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.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

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.

von Ralph (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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"

von Philipp D. (peacefish)


Lesenswert?

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.

von Philipp D. (peacefish)


Lesenswert?

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.

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.