Forum: Compiler & IDEs Fehler im avr-gcc bei Arrayzugriff


von Sebastian (Gast)


Lesenswert?

Hallo,
ja, ich weiß, wenn man glaubt der Compiler macht einen Fehler, dann war 
man das meistens selber.
Aber ich hab mir den Disassembler angeschaut, und mit verschiedenen 
Werten experimentiert, und alles deutet darauf hin dass es wirklich der 
Compiler war.

Frage an euch: Bin ich blöd, oder der Compiler? Ist der Fehler schon 
bekannt (Nach welchen Suchbegriffen würdet ihr suchen?), oder sollte ich 
versuchen ein minimales Programm zu bauen, das den Fehler reproduziert?

Die Compilerversion:
1
avr-gcc --version
2
avr-gcc (AVR_8_bit_GNU_Toolchain_3.3.0_364) 4.5.1
3
Copyright (C) 2010 Free Software Foundation, Inc.
4
This is free software; see the source for copying conditions.  There is NO
5
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Mit diesen Optionen (Dateinamen und Includepfade rausgekürzt)
1
avr-gcc -x c -funsigned-char -funsigned-bitfields -DF_CPU=1000000UL -ffunction-sections -fdata-sections -fpack-struct -fshort-enums -mmcu=atmega644 -c -gdwarf-2 -Wall -std=gnu99 -Os

Es geht um die folgende Zeile (uint8_t* input zeigt auf Daten vom TWI):
1
handle_analog_sensor_values(input[0] | ((uint16_t)input[1] << 8), input[2] | ((uint16_t)input[3] << 8), input[4] | ((uint16_t)input[5] << 8), input[6] | ((uint16_t)input[7] << 8));
in der diese Funktion aufgerufen wird:
1
void handle_analog_sensor_values(uint16_t v0, uint16_t v1, uint16_t v2, uint16_t v3)

Zuordnung zwischen Parametern und Registern, wie angezeigt von AVR 
Studio 4.19 bei Mouseover:
v0 = R24:R25
v1 = R23:R22
v2 = R21:R20
v3 = R19:R18

Der Disassembler, mit Anmerkungen von mir (bitte korrigiert mich wenn 
ich was falsch verstanden habe. Ich programmiere AVRs eigentlich nicht 
in Assembler)
1
415:          handle_analog_sensor_values(input[0] | ((uint16_t)input[1] << 8), input[2] | ((uint16_t)input[3] << 8), input[4] | ((uint16_t)input[5] << 8), input[6] | ((uint16_t)input[7] << 8));
2
+00000869:   9611        ADIW      R26,0x01       Add immediate to word               #
3
+0000086A:   91FC        LD        R31,X          Load indirect                       #
4
+0000086B:   9711        SBIW      R26,0x01       Subtract immediate from word        #
5
+0000086C:   E0E0        LDI       R30,0x00       Load immediate                      #
6
+0000086D:   8189        LDD       R24,Y+1        Load indirect with displacement     #
7
+0000086E:   E090        LDI       R25,0x00       Load immediate                      #
8
+0000086F:   9613        ADIW      R26,0x03       Add immediate to word               #
9
+00000870:   913C        LD        R19,X          Load indirect                       #
10
+00000871:   9713        SBIW      R26,0x03       Subtract immediate from word        #
11
+00000872:   E020        LDI       R18,0x00       Load immediate                      #
12
+00000873:   9612        ADIW      R26,0x02       Add immediate to word               #
13
+00000874:   916C        LD        R22,X          Load indirect                       #
14
+00000875:   9712        SBIW      R26,0x02       Subtract immediate from word        #
15
+00000876:   E070        LDI       R23,0x00       Load immediate                      #
16
+00000877:   2B62        OR        R22,R18        Logical OR                          #
17
+00000878:   2B73        OR        R23,R19        Logical OR                          #
18
+00000879:   9615        ADIW      R26,0x05       Add immediate to word               #
19
+0000087A:   913C        LD        R19,X          Load indirect                       # R19 = input[5]
20
+0000087B:   9715        SBIW      R26,0x05       Subtract immediate from word        #
21
+0000087C:   E020        LDI       R18,0x00       Load immediate                      #
22
+0000087D:   9614        ADIW      R26,0x04       Add immediate to word               #
23
+0000087E:   914C        LD        R20,X          Load indirect                       #
24
+0000087F:   9714        SBIW      R26,0x04       Subtract immediate from word        #
25
+00000880:   E050        LDI       R21,0x00       Load immediate                      #
26
+00000881:   2B42        OR        R20,R18        Logical OR                          #
27
+00000882:   2B53        OR        R21,R19        Logical OR                          #
28
+00000883:   E020        LDI       R18,0x00       Load immediate                      #
29
+00000884:   01E9        MOVW      R28,R18        Copy register pair                  # R29:R28 = R19:R18
30
+00000885:   9616        ADIW      R26,0x06       Add immediate to word               # X=R27:R26 = input + 6
31
+00000886:   912C        LD        R18,X          Load indirect                       # Lade input[6] nach v3 Low
32
+00000887:   E030        LDI       R19,0x00       Load immediate                      # Init v3 High
33
+00000888:   2B2C        OR        R18,R28        Logical OR                          # v3 Low
34
+00000889:   2B3D        OR        R19,R29        Logical OR                          # v3 High
35
+0000088A:   2B8E        OR        R24,R30        Logical OR                          #
36
+0000088B:   2B9F        OR        R25,R31        Logical OR                          #
37
+0000088C:   940E1BF7    CALL      0x00001BF7     Call subroutine                     #
38
+0000088E:   C01C        RJMP      PC+0x001D      Relative jump                       #

