logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak zmierzyć czas wykonania funkcji w AVR Studio z AVR-GCC?

rafikAVR 24 Wrz 2013 07:45 2850 11
  • #2 12771294
    Michał 911
    Poziom 18  
    Możesz włączyć przerwanie sprzętowe (najlepiej ustaw je jak najczęściej) w przerwaniu dodawaj licznik. Za funkcja której czas chesz zmierzyć ustaw "blokadę" licznika. Potem odczytaj licznik i pomnóż przez czas między jednym, a drugim przereaniem.

    Sposób 2:
    jeżeli funkcja nie jest niczym uwarunkowana ( same polecenia) dopisz w programie żeby wykonała się np. 10 000 razy, zmierz stoperem czas i podziel przez 10 000.
  • #3 12771360
    2P
    Poziom 20  
    Albo jeśli jest to funkcja która nie jest uwarunkowana zdarzeniami w świecie zewnętrznym (na przykład czysta funkcja obliczeniowa), można przeprowadzić symulację. Wstawiasz punkt wstrzymania przed i za wywołaniem funkcji. W trybie symulacji w AVR-Studio masz licznik cykli procesora (nie działa niestety w trybie debuggowania JTAG). Licznik ten możesz wyzerować na pierwszym breakpoincie i przy drugim masz czas wykonania w cyklach.
  • #4 12771400
    rafikAVR
    Poziom 16  
    2P napisał:
    Albo jeśli jest to funkcja która nie jest uwarunkowana zdarzeniami w świecie zewnętrznym (na przykład czysta funkcja obliczeniowa), można przeprowadzić symulację. Wstawiasz punkt wstrzymania przed i za wywołaniem funkcji. W trybie symulacji w AVR-Studio masz licznik cykli procesora (nie działa niestety w trybie debuggowania JTAG). Licznik ten możesz wyzerować na pierwszym breakpoincie i przy drugim masz czas wykonania w cyklach.


    Chcę zasymulować czas wykonywania funkcji ,nie posiadam pod ręka teraz uC .
    Wynik ma być oceną dla mnie czy AVR podoła zadaniu jakiego od niego oczekuje czy będę musiał zastosować uC o innej architekturze .

    używając breakpoint w Avr studio zawsze dostaje wynik 128uS dla testowego kodu :


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    co jest nie tak ? możesz pokierować mnie jak dokładnie wykonać symulacje ?
  • Pomocny post
    #5 12771433
    Tomasz Gumny
    Poziom 28  
    1. Ustaw kursor na wywołaniu badanej funkcji;
    2. Kliknij przycisk "Run to cursor";
    3. Wyzeruj "Cycle counter";
    4. Ustaw kursor za funkcją;
    5. Ponownie naciśnij "Run to cursor"
    6. Odczytaj licznik cykli.
    Możesz ustawić częstotliwość kwarcu i odczytać od razu poprawny czas wykonania funkcji.
  • #6 12771439
    2P
    Poziom 20  
    Kompilator może optymalizować kod ponieważ widzi, że zmienna In nie jest nigdzie używana i po prostu przypisuje jej wartość 64 a następnie wywołuje ciało for-a.
    Spróbuj nadać zmiennej In atrybut volatile.

    Niemniej zaskakuje mnie trochę to zjawisko. Z tego co pamiętam (nie mam pod ręką kompilatora avr-gcc), to we wnętrzy funkcji _delay_ms jest funkcja assemblerowa której optymalizacja jest zabroniona.

    Możesz jeszcze spróbowac dopisać we wnętrzu for-a coś takiego:
    asm volatile("" : : "r"(In));
    To powinno "oszukać" kompilator, że zmienna In jest używana

    Dodano:
    ----------------------
    Właśnie czytając powyższą odpowiedź pomyślałem - może w złym miejscu umieszczasz punkt przerwania? Nie umieszczaj go na "for" tylko przed i za.
  • #7 12771589
    tmf
    VIP Zasłużony dla elektroda
    2P napisał:
    Kompilator może optymalizować kod ponieważ widzi, że zmienna In nie jest nigdzie używana i po prostu przypisuje jej wartość 64 a następnie wywołuje ciało for-a.


    Nie jest to możliwe, gdyż optymalizacja _delay jest zabroniona - zawiera ona volatile. Dodatkowo nie ma atrybutu zezwalającego na zastąpienie wywołania wynikiem funkcji (__attribute__(const)).
    Najpewnie na skutek optymalizacji breakpoint nie jest postawiony tam gdzie się wydaje, że jest. Należy przejść na podgląd disasemblera i tam wstawić breakpointy.
    BTW, nie patrz na czas, bo ten zależy od ustawionej częstotliwości, tylko na cycle counter, który ci pokaże liczbę taktów zegara, którą jeśli potrzebujesz przeliczysz sobie na czas znając faktyczne taktowanie MCU.
  • #8 12771591
    excray
    Poziom 41  
    Dlatego najlepiej podejrzeć w pliku *.lss czy ta pętla ma odwzorowanie w kodzie asm. Ewentualnie jeśli ma symulację podejrzeć właśnie w asm i tam mierzyć czas trwania.
  • #9 12771705
    Tomasz Gumny
    Poziom 28  
    tmf napisał:
    BTW, nie patrz na czas, bo ten zależy od ustawionej częstotliwości, tylko na cycle counter, który ci pokaże liczbę taktów zegara, którą jeśli potrzebujesz przeliczysz sobie na czas znając faktyczne taktowanie MCU.
    Można odczytywać poprawny czas, tylko należy najpierw ustawić faktyczną częstotliwość taktowania. Wystarczy nacisnąć Debug->Start Debugging (Ctrl+Shift+Alt+F5) i następne AVR Simulator Option (Alt+O). Na wypadek, gdyby ktoś nie wiedział... :D
  • #10 12772547
    2P
    Poziom 20  
    tmf napisał:
    Nie jest to możliwe, gdyż optymalizacja _delay jest zabroniona - zawiera ona volatile.

    Dlatego też napisałem właśnie, że wydaje mi się to dziwne - nie miałem pod ręką kompilatora aby sprawdzić czy tam jest volatile w środku. Czyli mój trop był błędny.
    tmf napisał:
    Dodatkowo nie ma atrybutu zezwalającego na zastąpienie wywołania wynikiem funkcji (__attribute__(const)).

    To już nie jest takie proste, ponieważ funkcje static inline są traktowane przez kompilator w bardzo specyficzny sposób (trochę jak makra) i kompilator potrafi zoptymalizować ich wywołania nawet jeśli jawnie nie nadamy im atrybutu mówiącego kompilatorowi, że wyjście funkcji zależy tylko od podanego parametru.

    Ogólnie testowanie tego for-a jest uciążliwe. Miał być test czasu wykonania funkcji. Wtedy jest o tyle łatwiej, że takich wywołań, poza pewnymi specyficznymi warunkami, kompilator sam z siebie nie zoptymalizuje i stawiamy przerwanie przed i po wywołaniu funkcji. Po co więcej komplikacji? Jeśli funkcja jest umieszczona w pętli lub innym dziwnym miejscu, można sobie życie ułatwić dodając wstawką assemblerową dwa nopy (na początku i na końcu). Dzięki temu będziemy mieli gdzie breakpointa zaczepić.

    Natomiast testowanie w ten sposób jakichkolwiek funkcji typu static inline (a __delay_ms jest taką właśnie funkcją) to kłopotliwy temat. Przy włączonej optymalizacji może być bardzo różnie i zmierzony czas wykonania nie zawsze będzie adekwatny do czasu tej samej funkcji w innym miejscu programu.
  • Pomocny post
    #11 12772569
    tmf
    VIP Zasłużony dla elektroda
    Ja tam myślę, że to _delay to był tylko przykład - w końcu jaki jest sens mierzyć czas działania _delay? Żeby sprawdzić, czy autorzy AVR-libc się nie pomylili?
  • #12 12773001
    rafikAVR
    Poziom 16  
    Wywalilem delay_ms z testu i wstawiłem swoją funkcję której potrzebowałem znać czas wykonywania :)

    Dziękuje bardzo wszystkim za pomoc , symulator w AVR studio dostarczył mi wielu bardzo ważnych informacji na temat pisaniu oprogramowania i optymalizacji kodu do szybszej pracy .
REKLAMA