Robbo
Guest
Wed Aug 29, 2007 11:58 am
Witam,
Poniżej zamieszczam fragment programu w assemblerze
dla mikrokontrolera Atmel AVR ATmega32.
Byłbym wdzięczny za zapoznanie się z nim i moim komentarzem
i odpowiedź, czy dobrze rozumuję.
int main(void)
{
8e: cf e5 ldi r28, 0x5F ; 95
90: d4 e0 ldi r29, 0x04 ; 4
92: de bf out 0x3e, r29 ; 62
94: cd bf out 0x3d, r28 ; 61
PORTB = _BV(PB1);
96: 82 e0 ldi r24, 0x02 ; 2
98: 88 bb out 0x18, r24 ; 24
PORTB |= _BV(PB1);
9a: c1 9a sbi 0x18, 1 ; 24
sbi(PORTB, PB1);
9c: c1 9a sbi 0x18, 1 ; 24
*** PORTB |= _BV(PB1) jest tożsame z sbi(PORTB,PB1);
PORTB |= _BV(PB1) | _BV(PB2);
9e: 88 b3 in r24, 0x18 ; 24
a0: 86 60 ori r24, 0x06 ; 6
a2: 88 bb out 0x18, r24 ; 24
*** Jeżeli za pomocą PORTB |= ... chcemy ustawić więcej
niż jeden bit, to najpierw pobierana jest "wartość" występująca
na tym porcie, następnie wykonywana jest na tej wartości
operacja alternatywy z maską określającą bity, które mają
zostać ustawione, a następnie uzyskany wynik zapisywany jest
do portu.
Załóżmy, że w głównej pętli programu ustawiamy/zerujemy
wyjścia na jakimś porcie za pomocą PORTB |= _BV(PB1) | _BV(PB2).
W programie działa funkcja obsługi przerwania, która także
operuje na PORTB. Zatem może pojawić się sytuacja, w której
w programie głównym zostanie odczytana "wartość" na porcie
(in r24, 0x18), następnie zacznie być wykonywana funkcja
obsługi przerwania, która zmieni wartość na PORTB, po czym
nastąpi powrót do programu głównego i wykonanie ori r24,0x06
out 0x18,r24 -- z tym że ori r24,0x06 zostanie wykonana na
wartości portu, która była uprzednio (przed wejściem do funkcji
obsługi przerwania). Stąd, może pojawić się pewne zamieszanie
i program może działać niepoprawnie. Czy dobrze myślę?
Z góry dziękuję za pomoc.
Robbo
Bogdan G
Guest
Wed Aug 29, 2007 12:21 pm
Quote:
obsługi przerwania). Stąd, może pojawić się pewne zamieszanie
i program może działać niepoprawnie. Czy dobrze myślę?
Bardzo dobrze. Możesz się napić piwa.
Zibias
Guest
Thu Aug 30, 2007 2:06 pm
Quote:
*** Jeżeli za pomocą PORTB |= ... chcemy ustawić więcej
niż jeden bit, to najpierw pobierana jest "wartość" występująca
na tym porcie, następnie wykonywana jest na tej wartości
operacja alternatywy z maską określającą bity, które mają
zostać ustawione, a następnie uzyskany wynik zapisywany jest
do portu.
Załóżmy, że w głównej pętli programu ustawiamy/zerujemy
wyjścia na jakimś porcie za pomocą PORTB |= _BV(PB1) | _BV(PB2).
W programie działa funkcja obsługi przerwania, która także
operuje na PORTB. Zatem może pojawić się sytuacja, w której
w programie głównym zostanie odczytana "wartość" na porcie
(in r24, 0x18), następnie zacznie być wykonywana funkcja
obsługi przerwania, która zmieni wartość na PORTB, po czym
nastąpi powrót do programu głównego i wykonanie ori r24,0x06
out 0x18,r24 -- z tym że ori r24,0x06 zostanie wykonana na
wartości portu, która była uprzednio (przed wejściem do funkcji
obsługi przerwania). Stąd, może pojawić się pewne zamieszanie
i program może działać niepoprawnie. Czy dobrze myślę?
Tak.
Jak nie chcesz mieć problemu to przed odczytem stanu portu i zapisem
zmienionej wartosci zablokuj na chwile przerwania.
BartekK
Guest
Thu Aug 30, 2007 2:30 pm
Zibias pisze:
Quote:
nastąpi powrót do programu głównego i wykonanie ori r24,0x06
out 0x18,r24 -- z tym że ori r24,0x06 zostanie wykonana na
wartości portu, która była uprzednio (przed wejściem do funkcji
obsługi przerwania). Stąd, może pojawić się pewne zamieszanie
i program może działać niepoprawnie. Czy dobrze myślę?
Tak.
Jak nie chcesz mieć problemu to przed odczytem stanu portu i zapisem
zmienionej wartosci zablokuj na chwile przerwania.
Albo dokonuj wyłącznie zmian w jednym miejscu, regularnie albo np pod
wpływem flagi "zostały wprowadzone zmiany, trzeba uaktualnić porty".
Wtedy obojętnie czy to przerwanie zleci zmiane, czy też inne miejsce w
programie - nie będzie konfliktu.
--
| Bartlomiej Kuzniewski
| sibi@drut.org GG:23319 tel +48 696455098
http://drut.org/
|
http://www.allegro.pl/show_user_auctions.php?uid=338173