Hallo,
haette da eine Frage an die Experts..
Bei der Fehlersuche habe ich festgestellt, dass mein Programm ohne
Optimierung, d.h. mit -O funktioniert, mit der Optimierung -Os nicht.
Ich habe das Problem separiert, das Beispiel ist jetzt zwar funktionell
sinnfrei, aber das Problem laessst sich so nachvollziehen.
Ich habe festgestellt, dass das Programm immer laeuft wenn die Variable
"dow" entweder ausserhalb von main() oder static deklariert wird. D.h.
die Optimierung spielt keine Rolle.
Im folgenden Beispiel ist die Variable "dow" so definiert, dass das
Problem auftritt, d.h. die "NOP" Anweisung wird nicht erreicht. In
meinem echten Projekt fuehrt dieser Effekt dazu, dass die Variable "dow"
nicht gesetzt wird, d.h. auf 0 bleibt. Mein workaround ist zurzeit, die
Variable als static zu deklarieren.
Ich verwende:
XP, AVRStudio 4.16, WinAVR-20090313, avr libc 1.6.6, ATMega644p
Ich hoffe ich konnte das Problem halbwegs nachvollziehbar beschreiben.
Vielen Dank fuer evtl. Hinweise!
Gruss
Roland
#include <avr/io.h>
#define NOP asm volatile("nop"::);
unsigned int tag=4096;
//unsigned char dow; <-- ok
int main (void)
{
//static unsigned char dow; <-- ok
unsigned char dow; <-- nicht ok !
dow = (unsigned char) ((tag >> 12) & 0x000F);
dow++;
NOP; <-- Breakpoint im debugger
};
ja ok, hier ist die original Routine, vielleicht hilft das weiter. Mit
dem Beispiel habe ich es sicher uebertrieben..
void disp_wochentag (unsigned int tag)
{
char buf[12];
static unsigned char dow; <-- dow wird richtig berechnet
//unsigned char dow; <-- dow bleibt auf 0
dow = (unsigned char) ((tag >> 12) & 0x000F);
dow2ascii(dow, buf);
backcolor = BLUE;
textcolor = WHITE;
lcd_puts(buf);
}
Nachtrag: Ich kann mir nicht vorstellen, das ist bei diesem beispiel
wirklich nicht geht. Ich glaube das Problem ensteht erst in deinen
kompletten programm.
Bei Static bleibt der Inhalt von dow auch nach den ende der prozedure
disp_wochentag erhalten. Ich glaube der Fehler ist woanders. z.b. in
dow2ascii(dow, buf);
Hier die Routine mit -Os und static fuer "dow"
void disp_wochentag (unsigned int tag)
{
char buf[12];
static unsigned char dow;
//unsigned char dow;
dow = (unsigned char) ((tag >> 12) & 0x000F);
dow2ascii(dow, buf);
backcolor = BLUE;
textcolor = WHITE;
lcd_puts(buf);
}
@00001ABC: disp_wochentag
403: {
+00001ABC: 930F PUSH R16 Push register on stack
+00001ABD: 931F PUSH R17 Push register on stack
+00001ABE: 93DF PUSH R29 Push register on stack
+00001ABF: 93CF PUSH R28 Push register on stack
+00001AC0: B7CD IN R28,0x3D In from I/O location
+00001AC1: B7DE IN R29,0x3E In from I/O location
+00001AC2: 972C SBIW R28,0x0C Subtract immediate
from word
+00001AC3: B60F IN R0,0x3F In from I/O location
+00001AC4: 94F8 CLI Global Interrupt
Disable
+00001AC5: BFDE OUT 0x3E,R29 Out to I/O location
+00001AC6: BE0F OUT 0x3F,R0 Out to I/O location
+00001AC7: BFCD OUT 0x3D,R28 Out to I/O location
408: dow = (unsigned char) ((tag >> 12) & 0x000F);
+00001AC8: 9592 SWAP R25 Swap nibbles
+00001AC9: 709F ANDI R25,0x0F Logical AND with
immediate
+00001ACA: 9390016A STS 0x016A,R25 Store direct to data
space
409: dow2ascii(dow, buf);
+00001ACC: 2F89 MOV R24,R25 Copy register
+00001ACD: 018E MOVW R16,R28 Copy register pair
+00001ACE: 5F0F SUBI R16,0xFF Subtract immediate
+00001ACF: 4F1F SBCI R17,0xFF Subtract immediate
with carry
+00001AD0: 01B8 MOVW R22,R16 Copy register pair
+00001AD1: 940E1A96 CALL 0x00001A96 Call subroutine
411: backcolor = BLUE;
+00001AD3: E18F LDI R24,0x1F Load immediate
+00001AD4: E090 LDI R25,0x00 Load immediate
+00001AD5: 93900C33 STS 0x0C33,R25 Store direct to data
space
+00001AD7: 93800C32 STS 0x0C32,R24 Store direct to data
space
412: textcolor = WHITE;
+00001AD9: EF8F SER R24 Set Register
+00001ADA: EF9F SER R25 Set Register
+00001ADB: 93900C38 STS 0x0C38,R25 Store direct to data
space
+00001ADD: 93800C37 STS 0x0C37,R24 Store direct to data
space
413: lcd_puts(buf);
+00001ADF: 01C8 MOVW R24,R16 Copy register pair
+00001AE0: 940E263D CALL 0x0000263D Call subroutine
414: }
und jetzt ohne static
void disp_wochentag (unsigned int tag)
{
char buf[12];
//static unsigned char dow;
unsigned char dow;
dow = (unsigned char) ((tag >> 12) & 0x000F);
dow2ascii(dow, buf);
backcolor = BLUE;
textcolor = WHITE;
lcd_puts(buf);
}
@00001ABC: disp_wochentag
403: {
+00001ABC: 930F PUSH R16 Push register on stack
+00001ABD: 931F PUSH R17 Push register on stack
+00001ABE: 93DF PUSH R29 Push register on stack
+00001ABF: 93CF PUSH R28 Push register on stack
+00001AC0: B7CD IN R28,0x3D In from I/O location
+00001AC1: B7DE IN R29,0x3E In from I/O location
+00001AC2: 972C SBIW R28,0x0C Subtract immediate
from word
+00001AC3: B60F IN R0,0x3F In from I/O location
+00001AC4: 94F8 CLI Global Interrupt
Disable
+00001AC5: BFDE OUT 0x3E,R29 Out to I/O location
+00001AC6: BE0F OUT 0x3F,R0 Out to I/O location
+00001AC7: BFCD OUT 0x3D,R28 Out to I/O location
409: dow2ascii(dow, buf);
+00001AC8: 9582 SWAP R24 Swap nibbles
+00001AC9: 708F ANDI R24,0x0F Logical AND with
immediate
+00001ACA: 018E MOVW R16,R28 Copy register pair
+00001ACB: 5F0F SUBI R16,0xFF Subtract immediate
+00001ACC: 4F1F SBCI R17,0xFF Subtract immediate
with carry
+00001ACD: 01B8 MOVW R22,R16 Copy register pair
+00001ACE: 940E1A96 CALL 0x00001A96 Call subroutine
411: backcolor = BLUE;
+00001AD0: E18F LDI R24,0x1F Load immediate
+00001AD1: E090 LDI R25,0x00 Load immediate
+00001AD2: 93900C32 STS 0x0C32,R25 Store direct to data
space
+00001AD4: 93800C31 STS 0x0C31,R24 Store direct to data
space
412: textcolor = WHITE;
+00001AD6: EF8F SER R24 Set Register
+00001AD7: EF9F SER R25 Set Register
+00001AD8: 93900C37 STS 0x0C37,R25 Store direct to data
space
+00001ADA: 93800C36 STS 0x0C36,R24 Store direct to data
space
413: lcd_puts(buf);
+00001ADC: 01C8 MOVW R24,R16 Copy register pair
+00001ADD: 940E263A CALL 0x0000263A Call subroutine
414: }
Peter wrote:
> Nachtrag: Ich kann mir nicht vorstellen, das ist bei diesem beispiel> wirklich nicht geht. Ich glaube das Problem ensteht erst in deinen> kompletten programm.>> Bei Static bleibt der Inhalt von dow auch nach den ende der prozedure> disp_wochentag erhalten. Ich glaube der Fehler ist woanders. z.b. in> dow2ascii(dow, buf);
Hallo Peter,
das Problem kann ja direkt im debugger nachvollzogen werden. Ich kann ja
sehen das dow2ascii(dow, buf) mit dow=0 aufgerufen wird. Jedenfalls in
meinem "richtigen" Programm. Das Beispielprogramm bleibt in diesem Fall
"haengen". Ich habe es mit jtag mk2 gestestet.
Gruss
Roland
ich kann es immer noch nicht glauben.
Wenn ich mir den asm anschauen, ist in beiden fällen die gleiche
Berechnung drin. Bei der 1. Variante wird der Tag in R25 und bei der 2.
in R24 übergeben. Dann erfolgt aber genau die gleiche berechnung.
Prüfe mal bitte ob in den Register zu begin der Prozedur auf der Tag
drin steht.
Eventuell doch mal den kompletten quellcode posten.
Roland Berlauer wrote:
> ja ok, hier ist die original Routine, vielleicht hilft das weiter. Mit> dem Beispiel habe ich es sicher uebertrieben..>> void disp_wochentag (unsigned int tag)> {> char buf[12];> static unsigned char dow; <-- dow wird richtig berechnet> //unsigned char dow; <-- dow bleibt auf 0>> dow = (unsigned char) ((tag >> 12) & 0x000F);> dow2ascii(dow, buf);>> backcolor = BLUE;> textcolor = WHITE;> lcd_puts(buf);> }
Nein, es hilft nicht weiter. Es hagelt Fehler und Warnungen:
1
foo.c: In function 'disp_wochentag':
2
foo.c:4: error: expected expression before '<' token
3
foo.c:8: warning: implicit declaration of function 'dow2ascii'
4
foo.c:10: error: 'backcolor' undeclared (first use in this function)
5
foo.c:10: error: (Each undeclared identifier is reported only once
6
foo.c:10: error: for each function it appears in.)
7
foo.c:10: error: 'BLUE' undeclared (first use in this function)
8
foo.c:11: error: 'textcolor' undeclared (first use in this function)
9
foo.c:11: error: 'WHITE' undeclared (first use in this function)
10
foo.c:12: warning: implicit declaration of function 'lcd_puts'
11
foo.c:1: warning: unused parameter 'tag'
Wie soll man das Zeug nachvollziehen?
Wie wär's mit einem Testfall?
Johann
Johann L. wrote:
> Roland Berlauer wrote:>> ja ok, hier ist die original Routine, vielleicht hilft das weiter. Mit>> dem Beispiel habe ich es sicher uebertrieben..>>>> void disp_wochentag (unsigned int tag)>> {>> char buf[12];
...........
>> }>> Nein. Es hagelt Fehler:>>
1
................
2
>
>> Wie soll man das Zeug nachvollziehen?> Wie wär's mit einem Testfall?>> Johann
Hallo Johann,
deshalb hatte ich doch gleich als erstes ein Beispiel gepostet..
Peter wrote:
> ich kann es immer noch nicht glauben.>> Wenn ich mir den asm anschauen, ist in beiden fällen die gleiche> Berechnung drin. Bei der 1. Variante wird der Tag in R25 und bei der 2.> in R24 übergeben. Dann erfolgt aber genau die gleiche berechnung.>> Prüfe mal bitte ob in den Register zu begin der Prozedur auf der Tag> drin steht.> Eventuell doch mal den kompletten quellcode posten.
Das habe ich ueberprueft, z.B. wird die Routine mit tag=4096 aufgerufen,
fuer dow wird dann 1 berechnet, bei Deklaration von dow als static.
Habe es nach allen Richtungen im Debugger getestet.
Wiegesagt der asm code sollte gehen, wenn wir dir helfen sollen brauchen
wir etwas mehr code - in denke immer noch der Aufruf ist falsch.
Du sollte schauen ob in den Registern R24 bzw R25 auf der Wert für den
Tag enthalten ist.
Rufe doch mal bitte die funktion
disp_wochentag(4096)
auf. Also wirklich mit einer Konstante und schau was den passiert. Wenn
das auch nicht geht, schicke bitte auch den asm code von dem Aufruf mit.
Peter wrote:
> Wiegesagt der asm code sollte gehen, wenn wir dir helfen sollen brauchen> wir etwas mehr code - in denke immer noch der Aufruf ist falsch.>> Du sollte schauen ob in den Registern R24 bzw R25 auf der Wert für den> Tag enthalten ist.>> Rufe doch mal bitte die funktion>> disp_wochentag(4096)>> auf. Also wirklich mit einer Konstante und schau was den passiert. Wenn> das auch nicht geht, schicke bitte auch den asm code von dem Aufruf mit.
ok Peter, hier ein groesserer Auszug, der sich compilieren laesst. In
dieser Fassung wird dow richtig berechnet. Sobald man "static" weglaesst
entsteht das Problem.
#include <avr/io.h>
#include <avr/pgmspace.h>
#define NOP asm volatile("nop"::);
#define ANY_DAY 8
const char dow0[] PROGMEM = "?";
const char dow1[] PROGMEM = "Montag";
const char dow2[] PROGMEM = "Dienstag";
const char dow3[] PROGMEM = "Mittwoch";
const char dow4[] PROGMEM = "Donnerstag";
const char dow5[] PROGMEM = "Freitag";
const char dow6[] PROGMEM = "Samstag";
const char dow7[] PROGMEM = "Sonntag";
const char dow8[] PROGMEM = "taeglich";
PGM_P daytab[] PROGMEM = { dow0, dow1, dow2, dow3, dow4, dow5, dow6,
dow7, dow8 };
void dow2ascii(unsigned char dow, char *s)
{
PGM_P p;
if(dow <= ANY_DAY)
memcpy_P(&p, &daytab[dow], sizeof(PGM_P)); // ok, Tag holen
else
memcpy_P(&p, &daytab[0], sizeof(PGM_P)); // Fehleranzeige
strcpy_P(s, p);
}
void disp_wochentag (unsigned int tag)
{
char buf[12];
static unsigned char dow; // <-- ok
//unsigned char dow; // <-- nicht ok
dow = (unsigned char) ((tag >> 12) & 0x000F);
dow2ascii(dow, buf); // dow=1, in buf steht "Montag" bei tag=4096
NOP; // <-- breakpoint
//lcd_puts(buf);
}
int main (void)
{
disp_wochentag(4096);
while(1) {};
};
@Roland,Peter: Ohne eure Diskussion unterbrechen zu wollen: Der Fall ist
bereits geklärt. Offen ist nur, wer sich die Mühe mit bugzilla macht.
@Roland: Entweder du bleibst bei -O, oder du suchst dir eine ältere
WinAVR Version, in der das Problem nicht auftritt.
Roland Berlauer wrote:
> ok Peter, hier ein groesserer Auszug, der sich compilieren laesst. In> dieser Fassung wird dow richtig berechnet. Sobald man "static" weglaesst> entsteht das Problem.
Es ist, wie gesagt, ein Compilerfehler. Der Fehler tritt auch auf
-- in WinAVR-20080512
-- logische Rechtsshifts um 12, 13 und 14
-- wahlscheinlich auch bei Linksshifts um 12, 13, 14, wobei Testfällt
schwerer zu erzeugen sein dürften
-- für alle AVR-Derivate
Wie es aussieht, liefert die gcc-Option -fno-split-wide-types einen
Workaround.
Johann
A. K. wrote:
> @Roland,Peter: Ohne eure Diskussion unterbrechen zu wollen: Der Fall ist> bereits geklärt. Offen ist nur, wer sich die Mühe mit bugzilla macht.>> @Roland: Entweder du bleibst bei -O, oder du suchst dir eine ältere> WinAVR Version, in der das Problem nicht auftritt.
Hallo A. K,
Peter und Johann,
vielen Dank fuer die schnelle Klaerung! Ich selbst habe zuwenig
Erfahrung, als dass ich mich gewagt haette von einem compiler bug zu
sprechen. Deshalb ist es sicherlich zielfuehrender wenn das jemand von
euch meldet. Die Ausfuehrungen von Johann hatte nicht so wirklich
verstanden .. :-)
Danke nochmals.
Gruss
Roland
A. K. wrote:
> @Roland,Peter: Ohne eure Diskussion unterbrechen zu wollen: Der Fall ist> bereits geklärt. Offen ist nur, wer sich die Mühe mit bugzilla macht.
Schon passiert.
Johann
Johann L. wrote:
> -- in WinAVR-20080512
Sieh an! Bemerkenswert, dass sich ein Bug dieser Qualität so lang
verstecken konnte. Vielleicht weil sich rumgesprochen hat, dass
-fno-split-wide-types ohnehin nützlich ist.
Johann L. wrote:
> Roland Berlauer wrote:>>> ok Peter, hier ein groesserer Auszug, der sich compilieren laesst. In>> dieser Fassung wird dow richtig berechnet. Sobald man "static" weglaesst>> entsteht das Problem.>> Es ist, wie gesagt, ein Compilerfehler. Der Fehler tritt auch auf>> -- in WinAVR-20080512> -- logische Rechtsshifts um 12, 13 und 14> -- wahlscheinlich auch bei Linksshifts um 12, 13, 14, wobei Testfällt> schwerer zu erzeugen sein dürften> -- für alle AVR-Derivate>> Wie es aussieht, liefert die gcc-Option -fno-split-wide-types einen> Workaround.>> Johann
Hallo Johann,
war eine Ueberschneidung. Ich war damit beschaeftigt noch ein "Testcase"
zusammen zubasteln. Dein Hinweis "gcc-Option -fno-split-wide-types" habe
ich gleich ausprobiert. Super, es funktioniert.
Nochmals Danke
Hab's direkt in die avr-gcc-list gepostet. Ist einfacher und direkter,
da lesen Eric und Anatoly ja mit. Bis das im Web-Archiv erscheint,
dauert's allerdings bis zu 2 Stunden.
http://lists.gnu.org/archive/html/avr-gcc-list/2009-03/
Um so erstaunlicher das ganze, weil es schon mit
A. K. wrote:
> Das sieht schwer nach Compiler-Bug aus. Ich kann es reproduzieren.> Allerdings tritt der Fehler bei mir (Linux, 4.3.3) auch bei -O auf.
Was sagt denn -v? Ich kann den Fehler mit 4.3.3 unter Linux nicht
nachvollziehen. avr-gcc hab ich erzeugt aus svn gcc_4_3_3_release mit
gcc = 4.0.2
gmp = 4.2.2
mpfr = 2.3.1
Johann
Ich hatte den nicht selbst erzeugt, sondern vor ein paar Monaten aus dem
damaligen debian unstable installiert (4.3.3-1). Wird von mir aber nicht
produktiv eingesetzt, sondern nur für solche Tests.
A. K. wrote:
> Ich hatte den nicht selbst erzeugt, sondern vor ein paar Monaten aus dem> damaligen debian unstable installiert (4.3.3-1). Wird von mir aber nicht> produktiv eingesetzt, sondern nur für solche Tests.
Hast du wenigstens die Ausgabe von -v? Oder vielleicht sogar die
svn-Version oder Tag? Und sind da irgendwelche Patches drinne?
Momentan sieht's eher so aus als wär's ein Bug im Middleend, und nicht
im Backend.
Johann