Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

AVR: Czas obsługi/reakcji na przerwanie licznika

25 Mar 2017 13:09 1116 5
  • Poziom 13  
    Mam dziwny problem ze znikającym jednym tickiem w liczniku gdy są włączone przerwania przy przepełnieniu. Licznik pracuje w trybie normalnym, taki sam efekt przy 8 i 16 bitowym, zaobserwowałem na atmedze 16 i 644P (bo takie miałem akurat pod ręka).

    Normalnie bez przerwań, licznik przy przepełnieniu zeruje się i zaczyna liczyć od 0, wszystko tak jak można byłoby się spodziewać. Poniżej fragment kodu:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod


    Po zatrzymaniu licznika, zawiera wartość 5. Wszystko ok.

    Po włączeniu przerwań i dosyć prostym kodzie obsługi przerwania przepełnienia, zajmującej 12 cykli:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod


    Ten sam kod, zachowa się nieco inaczej:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod


    Na koniec, po zatrzymaniu licznika, jego wartość powinna wynosi tak jak wcześniej, powiększone o czas obsługi przerwania, czyli 17, a otrzymuję 16.

    Wygada to tak, jakby w punkcie [1], po ustaleniu, ze wymagane jest wykonanie przerwania, TCNT jest zerowane. Zrobiłem test wyłączając licznik w przerwaniu i po odjęciu narzutu tego kodu, TCNT wskazywał 0. Mimo, iż teoretycznie powinien wskazać 1, bo przerwanie nastąpiło po wykonaniu tego 1-cyklowego NOP-a. Gdy zamienię go na coś innego, np. jakaś 4-cyklową instrukcję, to oczywiście przerwanie wykona się po jej zakończeniu, ale licznik nadal pokaże o 1 cykl mniej, czyli 3.

    Przeszukałem siec i dokumentacje, ale nie mogłem nigdzie znaleźć żadnej wzmianki o tym zachowaniu. Być może jest to coś oczywistego i tak prostego, że aż nieprawdopodobnego, przez co to pomijam.

    Może ktoś potrafi coś więcej na ten temat powiedzieć, albo miał podobny problem?

    Uprzedzając pytania, po co, na co, do czego mi to, użyj innego um… itd. Chciałbym po prostu wiedzieć wtf , skąd wynika takie zachowanie. A potrzebne może to być w różnych dziwnych sytuacjach wymagających dokładnego reżimu czasowego, np., bramkowanie przy pomiarach, licznik cykli (AVR-Tick-Counter) etc.


    Update:
    Poprawiłem nieco formatowanie...
    BTW, syntax mógłby wycinać CRLF jeśli występujące po nim, aby nie wprowadzać dodatkowej pustej linii w formatowanym kodzie, i standardowo alignować taba do 4 znaków...
    [3.12.2020, webinar] Zagadnienia pomiarowe w nowoczesnej inżynierii materiałowej. Zarejestruj się
  • Poziom 31  
    Sprawdź czy skok do obsługi przerwania to JMP czy RJMP?

    JarekC
  • Poziom 13  
    Na początku sprawdziłem, jest JMP 3-cyklowy, zapomniałem o tym wspomnieć, myśląc że komentarze w kodzie o tym mówią. Jest nawet dodatkowy NOP, aby przerwanie miało dokładnie 12 cykli, jakoś na parzystych łatwiej mi się dokonuje obliczenia.

    Może innym licznikiem sprawdzę ile tak naprawdę cały ten kod konsumuje cykli...

    Update:
    Wyszło na to, że cały ten kod wykonuje się o 1 cykl mniej niż zakładałem, tak jakby przerwanie trwało tylko 11 cykli. Nasuwa się więc pytanie, jak interpretować fragment z dokumentacji opatrzony tytułem "Interrupt Response Time":

    Cytat:
    The interrupt execution response for all the enabled AVR interrupts is four clock cycles minimum. After four clock cycles the program vector address for the actual interrupt handling routine is executed. During this four clock cycle period, the Program Counter is pushed onto the Stack. The vector is normally a jump to the interrupt routine, and this jump takes three clock cycles.


    Szczególnie wzmianka o tych 4 cyklach. Czy w nich znajduje się ten skok do właściwego kodu przerwania, który znajduje się pod danym indeksem w wektorze, czy to tylko czas do rozpoczęcia wykonania tego co jest właśnie w tym wektorze? Bo nawet jeśli te minium 4 odnosi się do PUSH + RJMP + ewentualny offset do zakończenia mutli-cyklowej operacji, to nijak mi nie wychodzi te 11 cykli z mojego kodu. Bo powinno wyjść wtedy 10 cykli. W przeciwnym wypadku 12, ale nie 11...

    Update 2:
    Przejrzałem ponownie sieciowe zasoby mówiące o czasie odpowiedzi na ISR i one potwierdzają moje wcześniejsze założenie, ze 4 cykle odnoszą się do przygotowania i odpalenia tego co znajduje się pod danym adresie w wektorze przerwań.

    Zatem jest tak jak w pierwszym poście:
    Code:
    4 przygotowanie  przerwania
    
    3 jmp / 2 rjmp
    4 reti


    Potwierdza to też jakiś dokument atmela o użyciu przerwań zewnętrznych, gdzie znajduje się również sekcja "Interrupt Response Time", a tam dokładnie wylistowano owe 4 cykle:

    Cytat:
    These four/five clock cycles include:
    - Two/Three cycles for pushing the Program Counter (PC) value into the stack
     - One cycle for updating the stack pointer
     - One cycle for clearing the Global interrupt enable (I) bit


    Ta 5 cyklowa wersja dotyczy kostek gdzie PC jest większy niż 2 bajty.

    Zrobiłem kolejny test, podmieniłem w tablicy opcode z jmp na reti, czyli wedle docsów taki kod powinien zając 8 cykli. U mnie oczywiście różnica między wersją z przerwaniami a bez wynosi tylko 7 cykli.
  • Poziom 31  
    Wg. mnie te 4 takty obejmują również czas wykonania przerywanego rozkazu.
    Przynajmniej tak pokazuje symulator w AVR Studio.

    Oczywiście jeżeli przerywamy rozkaz dwucyklowy (np SBI) to opóźnienie wyniesie 5 taktów.

    Jeszcze dla pełnej poprawności to piszesz o ATEMGA16 i ATMEGA644P więc Twój przykładowy program zawiera błędy:
    - dla ATMEGA rejestry Timera 0 znajdują się w przestrzeni I/O więc dostęp do nich jest przez IN/OUT a nie LDS/STS
    - dla ATMEGA644P nie ma rejestru TCCR0 tylko są TCCR0A i TCCR0B i tez sa w przestrzenio I/O

    Pozdrawiam
    JarekC
  • Poziom 13  
    Dzięki za test w symulatorze. Brałem pod uwagę taki scenariusz i chyba tak w rzeczywistości jest, choć trochę kłóci się to z ostatnim cytatem z notki wyżej.

    Oczywiście pod innymi kostkami będą inne rejestry timera. Początkowo zaobserwowałem to pod 644P na 16-bit liczniku. Później sprawdziłem na innych timerach i atmedze16, skąd pochodzą fragmenty kodu. Różnice pomiędzy out i sts to chyba tylko szybkość i semantyka.
  • Użytkownik usunął konto