Hello, I'm using a Philips LPC2138 (with Olimex Header board) for my actual project, a control panel for light shows (DMX 512, dimmers, scanners, moving-heads, strobes, sound-to-light and all these stuff). I've already a lot of experience with C, C++, 8051 and windows programming (dotNET). It's my first project using an ARM processor and WINARM from Martin Thomas, so please don't be cruel to me :-) I don't really want to use any librarys like Newlib, libc etc. since limited resources. (OK, 512K of flash seems to be a lot, but the control panel is also going to be a really huge thing...) So I wrote my own graphic lcd support, my own low-level filesystem for storing files and directorys into an external I2C-eeprom and a printf-function. Problem is that the linker is using printf from libc.a instead of my own function even though there is no include for this lib nor in any of my c-files neither in the makefile. Is it possible that this lib is somehow automatically included? A workaround to fix this would be to rename my own printf to myprintf or something, but I prefer printf... Thanks and best regards Daniel Jerolm (for eMails please remove the no-spam)
It is not an issue of header files, they are processed by the compiler. It is an issue of the linker resolving symbols and where it finds them. I believe that if it matches a symbol in an object file it overrides any math subsequently found in the library (because it will not even be looking), so it seems that you have not linked the object file containing your printf. Alternatively if you are using C++ you have a C/C++ linkage issue and it is not matching against your C++ compiled printf(). It is a good idea in these circumstances to post your build log (the text output of your make/build). If invoking the linker via the compiler you can specify -nostdlib or -nodefaultlibs (if using the linker directly you have to specify the libraries and startup files explicitly in any case) - if you choose to use these options, you must supply your own support for calls that the compiler may generate internally (see http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Link-Options.html#Link-Options for details). If you have the -lc option you are linking libc.a regardless of the options mentioned above. Outside of stdio, and the C++ standard library, most standard library functions are trivial and highly optimised - you'd do well to retain their services, and ripping out the library will cause problems for the compiler. Without the standard library you will loose runtime support for dynamic memory allocation (malloc, new etc.), and the memory manipulation routines that the compiler generates calls to internally for static initialisation for example. I would suggest that you only call your function printf() is it behaves exactly like printf() - i.e. uses format specifiers and is variadic - omitting support for floating point perhaps may be reasonable. The reason being that if your code is later maintained by someone else, they may attempt to use features your version does not support and waste time trying to debug it. So it is best to highlight the fact that it is not ISO compliant and is hardware specific by using an alternative name; lcd_printf() for example (myprintf is not really a good name!) In all I believe that an attempt to omit the standard library will cause mre problems than it is worth. Nonetheless what you have described should work, so if you still whant to make it work, post the build log so we can see what you are really doing (make it a log from a clean build). Clifford
Thanks for your answer. You are right, kicking out the libs completly will cause some problems, so I'll have to rename my function or make friends with newlib. Today I spend some time thinking about this and I came to the conclusion that it's the best to make friends with newlib. Nevertheless here is my build log. As you can see I've still the switches -lnewlib-lpc, -lm, -lc and -lgcc turned on. I tryed to remove them but it didn't change anythink, but applying -nodefaultlibs (as you mentioned in your answer) causes a lot of trouble. If I call my own printf something else like lcd_printf code works fine and I don't get the "undefined references ..."-errors shown below. If I don't get it working it's not a dramatic problem, then I'll provide the "undefined references" in my programm and the newlib printf should work. ------- begin -------- arm-elf-gcc (GCC) 4.1.1 (WinARM) Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Assembling (ARM-only): StartUp.S arm-elf-gcc -c -mcpu=arm7tdmi -I. -x assembler-with-cpp -DROM_RUN -Wa,-adhlns=StartUp.lst,-gdwarf-2 StartUp.S -o StartUp.o Compiling C (ARM-only): timing.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=timing.lst -MD -MP -MF .dep/timing.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 timing.c -o timing.o Compiling C (ARM-only): codeblinker.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=codeblinker.lst -MD -MP -MF .dep/codeblinker.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 codeblinker.c -o codeblinker.o Compiling C (ARM-only): printf.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=printf.lst -MD -MP -MF .dep/printf.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 printf.c -o printf.o Compiling C (ARM-only): VIC.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=VIC.lst -MD -MP -MF .dep/VIC.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 VIC.c -o VIC.o Compiling C (ARM-only): timer.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=timer.lst -MD -MP -MF .dep/timer.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 timer.c -o timer.o Compiling C (ARM-only): HID.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=HID.lst -MD -MP -MF .dep/HID.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 HID.c -o HID.o Compiling C (ARM-only): Display.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=Display.lst -MD -MP -MF .dep/Display.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 Display.c -o Display.o Compiling C (ARM-only): main.c arm-elf-gcc -c -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=main.lst -MD -MP -MF .dep/main.o.d -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -std=gnu99 main.c -o main.o main.c: In function 'main': main.c:198: warning: declaration of 'i' shadows a previous local main.c:49: warning: shadowed declaration is here Linking: main.elf arm-elf-gcc -mcpu=arm7tdmi -I. -gdwarf-2 -DROM_RUN -O0 -Wall -Wcast-align -Wcast-qual -Wimplicit -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=StartUp.lst -MD -MP -MF .dep/main.elf.d StartUp.o timing.o codeblinker.o printf.o VIC.o timer.o HID.o Display.o main.o --output main.elf -nostartfiles -Wl,-Map=main.map,--cref -lnewlib-lpc -lm -lc -lgcc -Tbuild/LPC2138-ROM.ld c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(fr eer.o): In function `_malloc_trim_r': mallocr.c:(.text+0x48): undefined reference to `_sbrk_r' mallocr.c:(.text+0x64): undefined reference to `_sbrk_r' mallocr.c:(.text+0x84): undefined reference to `_sbrk_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(ma kebuf.o): In function `__smakebuf': makebuf.c:(.text+0x3c): undefined reference to `_fstat_r' makebuf.c:(.text+0x110): undefined reference to `isatty' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(ma llocr.o): In function `_malloc_r': mallocr.c:(.text+0x424): undefined reference to `_sbrk_r' mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st dio.o): In function `__sclose': stdio.c:(.text+0xc): undefined reference to `_close_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st dio.o): In function `__sseek': stdio.c:(.text+0x30): undefined reference to `_lseek_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st dio.o): In function `__swrite': stdio.c:(.text+0x84): undefined reference to `_lseek_r' stdio.c:(.text+0xac): undefined reference to `_write_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(st dio.o): In function `__sread': stdio.c:(.text+0xd0): undefined reference to `_read_r' collect2: ld returned 1 exit status make.exe: *** [main.elf] Error 1 > Process Exit Code: 2 > Time Taken: 00:02 Daniel
I'm using iprintf from the newlib now. Problem solved, but payed with about 25KB flash memory...
Daniel Jerolm wrote: > If I don't get it working it's not a dramatic problem, then I'll provide > the "undefined references" in my programm and the newlib printf should > work. Yes you need to provide Newlib's syscalls. In most cases thay can simply be stubs - especially if you are not using stdio. The sbrk call should be implemented however, unless you are certain never to use dynamic memory allocation or anything that utilises the heap. Example implementations are provided with WinARM, although that is what I thought newlib-lpc provided (note that this library is not Newlib itself, Newlib is the collective name for libm and libc provided with WinARM). You can safely remove libm if you are not using the C math routines - and without a hardware FPU you may be advised not to for some applications. libgcc should be kept however, it contains compiler support routines. However if you never make the calls, the code will not of course be included in the build, so probably best to leave them. > I'm using iprintf from the newlib now. Problem solved, but payed with > about 25KB flash memory... Much of that code however is probably shared by other routines, so using sprintf() for example would have negligable additional overhead. Note that printf() also has a significant runtime stack requirement. Personally I'd do whatever is easiest right now and worry about the application size when it starts to become a problem, which it may never do so. Clifford
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.