Zarządzanie przepełnieniem Timer1 w ATmega128 ? pytania o przerwania i czasoprzestoj
Przerwanie Timera w ATmega
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
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/
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/
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
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/
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
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/
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
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