Zarządzanie przepełnieniem Timer1 w ATmega128 ? pytania o przerwania i czasoprzestoj

Przerwanie Timera w ATmega





Poprzedni Następny
Wiadomość
Spis treści
From: Jacek_FH <satan_at_nospam_hell.net.pl>
Subject: Przerwanie Timera w ATmega
Date: Sat, 21 Jan 2006 17:29:34 +0100


Witam,

Mam proste pytanko, na które jednak nie umiałem znaleźć odpowiedzi w
specyfikacji (jest gruba więc mogłem przegapić - jak tak to proszę o
namiary)
Piszę program na ATmega128, w głównej pętli sprawdzam cyklicznie stan
portów i w momencie zmiany zapisuje stan i czas do pamięci.
Zliczanie czasu jest zrealizowane na 16bitowym Timerze1 z dzielnikiem 8 co
na 16MHz zegarze daje zliczanie co 0,5 mikrosekundy. By móc zmierzyć kilka
sekund dołożyłem dodatkowy rejestr inkrementowany w przerwaniu Timera1

Przepelnienietimera:
in r20, SREG
inc r22
out SREG, r20
reti

A pytanko jest takie:
Czy może się zdarzyć tak, że najpierw przepełni się licznik Timer1, później
w głównej pętli zostanie zapisany czas, a dopiero później zostanie
obsłużone przerwanie?
Inaczej mówiąc - czy mogą wystąpić jakieś przekłamania czy też skok do
przerwania występuje dokładnie z przejściem Timera z max na bottom ?
Doświadczalnie niczego takiego nie stwierdziłem ale wolałbym się upewnić.

I przy okazji drugie pytanko - opóźnienie czasu zapisania zdarzenia w
głównej pętli o obsługę przerwania to: 3 takty na zawartość procedury
przerwania, 4 takty na powrót z przerwania (reti) a ile taktów na skok do
przerwania ?
Inaczej - ile taktów zajmie cała przedstawiona procedura ?

--
Jacek_FH

Poprzedni Następny
Wiadomość
Spis treści
From: Gregor <pij_at_nospam_wiecej.piwa.a.nie.spamuj.pl>
Subject: Przerwanie Timera w ATmega
Date: Sat, 21 Jan 2006 19:34:57 +0000


Jacek_FH napisal:
Czy może się zdarzyć tak, że najpierw przepełni się licznik Timer1, później
w głównej pętli zostanie zapisany czas, a dopiero później zostanie
obsłużone przerwanie?
Zalezy jak napisales procedure w petli glownej - moze sie zdazyc nastepujaca
"nieszczesliwa" kombinacja - timer jest bliski przepelnienia, zachodzi zmiana na
porcie - petla glowna zaczyna kopiowac czas zdaznia - kopiuje zawartosc timera,
w tym momencie wchodzi przerywanie ktore inkrementuje twoj dodatkowy licznik,
petla glowna kontynuuje - kopiuje zawartosc licznika. Czas wynikowy - pomylka
"do przodu" prawie o jeden okres timera. Jesli zmienisz kolejnosc przepisywania
czasu (najpierw licznik, potem timer) podobny scenariusz wyprodukuje ci
pomylke "do tylu". Jest to wyjatkowo upierdliwy blad - wystepuje stosunkowo
zadko i trudno go zasymulowac. Tak na goraco proponowlbym nastepujace
rozwiazanie - kopiowac najpierw timer, potem licznik - nastepnie odczytac
timer jeszcze raz i sprawdzic czy jego wartosc nie jest mniejsza niz przy
pierwszym odczycie (co wskazuje na wystapienie przepelnienia pomiedzy
odczytami) - jesli tak, inkrementowac kopie licznika.
Przy okazji - nie napisales czy przerywanie od timera jest jedynym ktorego
uzywasz, jesli nie - wejscie do jego obslugi moze sie opoznic o czas obslugi
tego innego przerywania.
GRG

