I want create a project for the STM32F217IG microcontroller.
So I installed Eclipse and the GNU for ARM embedded GCC cross compiler. I don't think it is the Code Sourcery one. I used it, because it supports floating point and Code Sourcery does not.
Once I did that I tried creating a really small project with only two sources files: test.c and main.c with only the following Code written in both of them:
#include <stdlib.h> #include <stdio.h> int main (void) { printf("Hello, World!"); return 0; }
I changed the line command in the project property to replace GCC with arm-none-eabi-gcc and then tried to compile the project.
I did not create any makefile myself; I used the automatic creation in Eclipse.
The building seems to be fine, but when it comes to the linker I got the following errors in the console:
make all 'Building target: test3' 'Invoking: Cross GCC Linker' arm-none-eabi-gcc -o"test3" ./main.o ./test3.o c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit': exit.c:(.text.exit+0x2c): undefined reference to `_exit' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-sbrkr.o): In function `_sbrk_r': sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-writer.o): In function `_write_r': writer.c:(.text._write_r+0x20): undefined reference to `_write' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-closer.o): In function `_close_r': closer.c:(.text._close_r+0x18): undefined reference to `_close' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-fstatr.o): In function `_fstat_r': fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-isattyr.o): In function `_isatty_r': isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-lseekr.o): In function `_lseek_r': lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-readr.o): In function `_read_r': readr.c:(.text._read_r+0x20): undefined reference to `_read' collect2: ld returned 1 exit status make: *** [test3] Erreur 1
I looked on the Internet, and I found that it may be a syscall problem. But I don't know how I add this library to my project on Linux.
Is that really the problem? If yes, how do I fix it? And if not, where is the error coming from?
As someone suggested, I tried "linking" the C runtime library. In Eclipse it seems I have two solutions to do it:
First on the project properties → C/C++ → Build → Settings → Cross linker → libraries. I just add the letter c
and then the error does not change, but there is -lc
at the end of the command line:
make all 'Building target: test3' 'Invoking: Cross GCC Linker' arm-none-eabi-gcc -o"test3" ./main.o ./test3.o -lc c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit': exit.c:(.text.exit+0x2c): undefined reference to `_exit' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-sbrkr.o): In function `_sbrk_r': sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-writer.o): In function `_write_r': writer.c:(.text._write_r+0x20): undefined reference to `_write' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-closer.o): In function `_close_r': closer.c:(.text._close_r+0x18): undefined reference to `_close' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-fstatr.o): In function `_fstat_r': fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-isattyr.o): In function `_isatty_r': isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-lseekr.o): In function `_lseek_r': lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek' c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-readr.o): In function `_read_r': readr.c:(.text._read_r+0x20): undefined reference to `_read' collect2: ld returned 1 exit status make: *** [test3] Erreur 1
But I don't know if it is really means to add the C runtime library.
Second, I added the libc.a library in the project properties → C/C++ general → Path and symbols → Libraries, and here is what I get (completely different):
make all 'Building target: test3' 'Invoking: Cross GCC Linker' arm-none-eabi-gcc -o"test3" ./main.o ./test3.o -l"C:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a" c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/bin/ld.exe: cannot find -lC:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a collect2: ld returned 1 exit status make: *** [test3] Erreur 1
Then it still does not work, but is it the good way to search on?
Oh and a very interesting fact:
I got the errors only in debug mode. If I am in release mode everything is okay, and I don't have any errors (except if I add the libc.a then I think this is not the best thing to do). Does that mean the problem is the .elf file creation?
You can fix the errors by including the source code file that contains the definitions as part of the compilation. Alternatively, you can pass . obj files or . lib files that contain the definitions to the linker.
Linker errors occur when the linker is trying to put all the pieces of a program together to create an executable, and one or more pieces are missing. Typically, this can happen when an object file or libraries can't be found by the linker.
Even if you make it through the compilation process successfully, you may run into linker errors. Linker errors, unlike compiler errors, have nothing to do with incorrect syntax.
Linker Errors: These error occurs when after compilation we link the different object files with main's object using Ctrl+F9 key(RUN). These are errors generated when the executable of the program cannot be generated. This may be due to wrong function prototyping, incorrect header files.
I've looked at the toolkit you linked, just to read the following in the readme.txt
:
This toolchain is built and optimized for Cortex-R/M bare metal development.
In other words, this toolchain is specifically configured for embedded systems, perhaps with no operating system running at all. In such case, there's no system to provide e.g. standard output where printf()
is supposed to write, there's no file system, etc. - you have to link against some library providing these basic services, if you want to use them.
That said, your toolkit provides librdimon.a
library which provides all those basic services. This library is actually a part of libgloss compilation. If you want to link against it, try the following command:
arm-none-eabi-gcc --specs=rdimon.specs -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group -o test test.c
This links fine on my PC, but whether it's what you really want is another story (where do you expect to see printf()
output, anyway?).
For you chip you should probably look for a library which redirects the standard output to serial port or provides debug output over JTAG. Alternatively, you can use your custom function e.g. sending debug output to serial console instead of printf()
- it's up to you. If you decide on using printf()
I suggest reading libgloss
documentation.
Also, I suggest looking around for a toolchain which is specifically bundled for STM32 family. Properly configuring all this basic stuff (C library, linker script, etc.) requires a bit of experience.
Edit: Many embedded systems doesn't really use standard C library, starting pretty much from scratch. If you want to go this way, you should pass -nostdlib
to your gcc
invocation. Of course, you'll no longer have things like printf()
available.
Edit 2: Another way is to use standard library (newlib
, I mean) without libgloss
and provide appropriate stubs for things you do not need. You might want to follow this tutorial, where _read
and _write
is implemented over the serial port, and everything else is stubbed. This is most likely what you really want.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With