Beim Durchsehen des erzeugten Listing aus dem Beispielcode für den
AtXmega128A1
(Appnote AVR1300) bin ich auf die folgende Codesequenz gestossen.
1
ISR(ADCA_CH3_vect)
2
{
3
244:1f92pushr1
4
246:0f92pushr0
5
248:0fb6inr0,0x3f;63
6
24a:0f92pushr0
7
24c:08b6inr0,0x38;56
8
24e:0f92pushr0
9
250:18beout0x38,r1;56
10
252:09b6inr0,0x39;57
11
254:0f92pushr0
12
256:19beout0x39,r1;57
13
258:0bb6inr0,0x3b;59
14
25a:0f92pushr0
15
25c:1bbeout0x3b,r1;59
16
25e:1124eorr1,r1
17
260:0f93pushr16
18
...
R1 kann vom Vordergrundprogramm jeden beliebigen, zufälligen Wert
erhalten, Was landet dann in den IO Register 0x38, 0x39 und 0x3B ?
Das verwendete Makefile als Anhang.
r1 wird möglicherweise beim Xmega genauso behandelt wie bei den
normalen AVRs
"Falls das Register r1 verändert wird – was z.B. geschieht, wenn man
Multiplikationsbefehle verwendet – dann muss am Ende des Templates das
Register wieder auf 0 gesetzt werden, denn bei avr-gcc enthält dieses
Register immer den Wert 0. Das Register in die Clobber-Liste aufzunehen
bleibt wirkungslos. Hat man es zerstört, dann schreibt man ans Ende des
Templates ein clr _zero_reg_ und stellt es dadurch wieder her."
http://www.rn-wissen.de/index.php/Inline-Assembler_in_avr-gcc
Das würde in deinem Listing allerdings bedeuten, dass man eigenen
Inline-Assembler mit Nutzung von r1 atomar machen muss, d.h. nicht durch
Interrupts unterbrechbar.
Werner B. schrieb:
> R1 kann vom Vordergrundprogramm jeden beliebigen, zufälligen Wert> erhalten, Was landet dann in den IO Register 0x38, 0x39 und 0x3B ?
Mumpitz, sieht also nach nem Compilerbug aus.
Welche GCC-Version its das denn?
R1 ist zwar fast immer 0, aber wenn der Interrupt nach ner
Multiplikation mit 16Bit Ergebnis zuschlägt, krachts.
Peter
Ich glaube, das ist ein Bug. Hier mal der Code, wie er vom
Codegenerator selbst kommt:
1
.global __vector_74
2
.type __vector_74, @function
3
__vector_74:
4
push __zero_reg__
5
push r0
6
in r0,__SREG__
7
push r0
8
in r0,56-0
9
push r0
10
out 56-0,__zero_reg__
11
clr __zero_reg__
12
/* prologue: Signal */
13
/* frame size = 0 */
14
/* epilogue start */
15
pop r0
16
out 56-0,r0
17
pop r0
18
out __SREG__,r0
19
pop r0
20
pop __zero_reg__
21
reti
Die ISR kann sich nicht darauf verlassen, dass _zero_reg_ in der
Tat eine 0 enthält, insofern löscht sie das Register ordentlich,
bevor der eigentliche Code der ISR kommen würde -- aber zuvor
benutzt sie es bereits, um RAMPD zu löschen. :-/
Bitte schreib einen GCC-Bugreport dafür.
(Nicht-Xmegas sind davon nicht betroffen, da sie kein RAMPD-Register
besitzen.)
Wäre eigentlich ein schöner Zeitpunkt, endlich mal die Spezialregister
R0,R1 von ihrer Doppelfunktion zu entbinden und R2,R3 als SREG-Kopie und
Zero zu nehmen.
Würde pro Interrupt 7 Befehle und 13 Zyklen sparen.
Peter
Änderungen am ABI sind eine Höllenmaschine. Jeder Assembler-Code muss
dann mindestens kontrolliert und ggf. umgeschrieben werden, egal ob
innerhalb GCC oder separater Code.
Ein Register wie R2 global als Platz für die SREG-Kopie von
Interrupt-Handlern zu reservieren würde in sehr subtiler und schwer
identifizierbarer Form jene bestehenden Programme abschiessen, die
verschachtelte Interrupts verwenden. Was bei AVRs zwar nicht die Regel
ist, aber zulässig.
Ein klarer Fall von, "Das hab ich schon immer so gemacht, so bleibt es
auch ? - Was neues kommt nicht in Frage" :-))
Tja...muss man halt durch..
Gibts eigentlich das A20-Gate noch ?
Dback schrieb:
> Ein klarer Fall von, "Das hab ich schon immer so gemacht, so bleibt es> auch ? - Was neues kommt nicht in Frage" :-))
Solche Registerkonventionen sind eine Grundsatzentscheidung, die in der
Anfangsphase einer GCC Portierung getroffen wird. Sie im voll
entwickelten produktiven Produkt zu renovieren braucht mehr Anlass als
ein paar gewonnene Takte im Interrupt-Handler.
A. K. schrieb:
> Änderungen am ABI sind eine Höllenmaschine.
Mit dem R1 gabs ja schon öfters Ärger und es wird auch nicht das letzte
mal sein.
Man könnte das Zero-Register auch ganz weglassen, der Nutzen ist nur
sehr gering.
> Ein Register wie R2 global als Platz für die SREG-Kopie von> Interrupt-Handlern zu reservieren würde in sehr subtiler und schwer> identifizierbarer Form jene bestehenden Programme abschiessen
Dafür gibts doch ISR_BLOCK, ISR_NOBLOCK, damit könnte man dann das
zusätzliche Push/Pop steuern.
Peter
Das Problem besteht offenbar nur beim U*nix Compiler von
Bingo600@avrfreaks.
Ich habe das noch einmal mit WinAVR 20100110 Übersetzt. Da tritt der
Fehler nicht auf.
1
244:1f92pushr1
2
246:0f92pushr0
3
248:0fb6inr0,0x3f;63
4
24a:0f92pushr0
5
24c:08b6inr0,0x38;56
6
24e:0f92pushr0
7
250:09b6inr0,0x39;57
8
252:0f92pushr0
9
254:0bb6inr0,0x3b;59
10
256:0f92pushr0
11
258:1124eorr1,r1
12
25a:18beout0x38,r1;56
13
25c:19beout0x39,r1;57
14
25e:1bbeout0x3b,r1;59
15
...
Ich werde den Bug-Report also nur an Bingo600 schicken ;-)
Werner B. schrieb:
> Das Problem besteht offenbar nur beim U*nix Compiler von> Bingo600@avrfreaks.
Das würde bedeuten, dass mir wohl ein Patch fehlt. Schade auch,
leider hat Eric seine WinAVR-Patches noch nicht ins CVS bei
sourceforge.net gestellt. Damit kann ich nicht vergleichen, was
da fehlt.
Jörg Wunsch schrieb:
> Das würde bedeuten, dass mir wohl ein Patch fehlt.
Ich habe die Patches jetzt da. Werde ich mir demnächst mal angucken,
was mir da durch die Lappen gegangen ist.