-
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
- 8080
- Portowanie CP/M
- radyjko
- Re: Basen i chłodzenie w w wentylacji mechanicznej
- Akumulatory VRLA
- ładowarka zmarła
- Podstawa bezpiecznikowa jako rozłącznik DC
- Napięcie akumulatora wyłączające UPS / jakie nowe akumulatory do UPS?
- nawigacja satelitarna
- SmartLife/Tuya i osuszanie -- mordowanie z zimną krwią...
- Głośnik piezoelektryczny
- Mala autonomiczna kamera monitoringu
- czas na emeryturę i EB
- Generowanie sumy kontrolnej z fragmentu pliku bin
- Re: Mala autonomiczna kamera monitoringu
Najnowsze wątki
- 2024-07-13 256 świadków nie ma racji
- 2024-07-11 Tokarze CNC czyli ciężkie życie prototypiarza
- 2024-07-12 Zgody na przetwarzanie danych
- 2024-07-13 IObit Uninstaller Pro 13.6.0.5 Multilingual: Installation Guide
- 2024-07-12 stare graty młode kozy
- 2024-07-11 8080
- 2024-07-13 Przyłącze dolne grzejnika
- 2024-07-13 IObit Uninstaller Pro 13.6.0.5 Multilingual Overview
- 2024-07-12 Czym wykonać otwór fi 100 w betonie komórkowym?
- 2024-07-12 Warszawa => Senior Rust Software Engineer <=
- 2024-07-12 Warszawa => Business Unit Manager (Recruitment Business) <=
- 2024-07-12 Warszawa => Head of WMS Competence Center for IT&D Contract Logistics
- 2024-07-12 Warszawa => Head od WMS Competence Center dla IT&D (Blue Yonder) <=
- 2024-07-12 Kraków => Ruby Backend Developer <=
- 2024-07-12 Warszawa => UX/UI Designer <=