-
Data: 2009-06-14 10:23:08
Temat: Re: Problem lekko OT, ale w WinAVR ;-)
Od: Grzegorz Kurczyk <g...@c...slupsk.pl> szukaj wiadomości tego autora
[ pokaż wszystkie nagłówki ]Użytkownik T.M.F. napisał:
>
> Alez byla. Twoja zmienna jest typu int, czyli ma 2 bajty. AVR nie ma
> instrukcji ladowania z pamieci 2 bajtow jednoczesnie, a wiec takie
> przeslanie nie jest atomowe. Dlatego musisz okreslic ta zmienna jako
> volatile i zapewnic atomowosc operacji przez blokowanie przerwan.
> Zauwaz, ze gdyby uzyte przeslanie 16-bitowe bylo atomowe to blokowanie
> przerwan w ogole nie byloby potrzebne.
No dokładnie taki był mój tok rozumowania. Ponieważ pobranie zmiennej
int wymaga dwóch rozkazów blokuję możliwość przerwania tej operacji
przez inny wątek poprzedzając je rozkazem cli wstawionym "z palca". W
momencie gry program staje się jednowątkowy trudno mówić o ulotności
zmiennych.
Tak jak pisalem, jesli tej
> zmiennej nie okreslisz jako volatile to kompilator slusznie umieszcza to
> przerwanie gdzie mu wygodniej - w koncu nie powiedziales mu, ze cos moze
> wartosc tej zmiennej pomiedzy przeslaniami zmienic.
Ale co miałoby ją zmienić po rozkazie cli ? Po to dałem ten rozkaz aby
nic nie tykało tej zmiennej poza wnętrzem funkcji. Fakt, że gcc nie jest
kompilatorem dedykowanym do AVR-ów. W innych procesorach zablokowanie
przerwań wcale nie musi wykluczać wielowątkowości.
> Zobacz tu:
> http://www.nongnu.org/avr-libc/user-manual/group__ut
il__atomic.html
> wraz z wyjasnieniem i przykladami - powinno sie przydac.
>
I w sumie w moim przypadku volatile wcale nie jest potrzebne.
ATOMIC_BLOCK załatwia sprawę. I dokładnie taki "ATOMIC" próbowałem
zrobić na piechotę przez ręczne wstawienie cli/sei. Volatile niezbędne
byłoby gdybym gdzieś robił while(*pEncoderValue == bleble) {..} aby
uniknąć porównywania kopi wartości w rejestarch. No i w związku z tym,
że to int dodatkowo będzie potrzebny ATOMIC (choć nie w każdym przypadku).
int *pEncoderValue; // bez volatile
int GetEncoder(void) {
int e;
ATOMIC_BLOCK(ATOMIC_FORCEON) {
e = *pEncoderValue;
}
return e;
}
kompiluje się idealnie do:
1516: f8 94 cli
1518: e0 91 3a 01 lds r30, 0x013A
151c: f0 91 3b 01 lds r31, 0x013B
1520: 80 81 ld r24, Z
1522: 91 81 ldd r25, Z+1 ; 0x01
1524: 78 94 sei
1526: 08 95 ret
Niestety w WinAVR_20071221 nie było jeszcze biblioteki atomic.h, ale
można było to uzyskać metodą podaną przez Kolegę Zbycha czyli:
asm volatile ("cli":::"memory");
int e = *pEncoderValue;
asm volatile ("sei":::"memory");
Tym bardziej, że bezpieczniejszą formą funkcji będzie:
int *pEncoderValue; // może być bez volatile
int GetEncoder(void) {
int e;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
e = *pEncoderValue;
}
return e;
}
bo nie zawsze chciałbym aby wywołanie funkcji z automatu włączało mi
przerwania.
Kiedyś robiłem to na piechotę.
// wyrzucenie zawartości portu na stos
#define push_sfr(port) \
__asm__ __volatile__ ( \
"in __tmp_reg__,%0" "\n\t" \
"push __tmp_reg__" "\n\t" \
::"I" (_SFR_IO_ADDR(port)))
// odtworzenie zawartości portu ze stosu
#define pop_sfr(port) \
__asm__ __volatile__ ( \
"pop __tmp_reg__" "\n\t" \
"out %0,__tmp_reg__" "\n\t" \
::"I" (_SFR_IO_ADDR(port)))
int GetEncoder(void) {
push_sfr(SREG); cli();
int e = *pEncoderValue;
pop_sfr(SREG);
return e;
}
i działało bez problemu... do czasu :-)
Oczywiście dla świętego spokoju na przyszłość... dam te volatile ;-)
P.S. Choroba... w WinAVR_20071221 program wynikowy zajmował 15023 bajty,
a po skompilowaniu w WinAVR_20090313 wyszło już 16154. Całe szczęście,
że to nie ATmega16 ;-)
Pozdrawiam
Grzegorz
Następne wpisy z tego wątku
- 14.06.09 10:46 Grzegorz Kurczyk
- 14.06.09 18:20 T.M.F.
- 14.06.09 18:23 T.M.F.
- 14.06.09 12:35 Zbych
- 15.06.09 02:35 T.M.F.
Najnowsze wątki z tej grupy
- Hiszpania bez pradu
- amperomierz w plusie
- 3G-nadal działa
- Historia pewnego miernika kalibratora
- Ustym 4k Pro i wyświetlacz
- Czemu rozwaliło celę?
- Wojna w portfelu
- Jaki trojfazowy licznik tuya lub podobny?
- Problem z dekoderem adresów
- Intel się wyprzedaje: po 10latach pchnęli pakiet kontrolny Altery za 1/4 kwoty zakupu
- Korekcja perspektywy
- Wentylator zabija zasilacze LEDek?
- Re: Kompensacja mocy biernej przy 230VAC
- Totaliztyczny obowiązek naprawy maszyn i urządzeń
- Niby uziom ale nie
Najnowsze wątki
- 2025-04-30 Szczecin => Key Account Manager IT <=
- 2025-04-30 Chiny => Koordynator Produkcji / Przedstawiciel ds. rozwoju produktu <
- 2025-04-30 Wrocław => Konsultant wdrożeniowy Comarch XL (Logistyka, WMS, Produk
- 2025-04-29 Nożownik zaatakował i zabił lekarza
- 2025-04-29 Polecam żarówki Blackout na Blackout z dużym gwintem
- 2025-04-29 Porażka kasty sędziowskiej przed Trybunałem Sprawiedliwości UE
- 2025-04-29 Kombinacja znaków A11 i B33?
- 2025-04-29 Na jakim etapie jest sprawa karna "gaśnicowego" Brauna z grudnia 2023?
- 2025-04-29 TSUE jest "przeciw a nawet za" neosędziami :-)
- 2025-04-29 Wrocław => Konsultant wdrożeniowy (systemy kontrolingowe) <=
- 2025-04-29 China => Production Coordinator / Representant Product Dev <=
- 2025-04-29 Warszawa => Specjalista rekrutacji IT <=
- 2025-04-28 Hiszpania bez pradu
- 2025-04-28 chinska stal
- 2025-04-28 QR kody