Forum: Compiler & IDEs 16Bit aus 2x 8Bit, falsches Ergebnis bei Funktionsrückgabe


von Student T. (hberg)


Lesenswert?

Hallo,

ich habe soeben ein merkwürdiges Problem. Anbei ein kurzer Ausschnitt:
1
    
2
uint8_t tempLB = 0xc6; // als test
3
4
uint8_t tempHB = d1w_read();
5
//uint8_t tempHB = 0x01;
6
printf("hb: %x\n", tempHB);
7
8
uint16_t temp = ((uint16_t)tempHB << 8 ) | tempLB;
9
    
10
printf("temp: %d\n", temp);

d1w_read() gibt den Typ uint8_t zurück. Mit dem oberen Durchlauf erhalte 
ich als Rückgabe den Wert 0x01 (printf "hb: 1"). Die Berechnung von temp 
ergibt das falsche Ergebnis von Dezimal 2246. In der binärschreibweise 
erkennt man den Fehler:
0000 1000 1100 0110
   ->|

Das 0x01 kommt nicht wie durch tempHB<<8 an die 8te Stelle.

Wenn ich aber nun anstelle
1
uint8_t tempHB = d1w_read();
 folgendes ersetze
1
uint8_t tempHB = 0x01;
, erhalte ich das richtige Ergebnis von Dezimal 454 und in der 
binärschreibweise:
000 0001 1100 0110
     ->|