--
Tutaj sygnatura Grzegorza Domagały - jeśli chcesz wysłać do niego wiadomość
pisz pod adres grzegorz.domagata_at_nospam_chello.at i nie zapomnij dodać
"kielbaska dla cerbera" w treści albo Cerber zeżre twój list...
Strona domowa: http://members.chello.at/grzegorz.domagata/


Poprzedni Następny
Wiadomość
Spis treści
From: "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Sat, 21 Jan 2006 20:25:41 +0000 (UTC)


Gregor <pij_at_nospam_wiecej.piwa.a.nie.spamuj.pl> napisał(a):

Jacek_FH napisal:
Czy może się zdarzyć tak, że najpierw przepełni się licznik Timer1, później
w głównej pętli zostanie zapisany czas, a dopiero później zostanie
obsłużone przerwanie?
Zalezy jak napisales procedure w petli glownej - moze sie zdazyc nastepujaca
"nieszczesliwa" kombinacja - timer jest bliski przepelnienia, zachodzi zmiana n
a
porcie - petla glowna zaczyna kopiowac czas zdaznia - kopiuje zawartosc timera,
w tym momencie wchodzi przerywanie ktore inkrementuje twoj dodatkowy licznik,
petla glowna kontynuuje - kopiuje zawartosc licznika. Czas wynikowy - pomylka
"do przodu" prawie o jeden okres timera. Jesli zmienisz kolejnosc przepisywania
czasu (najpierw licznik, potem timer) podobny scenariusz wyprodukuje ci
pomylke "do tylu". Jest to wyjatkowo upierdliwy blad - wystepuje stosunkowo
zadko i trudno go zasymulowac. Tak na goraco proponowlbym nastepujace
rozwiazanie - kopiowac najpierw timer, potem licznik - nastepnie odczytac
timer jeszcze raz i sprawdzic czy jego wartosc nie jest mniejsza niz przy
pierwszym odczycie (co wskazuje na wystapienie przepelnienia pomiedzy
odczytami) - jesli tak, inkrementowac kopie licznika.
Przy okazji - nie napisales czy przerywanie od timera jest jedynym ktorego
uzywasz, jesli nie - wejscie do jego obslugi moze sie opoznic o czas obslugi
tego innego przerywania.
GRG


W takim przypadku , na czas odczytu zablokowałbym przerwanie od Timera.

Piotrek


--
Wysłano z serwisu Usenet w portalu Gazeta.pl -> http://www.gazeta.pl/usenet/

Poprzedni Następny
Wiadomość
Spis treści
From: Jacek_FH <satan_at_nospam_hell.net.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Sat, 21 Jan 2006 23:41:52 +0100


Jacek_FH napisal:
Czy może się zdarzyć tak, że najpierw przepełni się licznik Timer1, później
w głównej pętli zostanie zapisany czas, a dopiero później zostanie
obsłużone przerwanie?

Wyraziłem się trochę niejasno w powyższym pytaniu.
Sposób obsłużenia problemu o którym piszecie już mam (poniżej).
Pytam się trochę o coś innego - czy na pewno nie zdarzy się sytuacja że
najpierw przepełni się timer, później wykonam oba odczyty (licznika i
timera), a dopiero na końcu wykona się procedura przerwania. Lub też
odwrotnie - procedura przerwania wykona się gdy w timerze będzie najwyższa
wartość, później będą moje odczyty a dopiero po nich przekręci się timer.

Taki sposób działania jest całkiem nielogiczny (co pewnie spowodowało
niezrozumienie mojego pytania) ale chciałem się po prostu upewnić że avr
czegoś takiego nie wyczynia.

A w odpowiedzi:

Dnia 2006-01-21, "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl> pisze:

Tak na goraco proponowlbym nastepujace
rozwiazanie - kopiowac najpierw timer, potem licznik - nastepnie odczytac
timer jeszcze raz i sprawdzic czy jego wartosc nie jest mniejsza niz przy
pierwszym odczycie (co wskazuje na wystapienie przepelnienia pomiedzy
odczytami) - jesli tak, inkrementowac kopie licznika.

