Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Funkcja printf - błąd retarget'ingu

mickpr 02 Jan 2013 01:36 1530 5
  • #1
    mickpr
    Level 39  
    Witam
    Napotkałem problem z retarget-owaniem funkcji printf w C (kompilator CodeSourcery ARM EABI).
    W poniższym pliku (retarget.c - kod nie jest mój ) zawarta jest implementacja funkcji takich jak printf itd... chodzi mi właśnie o funkcję printf.
    Otóż..
    Funkcja działa poprawnie, łącznie z formatowaniem (np. %d) i znakami specjalnymi (\n \t... itd) tylko jeśli parametr funkcji kończy się znakiem '\n'!
    Jeśli tak nie jest, to program (ogólnie mówiąc) wywala się (Hard Fault).

    Do retargetingu wykorzystano wersje reentrant funkcji "write" - czyli :
    Code: c
    Log in, to see the code

    W TYM miejscu znalazłem częściowo wyjaśnienie, lecz nie rozumiem go w 100%.

    Zacząłem od reimplementacji funkcji write (zamiast jej wersji reentrant - powyżej) - bez efektu. Funkcja jakby nie była wcale wykonywana.
    Równiez funkcja isatty jest poprawnie (moim zdaniem) zdefiniowana.
    Blokowanie buforowania stdout też nie działa.
    Code: c
    Log in, to see the code


    O czym zapomniałem? Gdzie robię błąd?
    Jak poprawnie zaimplementować ten printf?

    A oto kod:
    Code: c
    Log in, to see the code
  • Helpful post
    #2
    rajszym
    Level 20  
    Może załączony plik stdio.c pomoże.

    W programie należy (wg potrzeby) zdefiniować funkcje:
    int get_char(void)
    int put_char(int c)
  • #3
    mickpr
    Level 39  
    rajszym wrote:
    Może załączony plik stdio.c pomoże....

    Bardzo dziękuję za chęć pomocy. Kod który przesłałeś działa.
    Niestety nie jest to to, czego bym oczekiwał.
    Równie dobrze mógłbym wrócić do mojej starej sprawdzonej funkcji xprintf.

    Moim celem jest jednak poznanie retarget'ingu, ponieważ czeka mnie implementacja systemu plików i dobrze aby był on dostępny w standardowy (dla języka C) sposób.
  • Helpful post
    #4
    rajszym
    Level 20  
    Twój kod z pewnością działa, tylko dane są buforowane i znak '\n' lub użycie funkcji 'fflush' opróżnia bufor. Nie pamiętam dokładnie, ale chyba analogiczne funkcje z biblioteki 'conio' działają podobnie.
  • Helpful post
    #5
    Freddie Chopin
    MCUs specialist
    Masz debugger? Powyżej piszesz o HardFault, ale czy jesteś PEWNY, że właśnie to się dzieje?

    Objawy które opisujesz (poza ewentualnym HardFault) są normalne, bo stdout domyślnie jest buforowany - jak już zauważono powyżej.

    4\/3!!
  • #6
    mickpr
    Level 39  
    Freddie Chopin wrote:
    Masz debugger? Powyżej piszesz o HardFault, ale czy jesteś PEWNY, że właśnie to się dzieje?
    Hard fault zwraca w moim przypadku
    CFSR = 1400 BFAR = E000ED38
    Czyli wygląda to na błąd związany ze stosem? Dobrze patrzę?.

    Program działa pod FreeRTOS 7.3.0, a zmiana wielkości stosu dla task'a nic nie daje :(.
    Wywaliłem wszystko zostawiając sam CMSIS + 3 instrukcje printf (bez znaku końca wiersza) + ostatnia ze znakiem i w tym przypadku działa tak, jak powinno - czyli drukowanie następuje PO znaku końca wiersza a brak znaku '\n' nie powoduje błędu.

    Jak więc kolega sprytnie zauważył - szukam dziury w całym (w implementacji printf).
    Dziękuję wszystkim - już wiem "gdzie walić młotkiem".
    -----------------------------------------------------------------
    [po jakimś czasie].........
    -----------------------------------------------------------------
    Dla potomności powiem, że standardowe procedury IO (z NewLIBC) są bardzo wymagające - szczególnie jeśli chodzi o gospodarowanie stosem.
    W dokumentacji FreeRTOS doczytałem, że w tym celu twórcy FreeRTOS polecają funkcje zastępczą - podobną nieco do zaproponowanego przez kolegę rajszym rozwiązania.
    Funkcje te są zawarte w pliku printf-stdarg.c , który można znaleźć w źródłach FreeRTOS'a.
    W moim przypadku przy wykorzystaniu Ethernet'u (stos LwIP w wersji 1.4.0) oraz mimo umieszczenia sterty FreeRTOS'a (wersja 7.3.0) w pamięci AHB1 (mikrokontrolera LPC1758) - tej pamięci po prostu zaczynało brakować - stąd wspomniane Hard Fault.