tempHB hat wie im oberen Durchlauf auch den Wert von 0x01 (printf: "hb: 
1").

Was ist denn da los? Ich kann mir das absolut nicht erklären. Beidesmal 
ist tempHB = 0x01, nur einmal wird der Wert durch die Funktion 
zugewiesen, und einmal direkt.

Hier noch die Funktion d1w_read():
1
uint8_t d1w_read() {
2
  
3
  uint8_t data = 0x00;
4
  
5
  for (uint8_t i = 0; i < 8; i++) {
6
    
7
    // set DDR to output
8
    D1W_DDR |= (1 << D1W_DQ);
9
  
10
    // put signal low
11
    D1W_PORT &= ~(1 << D1W_DQ);
12
  
13
    // hold down for at least 1us
14
    _delay_us(1);
15
  
16
    // release by DDR to input
17
    D1W_DDR &= ~(1 << D1W_DQ);
18
  
19
    // wait
20
    _delay_us(10);
21
  
22
    // read 1 (high)
23
    if (D1W_PIN & (1 << D1W_DQ)) {
24
      data |= (1 << i);
25
      
26
    //  read 0 (low)
27
    } else {
28
      
29
      data &= ~(1 << i);
30
      
31
      // wait until high
32
      //while (D1W_PIN & (1 << D1W_DQ));
33
    }
34
    
35
    // total slot at least 60us
36
    _delay_us(55);
37
  }
38
  
39
  return data;
40
}

Ich bin absolut ratlos. Wird durch den Compiler irgendwas wegoptimiert?

Freue mich um jede Hilfe..

Gruß,
Kevin

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mit deinen Infor kann man das Problem nicht nachvollziehen, denn es ist 
kein gültiger C-Code.

Um das Problem zu untersuchen, schaue dir den erzeugten Assembler-Code 
oder ein Disassembly des erzeuigten o, elf oder hex an.

Ist dieser Code korrekt, dann liegt dein Problem woanners, zB 
Stack-Überlauf, Controller ist Fehlpressung, ...

Ist der Code nicht korrekt, dann handelt es sich um einen Tool-Fehler 
(Compiler, Linker, Assembler, ...)

Um das Problem nachzuvollziehen braucht man mindestens ein gültiges 
(compilierbares) Stückchen C-Code, die Compiler-Version und die 
Kommandozeilenoptionen.

von Student T. (hberg)


Angehängte Dateien:

Lesenswert?

Fehlpressung kann ich ausschließen, an einem zweiten AVR tritt der exakt 
gleiche Fehler auf. Leider werde ich aus dem reinen Assembler-Code nicht 
schlau (*.lss), da ich nicht Assembler spreche. Auch ein diff der beiden 
lss-Dateien bringt mich nicht weiter.

Ich kann den Fehler aber noch einfacher reproduzieren:

Falsches Ergebnis (ds18b20_1.zip):
1
uint8_t tempLB = d1w_read();
2
uint8_t tempHB = d1w_read();
3
uint16_t temp = ((uint16_t)tempHB << 8 ) | tempLB;
4
//printf("%x\n", temp); // <--
5
printf("temp: %d\n", temp);

Ergebnis wie erwartet (ds18b20_2.zip):
1
uint8_t tempLB = d1w_read();
2
uint8_t tempHB = d1w_read();
3
uint16_t temp = ((uint16_t)tempHB << 8 ) | tempLB;
4
printf("%x\n", temp); // <--
5
printf("temp: %d\n", temp);

Es scheint, als würde die reine Ausgabe von printf() das Ergebnis 
verändern. Aus z.b. einem 1d2 (richtig) wird ein 8d2, sobald ich das 
printf weglasse.

Das C-File hängt auch im Anhang.

Anbei noch das Compiler-Log:
1
------ Build started: Project: DS18B20, Configuration: Release AVR ------
2
Build started.
3
Project "DS18B20.cproj" (default targets):
4
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
5
Target "CoreBuild" in file "C:\Program Files (x86)\Atmel\AVR Studio 5.1\Vs\Compiler.targets" from project "Y:\work\avrstudio\Projects\DS18B20\DS18B20\DS18B20.cproj" (target "Build" depends on it):
6
  Task "RunCompilerTask"
7
    C:\Program Files (x86)\Atmel\AVR Studio 5.1\make\make.exe all 
8
ser.c
9
    Invoking: AVR/GNU C Compiler
10
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc.exe"  -funsigned-char -funsigned-bitfields -I"../../../../../git/rfm23-lib"  -Os -fpack-struct -fshort-enums -Wall -c -std=gnu99 -MD -MP -MF "ser.d" -MT"ser.d"  -mmcu=atmega328p  -o"ser.o" "../../../../../git/rfm23-lib/ser.c" 
11
Y:\work\git\rfm23-lib\ser.c(10,1): initialization from incompatible pointer type
12
    Finished building: ../../../../../git/rfm23-lib/ser.c
13
DS18B20.c
14
    Invoking: AVR/GNU C Compiler
15
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc.exe"  -funsigned-char -funsigned-bitfields -I"../../../../../git/rfm23-lib"  -Os -fpack-struct -fshort-enums -Wall -c -std=gnu99 -MD -MP -MF "DS18B20.d" -MT"DS18B20.d"  -mmcu=atmega328p  -o"DS18B20.o" ".././DS18B20.c" 
16
    Finished building: .././DS18B20.c
17
    Building target: DS18B20.elf
18
    Invoking: AVR/GNU C Linker
19
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc.exe" -o DS18B20.elf  ser.o DS18B20.o   -Wl,-Map="DS18B20.map" -Wl,-lm   -mmcu=atmega328p  
20
    Finished building target: DS18B20.elf
21
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-objcopy.exe" -O ihex -R .eeprom -R .fuse -R .lock -R .signature  "DS18B20.elf" "DS18B20.hex"
22
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-objcopy.exe" -j .eeprom  --set-section-flags=.eeprom=alloc,load --change-section-lma .eeprom=0  --no-change-warnings -O ihex "DS18B20.elf" "DS18B20.eep" || exit 0
23
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-objdump.exe" -h -S "DS18B20.elf" > "DS18B20.lss"
24
    "C:\Program Files (x86)\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-size.exe" -C --mcu=atmega328p  "DS18B20.elf"
25
    AVR Memory Usage
26
    ----------------
27
    Device: atmega328p
28
    Program:    2256 bytes (6.9% Full)
29
    (.text + .data + .bootloader)
30
    Data:         38 bytes (1.9% Full)
31
    (.data + .bss + .noinit)
32
  Done executing task "RunCompilerTask".
33
Done building target "CoreBuild" in project "DS18B20.cproj".
34
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
35
Target "Build" in file "C:\Program Files (x86)\Atmel\AVR Studio 5.1\Vs\Avr.common.targets" from project "Y:\work\avrstudio\Projects\DS18B20\DS18B20\DS18B20.cproj" (entry point):
36
Done building target "Build" in project "DS18B20.cproj".
37
Done building project "DS18B20.cproj".
38
39
Build succeeded.
40
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

> avr-gcc DS18B20.c -S -Os -std=gnu99 -mmcu=atmega328p

gibt:

> DS18B20.c:13:17: fatal error: ser.h: No such file or directory

Ausserdem ist avr-gcc 3.3 asbach uralt. Hol dir mal was neues.

Dein Fehler sieht nach PR46779 aus, gefixt in 4.6.2 oder neuer und auch 
in 4.5.4.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Ausserdem ist avr-gcc 3.3 asbach uralt. Hol dir mal was neues.

Ich hatte mich auch zunächst über diese ominöse "Version" 3.3.1.27 
gewundert, da sie ja mit AVRStudio5.1 so gar nicht zusammenpasst.

Aber bei genauerem Hingucken ist das nicht die gcc-Version, sondern die 
Atmel-Versionsnummer ihrer eigenen Toolchain.

Da ich auch das AVRStudio5.1 drauf habe, habe ich mal nachgeschaut:
1
C:\>"C:\Program Files\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc" -v
2
Using built-in specs.
3
COLLECT_GCC=C:\Program Files\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc
4
COLLECT_LTO_WRAPPER=c:/program files/atmel/avr studio 5.1/extensions/atmel/avrgcc/3.3.1.27/avrtoolchain/bin/../libexec/gcc/avr/4.5.1/lt
5
o-wrapper.exe
6
Target: avr
7
Configured with: /usr/local/avr32studio/hudson/workspace/avr8-gnu-toolchain/src/gcc/configure LDFLAGS=-L/storage/hudson/workspace/avr8-
8
gnu-toolchain/avr8-gnu-toolchain-win32_x86/lib CPPFLAGS= --target=avr --host=i686-pc-mingw32 --build=x86_64-pc-linux-gnu --prefix=/stor
9
age/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-win32_x86 --libdir=/storage/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-too
10
lchain-win32_x86/lib --enable-languages=c,c++ --with-dwarf2 --enable-doc --disable-shared --disable-libada --disable-libssp --disable-n
11
ls --with-mpfr=/storage/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-win32_x86 --with-gmp=/storage/hudson/workspace/avr8-gnu-
12
toolchain/avr8-gnu-toolchain-win32_x86 --with-mpc=/storage/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-win32_x86 --enable-wi
13
n32-registry=avrtoolchain --enable-fixed-point --with-pkgversion=AVR_8_bit_GNU_Toolchain_3.3.1_466 --with-bugurl=http://www.atmel.com
14
Thread model: single
15
gcc version 4.5.1 (AVR_8_bit_GNU_Toolchain_3.3.1_466)

Ist also gcc 4.5.1.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:

> Ist also gcc 4.5.1.

Um PR46779 auszuschliessen, musst du in deinen erzeugten Code schauen 
oder ein Update auf 4.5.4, 4.6.2, 4.6.4 oder 4.7.1 machen.

Von 4.6.3 oder 4.7.0 rate ich aus anderen Gründen ab.

von Student T. (hberg)


Lesenswert?

Mit dem Update der AVR Toolchain auf 3.4.0 hat es geklappt. Nun wird das 
richtige Ergebnis mit und ohne printf ausgegeben.
1
gcc version 4.6.2 (AVR_8_bit_GNU_Toolchain_3.4.0_663)

Vielen Dank!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Johann L. schrieb:
> Frank M. schrieb:
>
>> Ist also gcc 4.5.1.
>
> Um PR46779 auszuschliessen, musst du in deinen erzeugten Code schauen
> oder ein Update auf 4.5.4, 4.6.2, 4.6.4 oder 4.7.1 machen.

Du verwechselst mich gerade mit dem TO, ich wollte eigentlich nur diese 
Info beisteuern ;-)

