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.

funkcja printf od Freddiego

Pawel Domagalski 18 Maj 2010 20:07 3293 8
  • #1 18 Maj 2010 20:07
    Pawel Domagalski
    Poziom 13  

    Poniżej przedstawiam korespondencję oraz dalsze kroki mające na celu wykorzystanie implementacji funkcji printf pochodzącej z strony freddiego chopina.

    Ja:
    Witaj, Chcialem wykorzystac twoja funkcje printf, jednak w paczce z nia zabraklo pliku usart.h . Brakowolo jedynie referencji do funkcji usart_put_char więc ją dopisalem. Niestety nie ma również referencji do pozostałych funkcji takich jak _close, _fstat, _sbrk , _isatty, _lseek, _read, _write.Czytałem że tych funkcji sie nie zamieszcza ponieważ są one bardzo zależne od sprzętu więc należy je napisać samodzielnie. Jednak to już przerasta moje umiejętności. Wobec tego mam pytanie czy mógłbyś udostępnić swoje powyższe funkcje pod stm32 ?

    Freddie Chopin:
    Jestem na 99% przekonany, że zamiast mojej funkcji printf_() (z
    podkreśleniem na końcu!) wywołujesz zwykłe printf() (bez podkreślenia)
    - czyli standardową funkcję z biblioteki. Dodałem tam to podkreślenie,
    bo zastąpienie funkcji printf() wymaga niewielkich zabiegów podczas
    samego procesu kompilacji (konkretnie dodanie flagi
    -fno-builtin-printf do kompilacji i/lub linkowania lub coś na ten
    styl) - prościej dopisać jeden znaczek więcej do nazwy [;
    Muszę kiedyś też zamieścić te minimalne syscalls (tak zwą się funkcje
    które wymieniłeś), ale to kiedyś przy okazji. Jeśli linker się o nie
    czepia, to znaczy, że dołączył jakąś standardową funkcję...

    Ja:
    Zgadza sie :). Wywoływałem printf(). Po wywołaniu
    printf_(), kompilacja przebiega prawidłowo niestety na terminal nic nie
    leci. UART mam dobrze skonfigurowane a moja funkcja usart_put_char
    wyglada nastepujaco.
    void usart_put_char(char znak)
    {
    USART_SendData(USART1,znak);
    }

    Mozesz wyslac mi swoj plik usart.h i napisać po krótce co należy zrobić
    aby funkcja printf poprawnie działała ?

    FC:
    Nie sądzę aby mój plik usart.h Cię ratował - funkcja wpisująca znaki na UART jest w moim przypadku mocno zakręcona, a to nie jest istotne w tej sprawie - Twoja implementacja jest też OK, jeśli jej ręczne wywołanie w kodzie działa:
    USART_SendData(USART1,'a');
    usart_put_char('b');

    Co trzeba zrobić, żeby działało? Hmm... Wg mnie nic, ale może być coś co przeoczyłem. Funkcję itoa() jak mniemam masz, bo bez tego by się nie zlinkowało. Jeśli masz JTAGa, to spróbuj użyć sprintf_() i podejrzeć zawartość pamięci. Jeśli go nie masz, to tak czy siak spróbuj sprintf_(), a rezultat wyślij potem UARTem ręcznie. Przed użyciem sprintf_() trzeba w pliku printf.h go "włączyć" odpowiednią linijką.

    Dodano po 7 [minuty]:

    Jtaga posiadam, oczywiście jedynego słusznego jtagkeya :) .
    Sprintf_ działa.
    printf_ niezbyt działa. Wywołanie printf_("String"); na terminalu wyswietlana jest tylko ostatnia litera czyli 'g'.

    0 8
  • #2 18 Maj 2010 21:21
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Dobra - kolejny test. Wydaje mi się, że masz lekki problem ze swoimi funkcjami. Może w Twoich funkcjach nie ma oczekiwania na zakończenie poprzedniej transmisji? Wywołaj swoją funkcję wyświetlania znaku mniej więcej tak:
    USART_SendData(USART1,'a');
    USART_SendData(USART1,'b');
    USART_SendData(USART1,'c');
    USART_SendData(USART1,'d');
    USART_SendData(USART1,'e');

    4\/3!!

    Jak kolega niżej.
    Robak

    0
  • #3 18 Maj 2010 22:08
    Pawel Domagalski
    Poziom 13  

    Racja, przeciez to logiczne. Po dodaniu najzwyklejszego opoznienia printf wreszcie dziala :)

    Chcialem jeszcze dopisac obsluge operatora \n wiec zmodyfikowalem funkcje __vfprintf w taki sposob jednak nie dziala:

    Code:

    static int __vfprintf_(printf_file_t *stream, const char *format, va_list arg)
    {
       char character;

       stream->length=0;                  // clear the current length of stream

       while ((character = *format++) != '\0')   // loop until termination character '\0'
       {
          /*
          if (character==92) //92 jako numer znaku \
          {
                if(character =='n')
                {
                   usart_put_char(10); //enter
                   usart_put_char(13);
                }
          }*/
          if (character != '%')            // specifier found?
             __fputc_(character, stream);   // no - just print the character
          else                        // yes
          {
             character=*format++;         // get the character after the specifier

             if (character == '%' || character == 'c')   // %% - print '%' or %c - print single char
             {
                if (character == 'c')      // was that %c?
                   character = va_arg(arg, int);   // get the char from va_list
                __fputc_(character, stream);
                continue;
             }

             // %s, %d and %x - these require a string to be copied to stream
             if (character == 's' || character == 'd' || character == 'x')
             {
                char buffer[11];
                char* buffer_ptr;

                if (character == 's')      // %s - get the pointer to string
                   buffer_ptr=va_arg(arg, char*);
                else                  // %d or %x - convert the number to string
                {
                   int base = (character == 'd' ? 10 : 16);

                   buffer_ptr = itoa(va_arg(arg, int), buffer, base);
                }

                while ((character = *buffer_ptr++))   // copy the string to stream
                   __fputc_(character, stream);
                continue;
             }
          }
       }

       return stream->length;
    }

    0
  • #4 18 Maj 2010 22:20
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Po pierwsze zauważ, że w Twoim kodzie sprawdzasz czy dany znak jest JEDNOCZEŚNIE backslashem (hint - można go zapisać jako '\\') i literką n.

    Zmodyfikuj więc swój kod mniej więcej tak:

    Code:
    if (character == '\\')
    
    {
        character = *format++;

        if (character == 'n')
        {
            __fputc_('\n', stream);
            __fputc_('\r', stream);
        }

        continue;
    }


    Nie jestem pewny tej kolejności \n i \r, ale to już pewnie wiesz [;

    Zasadniczo nie jestem pewny, czy zamiana\n na \r\n jest zgodna ze standardem... Myślę, że bardziej uniwersalną opcją byłaby zamiana ciągu znaków "\x" na znak '\x' (w sensie wykrywasz backslasha a za nim któryś ze znaków sterujących, to konwertujesz to jakoś do samego znaku sterującego). Wtedy jednak w niektórych terminalach trzeba by dawać do łańcuchów parę znaków \r\n Konwersję chyba można oprzeć na jakiejś tabeli, choć przydałoby się ją zoptymalizować. No chyba że dawać obsługę tylko \n ew. \n i \r, to nie ma sensu się bawić [;

    4\/3!!

    0
  • #5 19 Maj 2010 17:47
    Pawel Domagalski
    Poziom 13  

    Działa. Wystarczyło zmienić szukany znak z backslasha na '\n'.
    Ostatecznie modyfikacja wygląda nastepująco:

    Code:

    if (character == '\n')
                {
                    __fputc_('\n', stream);
                    __fputc_('\r', stream);
                    continue;
                }



    Dopracowałem rownież funkcje usart_put_char, zamiast wprowadzać delaya sprawdzam flage czy UART zakończył poprzednią transmisję.

    Code:

    #define TXEflag             ((uint32_t*)0x40013800) //adres flagi TXE dla STM32


    void usart_put_char(char znak)
    {
       while(!(*TXEflag&0x00000080)); //oczekiwanie dopoki flaga TXE==1
       USART_SendData(USART1,znak);
    }



    Tak na marginesie, niestety coś zepsułem, procesor wchodzi w przerwanie HardFault_Handler natomiast openocd rzuca takie oto błędy:
    Code:

    Error: JTAG-DP STICKY ERROR
    Error: MEM_AP_CSW 0x23000052, MEM_AP_TAR 0x8000004
    Error: JTAG-DP STICKY ERROR
    Error: MEM_AP_CSW 0x23000052, MEM_AP_TAR 0x8000004
    Warn : Block write error address 0x8000000, wcount 0xfd4
    Error: unexpected error -107


    gdzie moge wyczytać co to za błąd o numerze 107? W user manual openocd nie moglem tego znaleźć.
    Uzywam biblioteki fatfs i prawdopodobnie jedna z tych funkcji powoduje błąd. Procesor wchodzi w obsługę przerwania HardFault_Handler gdzie tez znajduje się while(1); W jaki sposób sprawdzić podczas debugowania jaka funkcja wywołała to przerwanie? Używam oczywiście Eclipsa skonfigurowanego według twojego tutorialu.
    P.S.
    Openocd zawsze wyswietla:
    Code:

    Warn : not enough working area available(requested 16384, free 16336)

    Czy ten błąd jest do pominięcią? Na razie się nim nie przejmowałem ponieważ programy działały.

    0
  • #6 19 Maj 2010 20:45
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Co do tej obsługi \n to w zasadzie wychodzi na to, że nie ma sensu jej dodawać - wystarczy do łańcuchów po prostu wpisywać \n\r i wyjdzie na to samo, a będzie prościej [;

    Flagę powinieneś raczej kontrolować wewnątrz swojej funkcji USART_SendData()...

    Błedy które rzuca OpenOCD zbyt wiele niestety nie mówią pozatym, że OpenOCD nie mógł zapisać flasha...

    Podczas debuggowania powinno być zawsze (gdy rdzeń jest zatrzymany) widoczne "drzewo wywołań" czyli która funkcja wywołuje którą itd. - w tym samym okienku gdzie widzoczne jest uruchomione GDB i OpenOCD.

    Warning o working area możesz całkowicie zignorować.

    4\/3!!

    0
  • #7 19 Maj 2010 21:13
    Pawel Domagalski
    Poziom 13  

    USART_SendData() jest funkcją bibliotek ST więc nie chciałem w niej grzebać.

    Drzewo wywołań owszem pokazuje się po zatrzymaniu programu lecz za wiele wyczytać z niego nie można :/

    funkcja printf od Freddiego

    0
  • Pomocny post
    #8 19 Maj 2010 21:18
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Zawsze możesz próbować grzebać na stosie i w rejestrach (adres "powrotu" powinien być w LR), ALE... HardFault wyskakuje jak pojawia się inny - krytyczny - problem, który jest nieobsługiwany.

    4\/3!!

    0
  • #9 19 Maj 2010 21:36
    Pawel Domagalski
    Poziom 13  

    OK. Dzieki za pomoc. Sprawę printfa uważam za rozwiązaną i zamkniętą. Z drugim problemem spróbóje jeszcze jutro w katedrze zaczerpnąć pomocy, ewentualnie założę nowy temat.
    Pozdrawiam

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