NewLib is a replacement for the standard C library. You can use newlib, but the ‘simple’ solution is to make sure your project is linking to the standard C libraries (which should be included in your compile tools/environment),
The standard C library is usually called ‘libc.a’ for the C library, and ‘libgcc.a’ for the C++ library. Link to those (or newlib) during the linker step, and that should slove your problem. Or get newlib, and link to newlib.
By default many compilers will link to libg.a or libgcc.a (which is why you can compile HelloWorld.c without messing with linking). Often a a compiler options that causes this auto link-include to not happen, which means you have to expelicitly link it.
FarMcKon:
The standard C library is usually called ‘libc.a’ for the C library, and ‘libgcc.a’ for the C++ library. Link to those (or newlib) during the linker step, and that should slove your problem. Or get newlib, and link to newlib.
I detected that i already use a linker command like this:
The library libgcc.a is a low-level run time library to support software floating point. This is needed if you define any floats or doubles in your code (the LPC2000 and AT91SAM7 families do not have hardware floating point).
The Newlib libraries are libc.a and libm.a I believe that you can find them in the folder c:\Program Files\Yagarto\arm-elf\lib. I’m hoping that Michael Fischer is reading this and will correct me if I’m wrong.
The library libc.a has the string support etc. The library libm.a has the math support for sine, cosine, pow and the like. I like to simply “import” it into Eclipse and add it to the linker line, right after the specification of libgcc.a.
One warning, I haven’t been able to get the math library, libm.a, to work with Yagarto, it gives some unresolved references. I’m still looking into that.
The Newlib was designed for Linux hosts and some of the popular routines like printf will be difficult to get working. This is why lots of people look to alternatives like armlib and others.
By the way, MicroCross has all the GNU manuals in pdf format on their web site. The Newlib document can be downloaded from this address:
Read the man page for ld, it will tell you how to specify libraries. Basically:
Using #include<something.h> just includes the declarations for the functions (and datatypes and such) so that the compiler knows how to call them, but does not include the functions themselves.
Using -lfoo tells the linker to find a library named libfoo.a and include it. So if the routines you need are in libc.a, then -lc tells the linker to find that file. You can tell it which directories to search using -L — say, -L/stuff/armlibs. Or you can just specify the library directly on the command line, /stuff/armlibs/libc.a, and skip the whole searching business entirely.
By the way, a .a file is just an archive containing a bunch of .o files, plus an index showing which functions are defined in which file. When the compiler sees a .a file, it figures out which functions have been referenced but not defined yet, and pulls out the .o files that it needs and links them in.
It would be nice if newlib had some better online documentation. Currently it’s not exactly clear from the webpage what it does (or what it does not do) and exactly what low-level support is required.
I took a look on ARMlib and it seem’s that this is a quite usefull code. (many thanks to jim lynch for this hint)
But back to the newlib and YAGARTO:
I have now changed my makefile:
When i try to use sprintf i got the following messages:
arm-elf-ld -v -lc -lm -lnosys -Map main.map -Tdemo_at91sam7_blink_flash.cmd -o main.out crt.o main.o lcd.o lowlevelInit.o debug.o libgcc.a lib\libc.a lib\libm.a
lib\libc.a(vfprintf.o): In function `_vfprintf_r':
../../../../../newlib-1.14.0/newlib/libc/stdio/vfprintf.c:822: undefined reference to `__ltdf2'
../../../../../newlib-1.14.0/newlib/libc/stdio/vfprintf.c:1169: undefined reference to `__eqdf2'
../../../../../newlib-1.14.0/newlib/libc/stdio/vfprintf.c:1199: undefined reference to `__nedf2'
lib\libc.a(vfprintf.o): In function `cvt':
../../../../../newlib-1.14.0/newlib/libc/stdio/vfprintf.c:1325: undefined reference to `__eqdf2'
../../../../../newlib-1.14.0/newlib/libc/stdio/vfprintf.c:1321: undefined reference to `__nedf2'
lib\libc.a(dtoa.o): In function `_dtoa_r':
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:282: undefined reference to `__nedf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:349: undefined reference to `__subdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:349: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:349: undefined reference to `__adddf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:349: undefined reference to `__floatsidf'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:349: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:349: undefined reference to `__adddf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:350: undefined reference to `__fixdfsi'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:351: undefined reference to `__ltdf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:356: undefined reference to `__ltdf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:343: undefined reference to `__floatsidf'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:449: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:451: undefined reference to `__divdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:463: undefined reference to `__ltdf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:469: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:472: undefined reference to `__floatsidf'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:472: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:472: undefined reference to `__adddf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:472: undefined reference to `__floatsidf'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:472: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:472: undefined reference to `__adddf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:490: undefined reference to `__divdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:490: undefined reference to `__subdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:493: undefined reference to `__fixdfsi'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:494: undefined reference to `__floatsidf'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:494: undefined reference to `__subdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:496: undefined reference to `__gtdf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:498: undefined reference to `__subdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:498: undefined reference to `__gtdf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:498: undefined reference to `__subdf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:498: undefined reference to `__ltdf2'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:502: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:503: undefined reference to `__muldf3'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:493: undefined reference to `__fixdfsi'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:494: undefined reference to `__floatsidf'
../../../../../newlib-1.14.0/newlib/libc/stdlib/dtoa.c:494: undefined reference to `__subdf3'
--
--
--
and many more messages...
Does this mean that i have to implement all these functions that can not be resolved by the linker myself, or do i need further library’s?
I tried to change the order of libc and libgcc and now the result is:
make -k all
...linking
arm-elf-ld -v -lc -lm -lnosys -Map main.map -Tdemo_at91sam7_blink_flash.cmd -o main.out crt.o main.o lcd.o lowlevelInit.o debug.o lib\libc.a lib\libm.a libgcc.a
GNU ld version 2.17
lib\libc.a(syscalls.o): In function `_sbrk':
../../../../../../newlib-1.14.0/newlib/libc/sys/arm/syscalls.c:500: undefined reference to `end'
make: *** [main.out] Error 1
make: Target `all' not remade because of errors.
I’m no expert in this, but as far as I know sbrk is a low-level function to claim memory and is used by malloc. To be able to do this, you need to have some memory space that acts as the C “heap”. I can imagine that ‘end’ indicates the end of the heap.
The end in this case is a symbol that points to the first free word in RAM after all global variables has been placed there. Some codelibraries use the symbol _end and some use the symbol end (without the underscore). It is usually defined in the linker script, in you case
demo_at91sam7_blink_flash.cmd
At the end, after the the definition of the symbol _end, add the line PROVIDE(end = .);
This means: let the symbol ‘end’ point to the current position unless it has been given a differnt value somewhere else.
[Jim] Perhaps this should standard in the linker scripts.
things like malloc and sprintf are working fine, But how can i redefine the puts or putchar function from the newlib so that it uses my own functions for this job and all my printf stuff is printed directly via the ARM’s debug port?
There is a debug unit uart on the ATSAM7S that can be used, any other UART is also OK.
Most file writing in newlib goes through the _write function. As far as I know, also puts and putchar uses this for the actual output. A very simple implementation, taken from the newlib sources is:
int _write(int file, char *ptr, int len){
int todo;
for (todo = 0; todo < len; todo++) {
writechar(*ptr++); /* PUT YOUR OWN CODE TO SEND ONE CHAR HERE */
}
return len;
}
This code will replace the _write function in libnosys and send the output to your chosen dstination. But I have not tested this specific code.