> Von 4.6.3 oder 4.7.0 rate ich aus anderen Gründen ab.

Hm, ich habe hier auch u.a. die 4.7.0. auf meinem Rechner - auch wenn 
ich meist die 4.3.3 (WinAVR20100110) verwende. Könntest Du erläutern, 
was an der 4.7.0 zu bemängeln ist? Ist denn die 4.7.1 okay?

Gruß,

Frank

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Frank M. schrieb:
> Johann L. schrieb:
>> Von 4.6.3 oder 4.7.0 rate ich aus anderen Gründen ab.
>
> Hm, ich habe hier auch u.a. die 4.7.0. auf meinem Rechner - auch wenn
> ich meist die 4.3.3 (WinAVR20100110) verwende. Könntest Du erläutern,
> was an der 4.7.0 zu bemängeln ist? Ist denn die 4.7.1 okay?

avr-gcc 4.7 hat ein paar neue Features:

- ATXmega Support
- Named Address Spaces wie __flash etc.
- AVR-spezifische Built-Ins wie __buitin_avr_sei()
- 24-Bit Integers

Bei diesen neuen Features gabs ein paar Bugs, die zu falschem Code 
führen:

- PR52506, PR52461: ISRs für Xmegas > 64KiB RAM, d.h. mit EBI

- PR53033: wenn man mit memcpy 3 Bytes kopiert (nur Xmega)

- PR52484, PR52507, PR52505: Probleme mit dem 24-Bit Address Space
  __memx

- PR51527: Manche binäre Operanden auf __int24 mit Konstanten,
  die ausserhalb dem Bereich vom __int24 liegen und nicht auf __int24
  gecastet wurden.

- PR53256: Die AVR-Libc enthält Makros für ISR, die Attribut-
  Kombinationen verwenden, die nie dokumentiert/spezifiziert waren,
  zB eine Funktion gleichzeitig als interrupt und als signal zu
  attributieren.  Um das zu beheben musste die Semantik von interrupt
  und signal im Compiler geändert werden, da es der AVR-Libc nicht
  möglich ist, das ISR-Makro anders zu schreiben.

- PR52737: -mtiny-stack wird als Multilib-Option verwendet, was ein
  Design-Fehler war.  Ab 4.7.1 wird -msp8 als Multilib-Option genommen.

- PR52692: AVR-spezifische Built-Ins funktionieren nicht mit LTO

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.