Akurat takie rozwiązanie mogłoby spowodować podwójne inkrementowanie
licznika. Trzeba by jeszcze raz odczytać licznik w przypadku różniących się
timerów.
Zamierzam zrobić to tak że licznik będę porównywał i przy różnych odczytach
uznam wyższy i zapiszę do pamięci na pozycji timer - zero.

Przy okazji - nie napisales czy przerywanie od timera jest jedynym ktorego
uzywasz, jesli nie - wejscie do jego obslugi moze sie opoznic o czas obslugi
tego innego przerywania.

Jedyne.

W takim przypadku , na czas odczytu zablokowałbym przerwanie od Timera.

Timer leci niezależnie od przerwań, tylko ten dodatkowy mój licznik
zostanie wtedy zatrzymany. Więc może nastąpić przepełnienie bez
inkrementowania licznika i wynik też do kitu.
Musiałbym i zatrzymywać przerwania i zliczanie timera ale wtedy tracę
"poczucie czasu" ;)

--
Jacek_FH

Poprzedni Następny
Wiadomość
Spis treści
From: "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Sun, 22 Jan 2006 01:17:01 +0000 (UTC)


Jacek_FH <satan_at_nospam_hell.net.pl> napisał(a):

..

W takim przypadku , na czas odczytu zablokowałbym przerwanie od Timera.

Timer leci niezależnie od przerwań, tylko ten dodatkowy mój licznik
zostanie wtedy zatrzymany. Więc może nastąpić przepełnienie bez
inkrementowania licznika i wynik też do kitu.
Musiałbym i zatrzymywać przerwania i zliczanie timera ale wtedy tracę
"poczucie czasu" ;)

Wybacz , ale chyba nie wiesz , o czym piszesz.Atmel przewidział Twój problem z
odczytem 16-bitowych rejestrów timera i nie ma możliwości , by licznik się
"przekręcił" pomiędzy odczytem młodszego i starszego rejestru licznika.
Podobny problem rozwiązałem jak poniżej , a preskaler ustawiony był na 1:
..
cli
in r16,TCNT1L
in r17,TCNT1H
mov r18,r22
sei
st Y+0,r16
st Y+1,r17
or r16,r17
brne skip
inc r18
skip:
st Y+2,r18
..

Pozdrawiam
Piotrek


--
Wysłano z serwisu Usenet w portalu Gazeta.pl -> http://www.gazeta.pl/usenet/

Poprzedni Następny
Wiadomość
Spis treści
From: Jacek_FH <satan_at_nospam_hell.net.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Sun, 22 Jan 2006 02:32:33 +0100


Dnia 2006-01-22, "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl> pisze:

Wybacz , ale chyba nie wiesz , o czym piszesz.Atmel przewidział Twój problem z
odczytem 16-bitowych rejestrów timera i nie ma możliwości , by licznik się
"przekręcił" pomiędzy odczytem młodszego i starszego rejestru licznika.

Wiem i nie o tym piszę.

Podobny problem rozwiązałem jak poniżej , a preskaler ustawiony był na 1:
..
cli <- załóżmy że TCNT1 = 65535, przerwanie jeszcze się nie wywołało
in r16,TCNT1L <- przerwanie wyłączone, a TCNT1 = 0, zatrzaskiwany w buforze
in r17,TCNT1H
mov r18,r22

Może źle myślę ale wytłumacz czemu.

--
Jacek_FH

Poprzedni Następny
Wiadomość
Spis treści
From: "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Sun, 22 Jan 2006 01:56:39 +0000 (UTC)


Jacek_FH <satan_at_nospam_hell.net.pl> napisał(a):

Dnia 2006-01-22, "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl> pisze:

Wybacz , ale chyba nie wiesz , o czym piszesz.Atmel przewidział Twój problem
z
odczytem 16-bitowych rejestrów timera i nie ma możliwości , by licznik się
"przekręcił" pomiędzy odczytem młodszego i starszego rejestru licznika.

