How to use newlib?

Hello everybody!

I’m very new to the ARM controllers. I’m currently working with an ATSAM7X256 and the YAGARTO Toolchain.

The toolchain works fine but i’m missing functions like sprintf and malloc ?

I read that they are avialable at the newlib library. How do i include this library into my code?

Do i need special linker or complier flags when my code uses sprintf or malloc functions?

Currently i got the folliwing error:

undefined reference to `malloc'

Tanks a lot

Greetings

Rain

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.

That function malloc and sprintf, sometime need to #include <stdlib.h> and <string.h> depending on Compiler. Please check.

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:

arm-elf-ld -v -lc ....... libgcc.a

Is malloc and sprintf not part of the libgcc?

It seems that yagarto already has the newlib:

http://www.yagarto.de/index.html#download

Which linker flag must i set so that i can use the newlib?

I tried to include

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

but the result is the same → undefined reference to `malloc’

Tanks a lot

Greetings

Rain

libc is where the standard c lib functions can be found.

Life is much easier if you use gcc as the driver for ld, eg.

arm-elf-gcc file1.o file2.o -o target.elf

This will setup the correct paths for the c libs for you.

Regards

Spen

ntfreak:
libc is where the standard c lib functions can be found.

Life is much easier if you use gcc as the driver for ld, eg.

arm-elf-gcc file1.o file2.o -o target.elf

This will setup the correct paths for the c libs for you.

Regards

Spen

sorry but i don’t understand what you mean.

Can anybody tell me how to use newlib with Yagarto in a very simple way?

I’m using the makefile from Jim Lynch’s tutorial.

Thank’s a lot

Rain

Here is the complete output of the build process:

make -k all
...compiling main.c
arm-elf-gcc -I./ -c -fno-common -O0 -g main.c
...linking
arm-elf-ld -v -lc  -Map main.map -Tdemo_at91sam7_blink_flash.cmd -o 
main.out crt.o  main.o lcd.o lowlevelInit.o debug.o libgcc.a
GNU ld version 2.17
main.o: In function `main':
I:\SOFTWARE\ARM_Projects\demo_at91sam7_blink_flash/main.c:49: 
undefined reference to `printf'
make: *** [main.out] Error 1
make: Target `all' not remade because of errors.

This is the Makefile that i’m currently using:

# ***************************************************************
# *     Makefile for Atmel AT91SAM7S256 - flash execution       *
# *                                                             *
# *                                                             *
# * James P Lynch  September 3, 2006                            *
# ***************************************************************

NAME   = demo_at91sam7_blink_flash

# variables
CC      = arm-elf-gcc
LD      = arm-elf-ld -v -lc
AR      = arm-elf-ar
AS      = arm-elf-as
CP      = arm-elf-objcopy
OD    = arm-elf-objdump

CFLAGS  = -I./ -c -fno-common -O0 -g
AFLAGS  = -ahls -mapcs-32 -o crt.o
LFLAGS  =  -Map main.map -Tdemo_at91sam7_blink_flash.cmd
CPFLAGS = --output-target=binary
ODFLAGS  = -x --syms

OBJECTS = crt.o  main.o lcd.o lowlevelInit.o debug.o


# make target called by Eclipse (Project -> Clean ...)
clean:
  -rm $(OBJECTS) crt.lst main.lst main.out main.bin main.hex main.map 
main.dmp


#make target called by Eclipse  (Project -> Build Project)
all:  main.out
  @ echo "...copying"
  $(CP) $(CPFLAGS) main.out main.bin
  $(OD) $(ODFLAGS) main.out > main.dmp

main.out: $(OBJECTS) demo_at91sam7_blink_flash.cmd
  @ echo "...linking"
  $(LD) $(LFLAGS) -o main.out $(OBJECTS) libgcc.a

crt.o: crt.s
  @ echo "...assembling crt.s"
  $(AS) $(AFLAGS) crt.s > crt.lst

main.o: main.c  include\AT91SAM7X256.h include\board_ex256.h 
include\registers.h include\lcd.h
  @ echo "...compiling main.c"
  $(CC) $(CFLAGS) main.c

lcd.o: lcd.c  include\AT91SAM7X256.h include\ext_registers.h 
include\lcd.h include\bits.h
  @ echo "...compiling lcd.c"
  $(CC) $(CFLAGS) lcd.c

lowlevelInit.o: lowlevelInit.c include\AT91SAM7X256.h 
include\board_ex256.h
  @ echo "...compiling lowlevelInit.c"
  $(CC) $(CFLAGS) lowlevelInit.c

debug.o: debug.c include\AT91SAM7X256.h include\board_ex256.h 
include\lib_AT91SAM7XC256.h
  @ echo "...compiling debug.c"
  $(CC) $(CFLAGS) debug.c

and yes i inculded:

#include <stdio.h>
#include <stdlib.h>

to my main.c file

I got these error message when i’m using functions like printf, malloc,

sprintf…

Is the libgcc file the newlib library? If not please tell me where I can

find it in the yagarto filestructure.

Thank’s a lot

Greetings,

Hi Rain.

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:

http://www.microcross.com/

Cheers,

Jim Lynch

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.

THANK YOU FOR YOUR REPLIES:

I think that i have now a clearer look on the newlib stuff. Thank you guys.

Is there any free library available for the ATSAM7X which includes the standard function that makes C programming much easier i think of:

printf

sprintf

memcpy

malloc

It seems that newlib is not the correct library for this.

Thank’s a lot

Rain

Try to link with with libnosys.a that can be found with libc.a , use -lnosys .

That helped me to get malloc loaded, but beware that it uses 1k of RAM for internal datastructus before allocating any memory.

Regards

Magnus

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?

Thanks for your patience,

rain

put libgcc last, after libc .

hello mlu,

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.

once again thanks for your patience

rain

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 is close.

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.

	    _end = .;
	    PROVIDE(end = .);

So actually end is the beginning of the heap.

Regards,

Magnus

Many Thanks - now i got newlib working!

I have one last question:

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?

Once again, thanks a lot

rain

Hello rain,

I think you can write your own puts and putchar

function. This will override the function from the

library. Have you try this?

What do you mean with “printed directly via the ARM’s debug port”?

Do you want to use the DCC of the ARM?

I think in this case you must have a debugger which support this

feature.

Regards,

Michael

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.

Magnus