www.mikrocontroller.net

Forum: Compiler & IDEs undefined reference to `log' - obwohl #include<math.h>


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

gleich vornweg - ich bin newbee im Bereich ARM und arbeite mich gerade 
ein mit Hilfe des Buch "C Programming for Embedded Microcontrollers".
Ich nutze das Olimex-DevBoard At91SAM7x256 mit Eclipse und 
Yagarto-Toolchain.
Bisher war alles lösbar.

Nun wollte ich die "log"-Funktion nutzen. Trotz einbinden der math.h 
folgt beim Kompilieren folgende Fehlermeldung
**** Build of configuration Default for project Tempsense ****

make all 
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 Code/main.c -o main.o
arm-elf-gcc -nostartfiles -Wl,-Map,out.map,--cref -T Startup/RAM.ld  -n -o tempsens.elf startup.o main.o syscalls.o dbgu.o
main.o: In function `CHECK_TEMPERATUR':
E:\ARM_C\_Ram-Prog\Tempsens/Code/main.c:74: undefined reference to `log'
collect2: ld returned 1 exit status
make: *** [sram] Error 1

Warum???
#include <stdio.h>
#include <math.h>
#include "at91sam7x.h"
#include "dbgu.h"

void CHECK_TEMPERATUR(void);
void INIT_ADC(void);
void Delay(void);
void INIT_LCD(void);

char my_str[40];

int main(void)
{
  DBGUInit(DBGU_115200);
  DBGUTxMsg(my_str);
  INIT_LCD();
  while (1)
  {
    Delay();
    CHECK_TEMPERATUR();
  }
}

void INIT_LCD(void)
{
...
}

void CHECK_TEMPERATUR(void)
{
    unsigned int ADC5, i;
    float Rtemp, Temp;
    INIT_ADC();
    ADC5=0;
    for(i=0;i<128;i++) //Mittelwertbildung - 128 Werte
    {
      ADC_CR = 0x00000002;        //Starten der Wandlung
      while(!(ADC_SR & 0x00000020));
      ADC5 += ADC_CDR5;
    }
    ADC5 /= 128;
    Rtemp = ( (1024-ADC5) * 1800 ) /ADC5;

    Temp = log(Rtemp/2595.2) / (-0.0431));

    sprintf(my_str,"\rAktuelle Temp = %f", Temp);
    DBGUTxMsg(my_str);
}


Autor: tpircher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du must die libm dazulinken. Fuege die Option -lm zu dem letzten Aufruf 
von gcc (linking stage) dazu.

Autor: Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Daniel schrieb:
>     Temp = log(Rtemp/2595.2) / (-0.0431));

Da stimmt was mit den Klammern nicht

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Thomas: Das mit den Klammern ist durch säubern für hier enstanden.

@tpircher: Wo mache ich das?
Hier mein "makefile"
#----------------------------------------------------------------------------------
#   FILENAME:       Makefile
#
#   DESCRIPTION:    Makefile for compiling and linking the OSPLC Framework code
#
#----------------------------------------------------------------------------------

#----------------------------------------------------------------------------------
# TODO: Change the name of the output files for your project
#    (Replace "Framework" with your projects name)
#----------------------------------------------------------------------------------
OUTFILE_SRAM=tempsens

TARGET=AT91SAM7X256

INCL=./Drivers

# Paths to standard and maths library files - assumes default YAGARTO installation
LIBGCC=C:/Programme/yagarto/lib/gcc/arm-elf/4.4.2/libgcc.a
LIBC=C:/Programme/yagarto/arm-elf/lib/libc.a
LIBM=C:/Programme/yagarto/arm-elf/lib/libm.a
LIBA=C:/Programme/yagarto/arm-elf/lib/liba.a


# Optimisation settings
# optimisation for size
#OPTIM=-Os
# no optimisation - for debug mode
OPTIM=-O0

AS=arm-elf-gcc
CC=arm-elf-gcc
LD=arm-elf-gcc
OBJCOPY=arm-elf-objcopy
OBJDUMP=arm-elf-objdump
CCFLAGS=-g -mcpu=arm7tdmi $(OPTIM) -Wall -I$(INCL) -D$(TARGET)
ASFLAGS=-D__ASSEMBLY__ -D$(TARGET) -g -mcpu=arm7tdmi -c $(OPTIM) -Wall -I$(INCL)

# Linker flags.
#  -Wl,... :    tell GCC to pass this to linker.
#  -Map    :    create map file
#  --cref  :    add cross reference to map file
LDFLAGS_R+=-nostartfiles -Wl,-Map,out.map,--cref
LDFLAGS_R+=-T Startup/RAM.ld


#----------------------------------------------------------------------------------
# TODO: Add all the object files generated for you project to the framework
#    objects listed below
#----------------------------------------------------------------------------------
OBJS=startup.o \
     main.o \
   syscalls.o \
   dbgu.o

rebuild: clean all

all: sram

sram: $(OBJS)
  $(LD) $(LDFLAGS_R)  -n -o $(OUTFILE_SRAM).elf $(OBJS)
  $(OBJCOPY) --strip-debug --strip-unneeded $(OUTFILE_SRAM).elf -O binary $(OUTFILE_SRAM).bin
  
#----------------------------------------------------------------------------------
# TODO: Add your object file compilation instructions
#----------------------------------------------------------------------------------

main.o: Code/main.c
  $(CC) -c $(CCFLAGS) Code/main.c -o main.o

startup.o:  Startup/startup.S
  $(AS) $(ASFLAGS) Startup/startup.S -o startup.o
  
dbgu.o: Drivers/dbgu.c
  $(CC) -c $(CCFLAGS) Drivers/dbgu.c -o dbgu.o
  
syscalls.o: syscalls.c 
  $(CC) -c $(CCFLAGS) syscalls.c -o syscalls.o 
  
clean:
  -rm *.o *.bin *.elf *.map


Autor: Thomas Pircher (tpircher) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
in der Sektion Linker flags.
LDFLAGS_R+=-lm

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meldung erscheint immer noch

Autor: Thomas Pircher (tpircher) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Taucht die Option -lm im Output von make auf? Hast du ein "make clean" 
und ein anschliessendes "make" probiert?

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
**** Build of configuration Default for project Tempsense ****

make all 
arm-elf-gcc -nostartfiles -Wl,-Map,out.map,--cref -T Startup/RAM.ld -lm  -n -o tempsens.elf startup.o main.o syscalls.o dbgu.o
main.o: In function `CHECK_TEMPERATUR':
E:\ARM_C\_Ram-Prog\Tempsens/Code/main.c:74: undefined reference to `log'
collect2: ld returned 1 exit status
make: *** [sram] Error 1

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
clean und danach build
**** Build of configuration Default for project Tempsense ****

make all 
arm-elf-gcc -D__ASSEMBLY__ -DAT91SAM7X256 -g -mcpu=arm7tdmi -c -O0 -Wall -I./Drivers Startup/startup.S -o startup.o
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 Code/main.c -o main.o 
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 syscalls.c -o syscalls.o 
arm-elf-gcc -c -g -mcpu=arm7tdmi -O0 -Wall -I./Drivers -DAT91SAM7X256 Drivers/dbgu.c -o dbgu.o
arm-elf-gcc -nostartfiles -Wl,-Map,out.map,--cref -T Startup/RAM.ld -lm  -n -o tempsens.elf startup.o main.o syscalls.o dbgu.o
main.o: In function `CHECK_TEMPERATUR':
E:\ARM_C\_Ram-Prog\Tempsens/Code/main.c:74: undefined reference to `log'
collect2: ld returned 1 exit status
make: *** [sram] Error 1

Autor: Thomas Pircher (tpircher) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist sehr seltsam. Kannst du gar keine Funktion aus libm aufrufen? 
Wie steht es mit logf(), oder pow()?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das "-lm" muss hinter die Object-Files (ja, beim Linken spielt die 
Reihenfolge eine Rolle).

Autor: Thomas Pircher (tpircher) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> ja, beim Linken spielt die Reihenfolge eine Rolle).

andenkopfschlag Natuerlich! :)
Die Zeile im Makefile koennte dann so aussehen:
sram: $(OBJS)
  $(LD) $(OBJS) $(LDFLAGS_R) -n -o $(OUTFILE_SRAM).elf

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe etwas rausgefunden
funkioniert nicht: Temp = log(Rtemp);
funktioniert     : Temp = log(2.2);

d.h. steht ein Wert in der Klammer funktioniert es und wenn der 
Variablenname innerhalb der Klammer steht macht er mir das Problem beim 
Kompilieren

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!-)

Ich habe aus:
sram: $(OBJS)
  $(LD) $(LDFLAGS_R)  -n -o $(OUTFILE_SRAM).elf $(OBJS)

das gemacht
sram: $(OBJS)
  $(LD) $(OBJS) $(LDFLAGS_R)  -n -o $(OUTFILE_SRAM).elf 

UND ES FUNKTIONIERT

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, 
Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, 
Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke, Danke


Ich habe da schon den ganzen Tag damit verbracht

Autor: Thomas Pircher (tpircher) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein Problem wurde schon von Stefan geloest, aber nur zur Information:

Daniel schrieb:
> funktioniert     : Temp = log(2.2);
> funkioniert nicht: Temp = log(Rtemp);

Du verwendest einen neuen GCC? Der erkennt, dass log(2.2) eine Konstante 
ist und ersetzt den Funktionsaufruf mit dem Ergebnis des Ausdrucks.

Das Ergebnis von log(Rtemp) ist zur Kompilationszeit nicht bekannt, und 
GCC muss die Funktion log() also aufrufen.

Im ersten Fall wird die log()-Funktion also nicht dazugelinkt, im 
zweiten Fall wird sie das. Deshalb hast du auch den Fehler nur bei der 
zweiten Variante bekommen.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas Pircher schrieb:
> Du verwendest einen neuen GCC? Der erkennt, dass log(2.2) eine Konstante
> ist und ersetzt den Funktionsaufruf mit dem Ergebnis des Ausdrucks.

Huh, der Compiler rechnet Logarithmusfunktionen aus? Cool.

Autor: Thomas Pircher (tpircher) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark Brandis schrieb:
> Huh, der Compiler rechnet Logarithmusfunktionen aus? Cool.

GCC kann das seit v4.3. Ein Auszug aus 
http://gcc.gnu.org/gcc-4.3/changes.html :

> The GCC middle-end has been integrated with the MPFR library. This allows
> GCC to evaluate and replace at compile-time calls to built-in math
> functions having constant arguments with their mathematically equivalent
> results. In making use of MPFR, GCC can generate correct results
> regardless of the math library implementation or floating point precision
> of the host platform. This also allows GCC to generate identical results
> regardless of whether one compiles in native or cross-compile
> configurations to a particular target. The following built-in functions
> take advantage of this new capability: acos, acosh, asin, asinh, atan2,
> atan, atanh, cbrt, cos, cosh, drem, erf, erfc, exp10, exp2, exp, expm1,
> fdim, fma, fmax, fmin, gamma_r, hypot, j0, j1, jn, lgamma_r, log10, log1p,
> log2, log, pow10, pow, remainder, remquo, sin, sincos, sinh, tan, tanh,
> tgamma, y0, y1 and yn. The float and long double variants of these
> functions (e.g. sinf and sinl) are also handled. The sqrt and cabs
> functions with constant arguments were already optimized in prior GCC
> releases. Now they also use MPFR.

Autor: Christian (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
DANKE! auch von mir. Der Witz ist nämlich, auf Linux ubuntu 
2.6.38-11-generic geht mein Aufruf
$ gcc -D_REENTRANT  -Wall -lm -lpcan -lpthread -o s2algo 
tools/sens2algos.c
ohne Probleme. Dagegen haut's mir den auf
Linux ubuntu 3.5.0-36-generic #57~precise1-Ubuntu SMP
um die Ohren. Ich habe's nicht verstanden. Mit
$ gcc -D_REENTRANT  -Wall -pthread -o s2algo tools/sens2algos.c -lm 
-lpcan
wurde ich glücklich.
Und ich habe ernsthaft 1.5 Tage recherchiert!!

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.