www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Fehler bei inline Anweisung


Autor: Andre H. (andre01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
ich habe mal ne Frage zu einer Compilerfehlermeldung. Ich versuche 
gerade den Datenrekorder aus der Codesammlung zu verwirklichen. 
Komischerweise bekomme ich beim Compilieren diese Fehlermeldung...
Ich kann mit der nicht viel anfangen
> "make.exe" all

-------- begin --------
avr-gcc (WinAVR 20090313) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Compiling C: ../../Logger/MrData/spi.c
avr-gcc -c -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=3686400UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./../../Logger/MrData/spi.lst  -std=gnu99 -Wundef -MMD -MP -MF .dep/spi.o.d ../../Logger/MrData/spi.c -o ../../Logger/MrData/spi.o 

Linking: main.elf
avr-gcc -mmcu=atmega8 -I. -gdwarf-2 -DF_CPU=3686400UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 -Wundef -MMD -MP -MF .dep/main.elf.d main.o ../../Logger/MrData/delay.o ../../Logger/MrData/fat16.o ../../Logger/MrData/mmc.o ../../Logger/MrData/spi.o --output main.elf -Wl,-Map=main.map,--cref     -lm
../../Logger/MrData/mmc.o: In function `MMC_cleanup':
D:\AVR\Logger\MrData/../../Logger/MrData/mmc.c:190: undefined reference to `spi_io'
D:\AVR\Logger\MrData/../../Logger/MrData/mmc.c:191: undefined reference to `spi_io'
../../Logger/MrData/mmc.o: In function `MMC_get_sec_stop_w':
D:\AVR\Logger\MrData/../../Logger/MrData/mmc.c:407: undefined reference to `spi_io'
D:\AVR\Logger\MrData/../../Logger/MrData/mmc.c:408: undefined reference to `spi_io'
D:\AVR\Logger\MrData/../../Logger/MrData/mmc.c:410: undefined reference to `spi_io'
../../Logger/MrData/mmc.o:D:\AVR\Logger\MrData/../../Logger/MrData/mmc.c:381: more undefined references to `spi_io' follow
make.exe: *** [main.elf] Error 1

Der Code den der Compiler nicht mag :
 inline u08 spi_io(u08 data){
/*  UDR0 = data;
  while (!(UCSR0A&(1<<RXC0)));
  return UDR0;*/
  outp(data, SPDR);
  while((inp(SPSR)&(1<<SPIF)) == 0x00){};
  return inp(SPDR);

Ich habe an dem Projekt nichts geändert.
Vielleicht weiß ja jemand was mein Compiler daran nicht mag...


Gruß
André

Autor: Lasse S. (cowz) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du die Funktion denn vorher deklariert?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deklariert ist die Funktion, da sonst der Compiler motzen würde. Wer 
hier motzt, ist der Linker.
Und das lässt vermuten, daß es eine Deklaration in Form eines 
Funktionsprototypen gibt, die nicht darauf hinweist, daß das eine 
inline-Funktion sein soll.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde ich auch ein static Problem nicht ausschliessen.

Gut wäre natürlich gewesen, wenn der TO ganz einfach einen Link zum 
Projekt in der Codesammlung gesetzt hätte. Dann hätte man sich den Code 
ansehen können.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andre H. schrieb:
> Der Code den der Compiler nicht mag :

Da gibt es nirgends eine Compilermeldung, die besagt, dass er daran
was auszusetzen hätte.

Was es dafür gibt ist eine *Linker*meldung.  Der findet die nämlich
nicht.  Wie auch?  Wenn sie "inline" sein soll, muss der Compiler
sie bereits auflösen können, nicht erst der Linker -- der kann sowas
nicht mehr nachträglich in den Code reinbasteln.

Damit der Compiler sie aber überall gleichermaßen kennt und auch in
den Code einfügen kann, gibt es für inline-Funktionen eine Ausnahme
von der "goldenen" Regel, nach der man keine Implementierungen direkt
in Headerdateien schreibt: inline sollte man, damit es Sinn hat,
in der Headerdatei implementieren.  Damit man nicht später noch über
andere Kasperfallen stolpert, bitte gleich und immer "static inline".

Autor: Andre H. (andre01)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
danke schon mal für die Antworten...

@ Karl heinz Buchegger
stimmt habe ich versäumt hier der Link zu dem Projekt..
[Beitrag "Datenrekorder auf SD-Karte mit mega88"]
und die Zip Datei auch mal mit angefügt bei der mir das passiert...

Das mit dem static vor dem inline habe ich schon mal getestet da es hier 
in Forum in einem andren Beitrag angeführt wurde, aber es gab immer noch 
die Meckerei.

Gruß André

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
lol

Schmeiss das inline bei der Funktion im spi.c raus.
Das ist sowieso sinnlos dort.

Da hat jemand nicht verstanden was inline macht und wie es funktioniert.

Obwohl: Zu einem Fehler dürfte es trotzdem nicht kommen. Solange die 
Funktion nicht static ist, muss der Compiler einen Funktionsrumpf 
erzeugen, selbst wenn die Funktion als inline markiert ist. Eventuelle 
Compilerschalter könnten das noch überschreiben, aber die hab ich jetzt 
nicht mehr geprüft.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Obwohl: Zu einem Fehler dürfte es trotzdem nicht kommen.

Doch.  C99 hat die Semantik von inline etwas anders definiert, als
GCC sie historisch implementiert hat.  Eine "extern inline"-Funktion
muss in C99 zwingend auch noch eine Implementierung ohne "inline"
liefern, denn es ist dem Compiler dann freigestellt, ob er die
Funktion inline erweitert oder ob er die extern implementierte
Funktion ruft.

Andre H. schrieb:
> Das mit dem static vor dem inline habe ich schon mal getestet da es hier
> in Forum in einem andren Beitrag angeführt wurde, aber es gab immer noch
> die Meckerei.

Klar, weil du noch gar nicht verstanden hast, wie der Compiler eine
inline-Funktion implementieren muss, damit sie Sinn hat: er muss
den Code an jeder Stelle, an der die Funktion "gerufen" wird, auch
besitzen.

Kurzfassung nochmal: "inline"-Funktionen, die in mehr als einer
Quelldatei benutzt werden sollen, gehören nicht in eine .c-Datei,
sondern in eine .h-Datei.  "inline" sollte man immer als "static
inline" schreiben (sofern man nicht ganz genau verstanden hat, wie
C99 mit "extern inline" umgeht, und dieses Verhalten explizit
wünscht).

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Karl heinz Buchegger schrieb:
>> Obwohl: Zu einem Fehler dürfte es trotzdem nicht kommen.
>
> Doch.  C99 hat die Semantik von inline etwas anders definiert, als
> GCC sie historisch implementiert hat.  Eine "extern inline"-Funktion
> muss in C99 zwingend auch noch eine Implementierung ohne "inline"
> liefern, denn es ist dem Compiler dann freigestellt, ob er die
> Funktion inline erweitert oder ob er die extern implementierte
> Funktion ruft.

Versteh ich da etwas falsch.
Es war doch auch bisher so, dass eine inline Funktion eine 
Implementierung haben musste. Es sei denn sie ist static inline, weil 
nur dann sicher gestellt ist, dass die Funktion von nirgendwo anders 
aufgerufen werden kann.

Autor: Andre H. (andre01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Schmeiss das inline bei der Funktion im spi.c raus.
> Das ist sowieso sinnlos dort.

Wie meinst denn das jetzt? Ersatzlos streichen geht ja nicht ist ja in 
anderen Dateien in Verwendung...

Naja ich habe das ja nicht programmiert...
Aber wenn ich die inline Anweisung richtig verstehe, wird der Code 
direkt an der Stelle erzeugt und eingefügt wo er so zusagen aufgerufen 
wird.
( so tief in c stecke ich noch nicht drin aber es wird besser )

Die Frage liegt das nun an dem Makefile was ich selbst gemacht habe oder 
an der spi.c/.h?

Achja,
im Betrag zu dem Projekt wird erwähnt das das mit WinAVR compiliert 
wurde (2008), deshalb wundere ich mich das es bei mir nicht klappt...


Gruß André

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andre H. schrieb:
> Karl heinz Buchegger schrieb:
>> Schmeiss das inline bei der Funktion im spi.c raus.
>> Das ist sowieso sinnlos dort.
>
> Wie meinst denn das jetzt? Ersatzlos streichen geht ja nicht ist ja in
> anderen Dateien in Verwendung...

Einfach das Schlüsselwort inline ersatzlos streichen.
08 spi_io(u08 data){
/*  UDR0 = data;
  while (!(UCSR0A&(1<<RXC0)));
  return UDR0;*/
  outp(data, SPDR);
  while((inp(SPSR)&(1<<SPIF)) == 0x00){};
  return inp(SPDR);
}

> Aber wenn ich die inline Anweisung richtig verstehe, wird der Code
> direkt an der Stelle erzeugt und eingefügt wo er so zusagen aufgerufen
> wird.
> ( so tief in c stecke ich noch nicht drin aber es wird besser )

Und wie soll der Compiler das machen, wenn er den Funktionskörper an der 
Aufrufstelle nie zu Gesicht bekommt?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Es war doch auch bisher so, dass eine inline Funktion eine
> Implementierung haben musste.

In C99 bist du (als Programmierer) verantwortlich, die externe
Implementierung dafür zu liefern.  Der Compiler darf sich dann
aussuchen, ob er die inline-Implementierung benutzt oder die
externe.  Natürlich dürfen beide auch komplett was verschiedenes
implementieren. >:-o

Andre H. schrieb:
> Wie meinst denn das jetzt? Ersatzlos streichen geht ja nicht ist ja in
> anderen Dateien in Verwendung...

Aus spi.c nach spi.h verschieben und dort "static inline" schreiben.
Oder halt (wie Karl Heinz empfiehlt) das "inline" wegnehmen und es
in spi.c belassen.

Wer auch immer das in spi.c implementiert hat, hat inline auch bloß
nicht verstanden.  Mit -std=c99 (oder -std=gnu99) wird das fehlende
Verständnis dann zum fatalen Fehler.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Karl heinz Buchegger schrieb:
>> Es war doch auch bisher so, dass eine inline Funktion eine
>> Implementierung haben musste.
>
> In C99 bist du (als Programmierer) verantwortlich, die externe
> Implementierung dafür zu liefern.  Der Compiler darf sich dann
> aussuchen, ob er die inline-Implementierung benutzt oder die
> externe.  Natürlich dürfen beide auch komplett was verschiedenes
> implementieren. >:-o

D.h. wenn man bisher inline richtig gemacht hat, hat sich eigentlich 
nichts verändert.

Autor: Andre H. (andre01)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok danke,
das Übersetzten hat schon mal geklappt. Gab nur noch ein paar warnungen.
Sobald die Platine und der 168 eigetroffen sind werde ich mal schauen 
was dabei raus kommt...

Danke


André

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.