-
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
- pradnica krokowa
- Nieustający podziw...
- Coś dusi.
- akumulator napięcie 12.0v
- Podłączenie DMA 8257 do 8085
- pozew za naprawę sprzętu na youtube
- gasik
- Zbieranie danych przez www
- reverse engineering i dodawanie elementów do istniejących zamkniętych produktów- legalne?
- Problem z odczytem karty CF
- 74F vs 74HCT
- Newag ciąg dalszy
- Digikey, SN74CBT3253CD, FST3253, ktoś ma?
- Szukam: czujnik ruchu z możliwością zaączenia na stałe
- kabelek - kynar ?
Najnowsze wątki
- 2025-01-20 huta ruszyla
- 2025-01-20 piece wodorowe
- 2025-01-20 Lublin => Programista Delphi <=
- 2025-01-20 Warszawa => Architekt rozwiązań (doświadczenie w obszarze Java, AWS
- 2025-01-20 Mińsk Mazowiecki => Area Sales Manager OZE <=
- 2025-01-20 Bieruń => Spedytor Międzynarodowy (handel ładunkami/prowadzenie flo
- 2025-01-19 Test - nie czytać
- 2025-01-19 qqqq
- 2025-01-19 Tauron przysyła aneks
- 2025-01-19 Nowa ładowarka Moya a Twizy -)
- 2025-01-18 Power BANK z ładowaniem przelotowym robi PRZERWY
- 2025-01-18 Pomoc dla Filipa ;)
- 2025-01-18 znowu kradno i sie nie dzielo
- 2025-01-18 Zieloni oszuchiści
- 2025-01-18 Zielonka => Specjalista ds. public relations <=