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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Student T. (hberg)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe soeben ein merkwürdiges Problem. Anbei ein kurzer Ausschnitt:
    
uint8_t tempLB = 0xc6; // als test

uint8_t tempHB = d1w_read();
//uint8_t tempHB = 0x01;
printf("hb: %x\n", tempHB);

uint16_t temp = ((uint16_t)tempHB << 8 ) | tempLB;
    
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
uint8_t tempHB = d1w_read();
 folgendes ersetze
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():
uint8_t d1w_read() {
  
  uint8_t data = 0x00;
  
  for (uint8_t i = 0; i < 8; i++) {
    
    // set DDR to output
    D1W_DDR |= (1 << D1W_DQ);
  
    // put signal low
    D1W_PORT &= ~(1 << D1W_DQ);
  
    // hold down for at least 1us
    _delay_us(1);
  
    // release by DDR to input
    D1W_DDR &= ~(1 << D1W_DQ);
  
    // wait
    _delay_us(10);
  
    // read 1 (high)
    if (D1W_PIN & (1 << D1W_DQ)) {
      data |= (1 << i);
      
    //  read 0 (low)
    } else {
      
      data &= ~(1 << i);
      
      // wait until high
      //while (D1W_PIN & (1 << D1W_DQ));
    }
    
    // total slot at least 60us
    _delay_us(55);
  }
  
  return data;
}

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

Freue mich um jede Hilfe..

Gruß,
Kevin

von Johann L. (gjlayde) Benutzerseite


Bewertung
0 lesenswert
nicht 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:

Bewertung
0 lesenswert
nicht 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):
uint8_t tempLB = d1w_read();
uint8_t tempHB = d1w_read();
uint16_t temp = ((uint16_t)tempHB << 8 ) | tempLB;
//printf("%x\n", temp); // <--
printf("temp: %d\n", temp);

Ergebnis wie erwartet (ds18b20_2.zip):
uint8_t tempLB = d1w_read();
uint8_t tempHB = d1w_read();
uint16_t temp = ((uint16_t)tempHB << 8 ) | tempLB;
printf("%x\n", temp); // <--
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:
------ Build started: Project: DS18B20, Configuration: Release AVR ------
Build started.
Project "DS18B20.cproj" (default targets):
Target "PreBuildEvent" skipped, due to false condition; ('$(PreBuildEvent)'!='') was evaluated as (''!='').
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):
  Task "RunCompilerTask"
    C:\Program Files (x86)\Atmel\AVR Studio 5.1\make\make.exe all 
ser.c
    Invoking: AVR/GNU C Compiler
    "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" 
Y:\work\git\rfm23-lib\ser.c(10,1): initialization from incompatible pointer type
    Finished building: ../../../../../git/rfm23-lib/ser.c
DS18B20.c
    Invoking: AVR/GNU C Compiler
    "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" 
    Finished building: .././DS18B20.c
    Building target: DS18B20.elf
    Invoking: AVR/GNU C Linker
    "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  
    Finished building target: DS18B20.elf
    "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"
    "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
    "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"
    "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"
    AVR Memory Usage
    ----------------
    Device: atmega328p
    Program:    2256 bytes (6.9% Full)
    (.text + .data + .bootloader)
    Data:         38 bytes (1.9% Full)
    (.data + .bss + .noinit)
  Done executing task "RunCompilerTask".
Done building target "CoreBuild" in project "DS18B20.cproj".
Target "PostBuildEvent" skipped, due to false condition; ('$(PostBuildEvent)' != '') was evaluated as ('' != '').
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):
Done building target "Build" in project "DS18B20.cproj".
Done building project "DS18B20.cproj".

Build succeeded.
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========

von Johann L. (gjlayde) Benutzerseite


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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:
C:\>"C:\Program Files\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc" -v
Using built-in specs.
COLLECT_GCC=C:\Program Files\Atmel\AVR Studio 5.1\extensions\Atmel\AVRGCC\3.3.1.27\AVRToolchain\bin\avr-gcc
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
o-wrapper.exe
Target: avr
Configured with: /usr/local/avr32studio/hudson/workspace/avr8-gnu-toolchain/src/gcc/configure LDFLAGS=-L/storage/hudson/workspace/avr8-
gnu-toolchain/avr8-gnu-toolchain-win32_x86/lib CPPFLAGS= --target=avr --host=i686-pc-mingw32 --build=x86_64-pc-linux-gnu --prefix=/stor
age/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-win32_x86 --libdir=/storage/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-too
lchain-win32_x86/lib --enable-languages=c,c++ --with-dwarf2 --enable-doc --disable-shared --disable-libada --disable-libssp --disable-n
ls --with-mpfr=/storage/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-win32_x86 --with-gmp=/storage/hudson/workspace/avr8-gnu-
toolchain/avr8-gnu-toolchain-win32_x86 --with-mpc=/storage/hudson/workspace/avr8-gnu-toolchain/avr8-gnu-toolchain-win32_x86 --enable-wi
n32-registry=avrtoolchain --enable-fixed-point --with-pkgversion=AVR_8_bit_GNU_Toolchain_3.3.1_466 --with-bugurl=http://www.atmel.com
Thread model: single
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


Bewertung
0 lesenswert
nicht 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)


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

Vielen Dank!

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
0 lesenswert
nicht 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


Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.