Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

WinARM i funkcja sprintf??

august_a 03 Wrz 2007 19:03 4084 12
  • #1 03 Wrz 2007 19:03
    august_a
    Poziom 21  

    Witam,
    Mam problem z użyciem pod WinArm funkcji sprintf.
    Gdy ją wywołam, to kompilator wywala błąd:

    Code:
    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.

  • #2 03 Wrz 2007 19:34
    aster11
    Poziom 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 03 Wrz 2007 20:44
    adamusx
    Poziom 27  

    Wydaje mi sie ze musisz dolaczyc plik syscalls.c

  • #4 03 Wrz 2007 21:14
    markosik20
    Poziom 33  

    Funkcja sprintf znajduje się przeważnie w bibliotece......

    Code:
    #include <stdio.h>


    Oczywiście jest dołączona?

  • #5 03 Wrz 2007 21:56
    aster11
    Poziom 19  

    markosik20 napisał:
    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 03 Wrz 2007 22:01
    markosik20
    Poziom 33  

    Cytat:
    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".

  • Pomocny post
    #7 04 Wrz 2007 01:15
    adamusx
    Poziom 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 04 Wrz 2007 13:49
    august_a
    Poziom 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 04 Wrz 2007 15:13
    kamilnt
    Poziom 10  

    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 04 Wrz 2007 15:45
    aster11
    Poziom 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 napisał:
    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 04 Wrz 2007 16:56
    adamusx
    Poziom 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:

    Code:
    /*  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 04 Wrz 2007 17:50
    aster11
    Poziom 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 04 Wrz 2007 22:27
    upanie
    Poziom 21  

    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.

TME logo Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
TME Logo