Forum: Mikrocontroller und Digitale Elektronik Probleme mit newlib / arm-none-eabi-gcc


von Obs (Gast)


Lesenswert?

Hallo Community,

die Frage hier baut auf meiner anderen Frage in diesem Thread auf 
(Beitrag "Re: Probleme beim Linken mit arm-none-eabi-gcc (yagarto)"), ist aber jetzt 
etwas spezifischer geworden, weswegen ich sie noch mal neu formuliere. 
Das erwähnte Problem habe ich nun zwar einfach umgangen, aber ich weiß 
nicht wieso es überhaupt da ist. Um  es noch mal kurz zu beschreiben: 
Ich versuche Code für einen Cortex-M3 zu kompilieren und verwende dazu 
die yagarto-Toolchain und die newlibc. Nachdem ich einige Änderungen an 
meinem Code vorgenommen hatte, wollte ich wieder kompilieren und bekam 
dann diese Linker-Fehler:
1
arm-none-eabi-gcc -T ../../cpu/arm//atsam3s4/atsam3s4-flash.ld -L../../cpu/arm//atsam3s4 -march=armv7-m -mcpu=cortex-m3 -mthumb -Wl,-Map=mapfile -nostartfiles   hello-world.co obj_deRFusb-13E00/contiki-main.o contiki-deRFusb-13E00.a  -o hello-world.deRFusb-13E00
2
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-impure.o):(.data+0x0): multiple definition of `_impure_ptr'
3
contiki-deRFusb-13E00.a(stdio.o):(.data+0x428): first defined here
4
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
5
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/sbrkr.c:58: undefined reference to `_sbrk'
6
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-writer.o): In function `_write_r':
7
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/writer.c:58: undefined reference to `_write'
8
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-closer.o): In function `_close_r':
9
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/closer.c:53: undefined reference to `_close'
10
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-fstatr.o): In function `_fstat_r':
11
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/fstatr.c:62: undefined reference to `_fstat'
12
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-isattyr.o): In function `_isatty_r':
13
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/isattyr.c:58: undefined reference to `_isatty'
14
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-lseekr.o): In function `_lseek_r':
15
rm hello-world.co
16
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/lseekr.c:58: undefined reference to `_lseek'
17
c:/yagarto-20121222/bin/../lib/gcc/arm-none-eabi/4.7.2/../../../../arm-none-eabi/lib/thumb/v7m\libc.a(lib_a-readr.o): In function `_read_r':
18
C:\msys\1.0\home\yagarto\newlib-build\arm-none-eabi\thumb\v7m\newlib\libc\reent/../../../../../../../newlib-1.20.0/newlib/libc/reent/readr.c:58: undefined reference to `_read'
19
collect2.exe: error: ld returned 1 exit status
20
make: *** [hello-world.deRFusb-13E00] Error 1
Nach Stunden der Problemsuche hab ich dann einfach eine ältere 
kompilierbare Version wieder hergestellt und nach und nach die 
Neuerungen eingebaut, bis ich den Grund für die Fehler gefunden hatte 
und letztendlich lag es an einem Aufruf von putchar, was ich an manchen 
Stellen als ein schnelles printf zu Debuggingzwecken verwende. Mit 
printf hat der Compiler respeketive Linker übrigens kein Problem. 
Nachdem ich das putchar auskommentiert habe, hat er wieder kompiliert 
und ich verstehe nicht warum. Als eine ‚Besonderheit’ muss ich wohl noch 
hinzufügen, dass ich verschiedene Quelldateien mit in meinem Projekt 
habe, die C-Standardfunktionen ‚überschreiben’, unter anderem printf, 
fputc, putchar und so weiter. Ich schätze, dass das vielleicht nicht 
ganz sauber ist, aber zum einen habe ich das Projekt auch nur so 
übernommen. Und zum anderen sind die Quelldateien laut der Kommentare 
auch direkt von Atmel und erzeugen auch wesentlich schlankeren Code als 
die newlib mit dem ganzen Reent-Zeug und brauchen auch kein malloc. 
Insgesamt macht das für mich einen Unterschied von knapp 24kB, weswegen 
ich auch sicher nicht auf die newlib-Implementierung umsteigen werde. 
Wie dem auch sei. Das Komische ist eben, dass putchar in derselben Datei 
implementiert ist wie fputc, nämlich uart_console.c. Aber fputc kann ich 
ohne Probleme verwenden. Und die Implementierung von putchar macht auch 
nichts anderes als fputc mit stdio als Argument aufzurufen:
1
signed int putchar(signed int c)
2
{
3
    return fputc(c, stdout);
4
}
Die printf-Funktion ist in einer anderen Datei implementiert, nämlich in 
stdio.c, ruft aber irgendwann über vprintf, vfprintf und fputs auch 
wieder fputc auf. Ein Aufruf von printf im Code kompiliert problemlos 
und tut zur Laufzeit auch genau das, was sie soll. fputc ruft dann 
übrigens Funktionen auf, die auf die serielle Schnittstelle schreiben, 
ebenfalls in uart_console.c implementiert.
Jetzt verstehe ich nicht, wieso es mit printf und fputc kompiliert und 
mit putchar nicht, obwohl putchar in derselben Datei wie fputc 
implementiert ist und auch nichts weiter tut als fputc aufzurufen. Ein 
Auszug aus dem mapfile zeigt auch, dass auf jeden Fall die richtige 
putchar-Implementierung genommen wird:
1
.text          0x0040a65c      0x3a8 contiki-deRFusb-13E00.a(uart_console.o)
2
                0x0040a694                UART_Configure
3
                0x0040a730                UART_PutChar
4
                0x0040a780                UART_GetChar
5
                0x0040a7cc                UART_IsRxReady
6
                0x0040a818                UART_SetInputHandler
7
                0x0040a854                UART0_IrqHandler
8
                0x0040a888                fputc
9
                0x0040a8e0                fputs
10
                0x0040a930                putchar
11
                0x0040a958                fgetc
12
                0x0040a98c                getchar
Was hat die newlib bzw. der Linker da für ein Problem mit putchar?!
Der Linker beschwert sich ja, dass z.B. in der newlib-Funktion _sbrk_r 
_sbrk verwendet wird, was aber nicht referenziert werden kann. Nehme ich 
putchar raus, wird auch _sbrk_r nicht mehr benötigt und daher kommt der 
Fehler auch nicht. Gleiches gilt für _write_r, _close_r und so weiter. 
Aber in der Implementierung von putchar passiert ja auch nichts weiter, 
weswegen ich nicht verstehe, wieso dann auf einmal die ganzen 
newlib-Funktionen gebraucht werden. Gibt es auch eine Möglichkeit zu 
sehen, wieso er jetzt auf einmal die newlib-Funktionen braucht? Die 
müssen ja irgendwo aufgerufen werden jetzt. Also quasi so eine Art „Open 
Call Hierachry“, nur eben auf Object-Code-Ebene.

Vielen Dank für eure Hilfe.

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.