siehe 
http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_nomenclature.html
X=R27:R26, Y=R29:R28 and Z=R31:R30

X scheint auf input zu zeigen.

Mal abgesehen davon dass ich nicht verstehe, dass avr-gcc da OR Befehle 
braucht wenn ich eigentlich nur Low- und High-Byte zusammenbauen wollte, 
und die dauernde Hin- und Herschieberei der X Register kommt mir auch 
unnötig vor...

Soweit ich diesen Disassembler verstehe, wird für das High-Byte von 
Parameter v3 nicht input[7], sondern input[5] verwendet.

Und genau das beobachte ich auch, wenn ich Test-Werte über TWI 
reinschicke:
Eingabe: 258, 269, 0x305, 0x0106
Ergebnis: 258, 269, 773, 774

von Oliver S. (oliverso)


Lesenswert?

Ein compilierbares Beispiel wäre nicht schlecht. Der Assemblercode ist 
nicht vollständig genug, zumindest kann ich nicht erkennen, was im 
Y-Register steht.

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Denkbar ist https://gcc.gnu.org/PR46779

Auch wenn es der nicht ist, würd keine Toolchain mit PR46779 verwenden!

von Sebastian (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe jetzt ein kleines AVR-Studio Projekt (bug.zip) gemacht, mit dem 
sich der Fehler reproduzieren lässt. Breakpoint aufs return von main, 
dort hat die Variable parameter_in_function den falschen Wert.

Der falsch compilierte Teil ist in einer ganz kurze Datei, bug.c:
1
#include <stdint.h>
2
3
void handle_analog_sensor_values(uint16_t v0, uint16_t v1, uint16_t v2, uint16_t v3);
4
5
void testcall(uint8_t* input)
6
{
7
  handle_analog_sensor_values(input[0] | ((uint16_t)input[1] << 8), input[2] | ((uint16_t)input[3] << 8), input[4] | ((uint16_t)input[5] << 8), input[6] | ((uint16_t)input[7] << 8));
8
}

Der daraus erzeugte Assemblercode ist im Anhang als bug.s.

von Sebastian (Gast)


Lesenswert?

Johann L. schrieb:
> Denkbar ist https://gcc.gnu.org/PR46779

Nächster Schritt wird wohl sein, das Beispiel im GCC Bug Tracker zu 
melden, um zu sehen ob es der ist, oder?

von m. keller (Gast)


Lesenswert?

Abgesehen von dem vermuteten Fehler, würde ich empfehlen dieser Funktion 
einfach das Array zu übergeben anstatt 4 Paramter mit Shift-Operationen 
beim Aufruf! Oder zumindest das Tauschen der Bytes mit localen variablen 
erledigen.

Läuft der Code denn ohne oder mit anderen Optimierungsstufen?

von Sebastian (Gast)


Lesenswert?

Johann L. schrieb:
> Denkbar ist https://gcc.gnu.org/PR46779

Aus dem Ticket:
It seems to be that the generation of the code goes wrong if using size 
optimization, inline assembler and nested loops.

Selbst wenn es der gleiche Fehler ist, dann hab ich ihn unter anderen 
Vorraussetzungen bekommen. Size Optimization JA, inline assembler und 
nested loops NEIN.

Allerdings: https://gcc.gnu.org/PR45291 und noch ein paar andere
sind als Duplikat verlinkt, und kommen auch ohne inline assembler und 
nested loops aus.

von Sebastian (Gast)


Lesenswert?

m. keller schrieb:
> Abgesehen von dem vermuteten Fehler, würde ich empfehlen dieser Funktion
> einfach das Array zu übergeben
Geht nicht so einfach, ist generierter Code für dem Empfang von TWI 
Nachrichten.

> Läuft der Code denn ohne oder mit anderen Optimierungsstufen?
Hab ich noch nicht probiert.
Ist das sinnvoll, oder sollte ich lieber gleich eine andere 
Compilerversion nehmen?

von Jim M. (turboj)


Lesenswert?

Bei einem Alter >5 Jahren würde ich zuerst eine neue Compilerversion 
probieren. Eventuell hat Deinen Bug längst jemand behoben.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sebastian schrieb:
> Johann L. schrieb:
>> Denkbar ist https://gcc.gnu.org/PR46779
>
> Nächster Schritt wird wohl sein, das Beispiel im GCC Bug Tracker zu
> melden, um zu sehen ob es der ist, oder?

Die 4.5 wird nicht mehr supportet, die älteste supportete Version ist 
4.9.

Außerdem verwendest du die 4.5.1 obwohl die 4.5.4 diesen Bug behoben 
hat.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Sebastian schrieb:
> Johann L. schrieb:
>> Denkbar ist https://gcc.gnu.org/PR46779
>
> Aus dem Ticket:
> It seems to be that the generation of the code goes wrong if using size
> optimization, inline assembler and nested loops.
>
> Selbst wenn es der gleiche Fehler ist, dann hab ich ihn unter anderen
> Vorraussetzungen bekommen. Size Optimization JA, inline assembler und
> nested loops NEIN.

Die Leute schreiben alle möglichen Theorien und Spekulationen in ihre 
Bug-Reprorts.  Fakt ist, dass PR46779 weder was mit Inline Asm noch mit 
Loops zu tun hat.

> Allerdings: https://gcc.gnu.org/PR45291 und noch ein paar andere
> sind als Duplikat verlinkt, und kommen auch ohne inline assembler und
> nested loops aus.

QED

von sebastian (Gast)


Lesenswert?

Johann L. schrieb:
> Die 4.5 wird nicht mehr supportet, die älteste supportete Version ist
> 4.9.
D.h. einen Bug-Report, den man mit 4.9 nicht reproduzieren kann, wird 
niemand beachten, kann ich mir also sparen?

> Außerdem verwendest du die 4.5.1 obwohl die 4.5.4 diesen Bug behoben
> hat.
Du meinst also, es handelt sich wirklich um PR46779, ich brauche mir 
also mit allem >= 4.5.4 keine Sorgen zu machen?

Zur Erklärung, warum ich diese Version verwende: Das war halt die, die 
man bei Atmel runterladen konnte, als ich mit den AVR angefangen habe, 
und die noch anstandslos mit AVRStudio 4.19 funktioniert. (Inzwischen 
hat sich ja rausgestellt, dass auch die neuen mit den entsprechenden 
Parametern gehen, das wusste ich damals aber noch nicht: 
Beitrag "Avr Studio 4 und die neue AVR Toolchain - So funktionierts!")

Was für eine Version würdet ihr denn inzwischen empfehlen? Eine von 
Atmel gepatchte, oder eine (z.B. 4.9.3?) aus dem normalen gcc 
repository?

Mir kommts nicht so sehr auf neue features an. Hauptsache es tut.
Und mit dem AVRStudio 4.19 war ich bisher auch ganz zufrieden (läuft 
auch auf einem Uralt-Laptop noch, den ich ab und zu zum debuggen nehme, 
weils mir den Transport eines anderen Computers spart).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

sebastian schrieb:
> Johann L. schrieb:
>> Die 4.5 wird nicht mehr supportet, die älteste supportete Version ist
>> 4.9.
> D.h. einen Bug-Report, den man mit 4.9 nicht reproduzieren kann, wird
> niemand beachten, kann ich mir also sparen?

Ja.

Außerdem gibt's in ein paar Wochen die v6, dann wird die älteste noch 
Support genießende Version die v5 werden.

>> Außerdem verwendest du die 4.5.1 obwohl die 4.5.4 diesen Bug behoben
>> hat.
> Du meinst also, es handelt sich wirklich um PR46779, ich brauche mir
> also mit allem >= 4.5.4 keine Sorgen zu machen?

Den Bug konnte ich mit der 4.5.0 nachvollziehen. Und ja, es passt auf 
PR46779.  Ich wüsste keinen anderen Bug der ähnliche Artefakte erzeugt.

> Was für eine Version würdet ihr denn inzwischen empfehlen? Eine von
> Atmel gepatchte, oder eine (z.B. 4.9.3?) aus dem normalen gcc
> repository?

Generell: Wenn du dich für eine Release entschieden hast, dann willst du 
immer die neueste Bugfix-Release.  Bei v4 ist das also 4.y.x mit dem 
größten x, das du bekommen kannst.  Sinngemäß bei v5 aufwärts die v5.x 
mit dem größten x (ab v5 hat sich die Versionszählung geändert).

> Mir kommts nicht so sehr auf neue features an. Hauptsache es tut.
> Und mit dem AVRStudio 4.19 war ich bisher auch ganz zufrieden (läuft
> auch auf einem Uralt-Laptop noch, den ich ab und zu zum debuggen nehme,
> weils mir den Transport eines anderen Computers spart).

Die Atmel-Releases kümmern sich vor allem um Device-Support.

Die 4.7.3+ hatte auf mich nen ganz guten Eindruck gemacht, und die v5 
ist auch okay, wobei die 5.2 mit -flto -fipa-pta falschen Code erzeugen 
kann (fix in 5.3).  v5.x mit x < 2 funktioniert hingegen nicht.  Und 
gegen 4.9.3 ist auch nix zu sagen.

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.