Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

WinARM i funkcja sprintf??

august_a 03 Sep 2007 19:03 4357 12
Computer Controls
  • #1
    august_a
    Level 21  
    Witam,
    Mam problem z użyciem pod WinArm funkcji sprintf.
    Gdy ją wywołam, to kompilator wywala błąd:
    Linking: main.elf
    arm-elf-gcc -mthumb -mcpu=arm7tdmi -mthumb-interwork -I. -gdwarf-2 -DROM_RUN -D__WinARM__  -Os -Wall -Wcast-align -Wimplicit  -Wpointer-arith -Wswitch -Wredundant-decls -Wreturn-type -Wshadow -Wunused -Wa,-adhlns=Cstartup.lst   -MD -MP -MF .dep/main.elf.d Cstartup.o  Cstartup_SAM7.o main.o  t6963c.o adc.o Board.o     --output main.elf -nostartfiles -Wl,-Map=main.map,--cref -lc  -lm -lc -lgcc     -TAT91SAM7S64-ROM.ld
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(freer.o): In function `_malloc_trim_r':
    mallocr.c:(.text+0x2c): undefined reference to `_sbrk_r'
    mallocr.c:(.text+0x3c): undefined reference to `_sbrk_r'
    mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(makebuf.o): In function `__smakebuf':
    makebuf.c:(.text+0x1c): undefined reference to `_fstat_r'
    makebuf.c:(.text+0xb2): undefined reference to `isatty'
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(mallocr.o): In function `_malloc_r':
    mallocr.c:(.text+0x2e8): undefined reference to `_sbrk_r'
    mallocr.c:(.text+0x388): undefined reference to `_sbrk_r'
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(stdio.o): In function `__sclose':
    stdio.c:(.text+0xc): undefined reference to `_close_r'
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(stdio.o): In function `__sseek':
    stdio.c:(.text+0x2a): undefined reference to `_lseek_r'
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(stdio.o): In function `__swrite':
    stdio.c:(.text+0x6e): undefined reference to `_lseek_r'
    stdio.c:(.text+0x86): undefined reference to `_write_r'
    c:/WinARM/arm-elf/lib/thumb/interwork\libc.a(stdio.o): In function `__sread':
    stdio.c:(.text+0xaa): undefined reference to `_read_r'
    make.exe: *** [main.elf] Error 1
    


    Co może być?? Spotkał już ktoś sę z takim błędem??
    Pzdr.
    A.
  • Computer Controls
  • #2
    aster11
    Level 19  
    Linker nie może się czegoś doszukać, pewnie brak jakiegoś pliku bibliotecznego.
    Mogę powiedzieć Ci tylko tyle, że u mnie sprintf kompiluje się bez problemu na WinARM, specjalnie sprawdziłem.

    Jeżeli chcesz, możesz przesłać mi program, spróbuję skompilować go u siebie.
  • #3
    adamusx
    Level 27  
    Wydaje mi sie ze musisz dolaczyc plik syscalls.c
  • Computer Controls
  • #5
    aster11
    Level 19  
    markosik20 wrote:
    Funkcja sprintf znajduje się przeważnie w bibliotece......

    Kod:
    #include <stdio.h>

    Oczywiście jest dołączona?


    Zgadza się, funkcja sprintf jest zdefiniowana w pliku nagłówkowym stdio.h. Jednak błędy linkowania, które zostały zacytowane, nie mogą wynikać z braku inkludowania tego pliku - w takim wypadku wystąpiłby błąd na etapie kompilacji.
    Błędy linkera "undefined reference to" wiążą się z brakiem obecności binarnej (obiektowej) reprezentacji funkcji w zbiorach bibliotecznych, a nie z brakiem ich deklaracji, np.w plikach nagłówkowych.
    Poza tym z wypisu linkera wynika, że problem jest nie ze znalezieniem implementacji funkcji sprintf, ale jakichś innych funkcji, zapewne wywoływanych przez nią pośrednio.

    Najbardziej podejrzewam, że problem wynika z jakiegoś niedopracowania w zbiorze parametrów kompilacji, określonych w Makefile.
    Na drugim miejscu przypuszczam, że może coś rozsypało się w instalacji WinARM.
    Tak czy owak, proponuję Zainteresowanemu próbę kompilacji u siebie. Widzę, że albo nie jest zainteresowany, albo już problem rozwiązał, albo czasowo zawiesił próby :)
  • #6
    markosik20
    Level 33  
    Quote:
    jakiegoś niedopracowania w zbiorze parametrów kompilacji, określonych w Makefile


    I dlatego zabawę z ARM'ami zacząłem od Keila for ARM :wink:.
    GCC narazie dla mnie jest zbyt "zawiły".
  • Helpful post
    #7
    adamusx
    Level 27  
    Spróbuj dołączyc do projektu (do makefile) plik z załącznika.
    Poza tym warto zamiast sprintf uzywac iprintf , ta funkcja jest mniej pamieciozerna.
  • #8
    august_a
    Level 21  
    Dzieki bardzo za pomoc. Dodałem syscalls.c i kompilacja przebiegła prawidłowo, ale program pzed dodaniem syscalls.c zajmował 3123 bajty a po dodaniu zajmuje 31234 bajtów :|
  • #9
    kamilnt
    Level 11  
    proponuje wykroić tylko ciało funkcji sprintf z pliku syscalls.c (+ niezbędne funkcje dodatkowe - o ile takie tam są), napewno rozmiar generowanego pliku zmaleje

    pozdro
  • #10
    aster11
    Level 19  
    Niestety, jeżeli używasz formatów %... w łańcuchu formatującym funkcji sprintf, dorzucane jest ok. 30kB kodu wynikowego. Sprawdziłem to też u siebie. Może spróbuj zastosować iprintf, o której pisze adamusx. Widać, że ten Człowiek zna się na rzeczy. Wiedział, w jakim pliku szukać funkcji, których Tobie brakowało. U mnie sprintf idzie bez jawnego dołączania syscalls.c, widocznie odpowiednie zbiory binarne znajdują sie już w przeszukiwanych przez linker bibliotekach. Ciekawe od czego to zależy: od opcji linkowania, organizacji bibliotek, wersji WinAVR ... ?

    kamiInt wrote:
    proponuje wykroić tylko ciało funkcji sprintf z pliku syscalls.c

    Patrzyłeś na błędy linkowania zacytowane przez august_a lub/i na zawartość pliku syscalls.c? Nikt tutaj nie poszukuje ciała funkcji sprintf.
  • #11
    adamusx
    Level 27  
    W pliku syscalls.c nie ma ciała funkcji sprintf, znajduja sie tam funkcje potrzebne do działania sprintf.
    Aster11 jakiego kompilatora uzywasz? Z tego co wiem w bibliotece w WinARMie jest jakas niezgodnosc i by funkcie printf działały należy własnie dołaczać ten plik syscall.s. Wówczas chyba kompilator nie linkuje tych funkcji z biblkoteki tylko z dołączonego pliku syscalls.c
    Zresztą na początku pliku jest napisane:

    /*  These are "reentrant functions" as needed by                       */
    /*  the WinARM-newlib-config, see newlib-manual.                       */
    /*  Collected and modified by Martin Thomas                            */
    /*                                                                     */
    /***********************************************************************/
    
    /* adapted for the SAM7 at91_lib DBGU - mthomas 4/2006 */ 


    A wiedziałem jaki plik bo sam miałem kiedyś z tym problem :)
  • #12
    aster11
    Level 19  
    Eeeee, Pochwaliłem się niepotrzebnie :D Funkcję sprintf sprawdziłem tylko dla czystego tekstu. Gdy dodaję elementy formatowania %..., brakuje odniesień, tak jak u august_a.
    Wszystko jest więc tak, jak Ty mówisz.

    Będę wiedział na przyszłość. Dobrze jest czasami czegoś nauczyć się na (nie swoich) błędach :D

    Pozdrawiam.


    PS:

    Dokładniej mówiąc to jest tak:
    Pod WinARM (arm-elf-gcc 4.1.1) występuje ten problem, o którym rozmawialiśmy. Pod linuksem (GNU-ARM: arm-elf-gcc 4.2.1) nie mam problemów z budowaniem kodu wykonywalnego - nie potrzeba jawnie "dokompilowywać" syscalls.c, linker radzi sobie bez tego. Oczywiście bez złudnej nadziei - użycie sprintf z %... tak samo dokłada ok. 30kB :D
  • #13
    upanie
    Level 22  
    Z grubsza sprawa wygląda tak, że sprintf jest chyba jedną z najbardziej kobylastych funkcji bibliotecznych - polecam lekturę kodu źródłowego - i stąd tyle kodu wynikowego.
    Do prawidłowego działania wymaga ona między innymi malloca. Ten z kolei, jako że jest standardową funkcją biblioteczną, nie ma zielonego pojęcia ile jest wolnej pamięci i gdzie się ona zaczyna. Zatem malloc wykorzystuje funkcję _sbrk. _sbrk jest funkcją super uzależnioną od sprzętu i dlatego musi zostać zaimplementowana przez programistę a nie może być zaciągana z jakiegoś standardowego zestawu z pakietu kompilatora. Funkcja ta również ma swoje powiązanie ze skryptem linkera. Funkcja _sbrk wchodzi w skład pliku syscalls.c Każdy powinien sobie zaimplementować wszystkie funkcje wchodzące w jego skład bo jak sama nazwa wskazuje jest plik odwołań do systemu i w związku z tym u każdego może być inaczej. Tych funkcji nie jest dużo, są np. "_write", "_sbrk", "_open", "_close" i t.p.
    Wujek google wskaże wam drogę do przykładowego pliku.
    I jeszcze jedna uwaga: plik syscalls najczęściej nie jest wymagany bo istnieje w bibliotece jakaś tam jego implementacja ale gdy dodacie do źródeł swój plik to linker automatycznie zaciągnie waszą wersję olewając tę biblioteczną.
    Jeszcze jedno: gdy funkcja ma na końcu sufix "_r" to oznacza, że jest to tzw wersja reentrant co z kolei oznacz, że może być stosowana w programach wielowątkowych. Funkcje bez tych końcówek nie powinny być używane w aplikacjach wielowątkowych. No i odwrotnie, aplikacje jednowątkowe nie powinny korzystać z funkcji typu reentrant ze względu na ich dłuższy kod i troszkę wolniejsze działanie.
    Owocnej zabawy.