Wiem i nie o tym piszę.

Podobny problem rozwiązałem jak poniżej , a preskaler ustawiony był na 1:
..
cli <- załóżmy że TCNT1 = 65535, przerwanie jeszcze się nie wywołało
in r16,TCNT1L <- przerwanie wyłączone, a TCNT1 = 0, zatrzaskiwany w buforze
in r17,TCNT1H
mov r18,r22

Może źle myślę ale wytłumacz czemu.


Do naprawienia powyższego przypadku , służy właśnie to:
sei <-teraz wykona się przerwanie , a w nim inc r22
st Y+0,r16
st Y+1,r17
or r16,r17 <- r16=0 i r17=0 więc ...
brne skip <- ... warunek nie spełniony i ...
inc r18 <- ... wykona się ta instrukcja , czyli wartość r18 przed
przerwaniem+1 i tyle właśnie jest w tym momencie w r22
skip:
st Y+2,r18
..
Czy teraz rozumiesz , o co mi chodzi ?

Piotrek


--
Wysłano z serwisu Usenet w portalu Gazeta.pl -> http://www.gazeta.pl/usenet/

Poprzedni Następny
Wiadomość
Spis treści
From: Jacek_FH <satan_at_nospam_hell.net.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Mon, 23 Jan 2006 02:01:13 +0100


Dnia 2006-01-22, "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl> pisze:

Do naprawienia powyższego przypadku , służy właśnie to:
sei <-teraz wykona się przerwanie , a w nim inc r22
st Y+0,r16
st Y+1,r17
or r16,r17 <- r16=0 i r17=0 więc ...
brne skip <- ... warunek nie spełniony i ...
inc r18 <- ... wykona się ta instrukcja , czyli wartość r18 przed
przerwaniem+1 i tyle właśnie jest w tym momencie w r22
skip:
st Y+2,r18
..
Czy teraz rozumiesz , o co mi chodzi ?

Teraz wszystko pasuje, wczoraj odpowiadałem późno w nocy i z lenistwa nie
przyjrzałem się końcówce kodu :(

Ale zastosuję swój kod bo jest o 2-3 takty szybszy:

mov r18,r22
in r16,TCNT1L
in r17,TCNT1H
cmp r18,r22
brne change
st Y+2,r18
st Y+1,r17
st Y+0,r16
ret
change:
st Y+2,r22
st Y+1,r23 ; r23 = 0
st Y+0,r23
ret

--
Jacek_FH

Poprzedni Następny
Wiadomość
Spis treści
From: Jacek_FH <satan_at_nospam_hell.net.pl>
Subject: Re: Przerwanie Timera w ATmega
Date: Mon, 23 Jan 2006 02:14:55 +0100


Dnia 2006-01-22, "Piotrek Sz." <zumek_at_nospam_WYTNIJ.gazeta.pl> pisze:

Do naprawienia powyższego przypadku , służy właśnie to:
sei <-teraz wykona się przerwanie , a w nim inc r22
st Y+0,r16
st Y+1,r17
or r16,r17 <- r16=0 i r17=0 więc ...
brne skip <- ... warunek nie spełniony i ...
inc r18 <- ... wykona się ta instrukcja , czyli wartość r18 przed
przerwaniem+1 i tyle właśnie jest w tym momencie w r22
skip:
st Y+2,r18
..
Czy teraz rozumiesz , o co mi chodzi ?

Teraz wszystko pasuje, wczoraj odpowiadałem późno w nocy i z lenistwa nie
przyjrzałem się końcówce kodu :(
Ale działa tylko dla prescalera = 1 więc zastosuje swój (zresztą o 2-3
takty krótszy):

mov r18,r22
in r16,TCNT1L
in r17,TCNT1H
cmp r18,r22
brne change
st Y+2,r18
st Y+1,r17
st Y+0,r16
ret
change:
st Y+2,r22
st Y+1,r23 ; r23 = 0
st Y+0,r23
ret

--
Jacek_FH