30

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++BuildSettingsCross linkerlibraries. 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++ generalPath and symbolsLibraries, 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?

Scott Madeux
  • 329
  • 3
  • 8
damien
  • 415
  • 1
  • 6
  • 13
  • Format the sources into something readable, please! Provide the linker command line, more details about your toolchain (I can only guess it's Code Sourcery/Mentor toolchain), etc. – Code Painters Nov 05 '12 at 16:03
  • I edited my question I am really new about all of that so I don't really know the information you need to answer the question, if you need more tell me I will edit again – damien Nov 05 '12 at 16:15
  • If quoting a file's name the spaces do not need to be escaped: So it should be either `... -l"C:/Program Files/GNU Tools ARM Embedded/4.6 2012q4/arm-none-eabi/lib/armv7-m/libc.a"` or `... -lC:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a` – alk Nov 05 '12 at 16:53
  • Ok but I don't know how to change it and anyway when we read the error it is: `ld.exe: cannot find -lC:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a` which is your second suggestion then I think the command line has a good syntax even if it does not work no? – damien Nov 05 '12 at 17:01
  • Depending on your code, you might want to stub out those functions... Here they are: extern "C" { void _exit( int status ) { while (1); } unsigned int _getpid() { return 0; } int _kill( int id, int sig ) { return 0; } void _sbrk( int id) {} int _fstat (int fd, void* buf) { return 0; } int _write( int fd, char *buf, int count ) { return 0; } int _read( int fd, char *buf, int count ) { return 0; } int _lseek( int fd, int count ) { return 0; } int _close( int fd ) { return 0; } int _isatty( int fd ) { return 0; } } – Luke Dupin Aug 28 '15 at 20:43

5 Answers5

34

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.

Code Painters
  • 7,175
  • 2
  • 31
  • 47
  • Thank you for your answer even if I don't get where I should do this command in eclipse. By chance would anyone know if there is a toolchain specifically bundled for STM32 family? – damien Nov 07 '12 at 08:43
  • To answer your question I did not expect to see printf() anywhere. I am just trying to do a simple project and compile and link it to be sure that this toolchain will be usable later for my project. By the way if it is a library problem why do I get the error only in debug mode and not in release mode? – damien Nov 07 '12 at 08:57
  • Since you though about printf I just comment all both the printf in my project and here is what happen: I still have error even if it is just one: `'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' collect2: ld returned 1 exit status make: *** [test3] Erreur 1` Which is exactly the same error as the first one I got before – damien Nov 07 '12 at 09:12
  • Well, not exactly, I'd say - does it still complain about e.g. `_write()`? Anyway, `_exit()` is also a part of `libgloss` referenced from `newlib`, you need to either provide some implementation, or give up with standard library. Let me update my answer. – Code Painters Nov 07 '12 at 09:26
  • Actually I managed to add the rdimon library and it links fine. Thank you very much. I just now need to be able to generate a elf file which is not the case currently and i do not know why – damien Nov 07 '12 at 09:34
  • See my last update, I believe it's the best starting point for you. – Code Painters Nov 07 '12 at 10:02
11

I know this is an old question, but I ran into this today when trying to build for an STM32 board. The project I have has some linker scripts (specifically libs.ld). Adding an entry for libnosys.a in this satisfied the linker and I was able to continue.

libs.ld:

 GROUP(
   libgcc.a
   libg.a
   libc.a
   libm.a
   libnosys.a
 )
Shane
  • 1,255
  • 14
  • 14
  • It's important to understand that `nosys` stubs pretty much everything - thus `HelloWorld` above will compile and link, but will do nothing, as file I/O is stubbed as well. – Code Painters Aug 16 '16 at 12:38
6

Saving your C program as "myprint.c", I compile it as follows:

arm-none-eabi-gcc myprint.c -lc -specs=nosys.specs

No errors and output is fine.

Peter Teoh
  • 6,337
  • 4
  • 42
  • 58
3

There also was such a problem with malloc() and free() function calls in the Eclipse project. I have written firmware for an STM32 microcontroller using Eclipse + GNU for ARM embedded GCC cross compiler + STM32CubeMX for microcontroller periphery initialization and linker script making.

When I have added missing strings libg.a ( * ) and libnosys.a ( * ) in the DISCARD section of .ld script, my project was build successfully.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

I had created an RTOS project using CubeMX and added a printf and had the same issue on linking, while debugging using OpenOCD.

I replaced the printf("Hello ARM World!") with trace_puts("Hello ARM World!"); and had the messages appear in the debug console.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131