eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronikaProblem lekko OT, ale w WinAVR ;-) › Re: Problem lekko OT, ale w WinAVR ;-)
  • Path: news-archive.icm.edu.pl!newsfeed.gazeta.pl!news.onet.pl!newsfeed.neostrada.pl!a
    tlantis.news.neostrada.pl!news.neostrada.pl!not-for-mail
    From: Grzegorz Kurczyk <g...@c...slupsk.pl>
    Newsgroups: pl.misc.elektronika
    Subject: Re: Problem lekko OT, ale w WinAVR ;-)
    Date: Sun, 14 Jun 2009 12:23:08 +0200
    Organization: TP - http://www.tp.pl/
    Lines: 108
    Message-ID: <h12j6a$hve$1@atlantis.news.neostrada.pl>
    References: <h0qku7$a6o$1@atlantis.news.neostrada.pl>
    <h0ud45$219$1@atlantis.news.neostrada.pl> <h0udur$2j2d$1@news.mm.pl>
    <h0v0bq$jmg$1@nemesis.news.neostrada.pl>
    <h0vhtr$i32$1@atlantis.news.neostrada.pl>
    <h0voto$eke$1@nemesis.news.neostrada.pl>
    <h0vvnn$q5t$1@nemesis.news.neostrada.pl>
    <8...@4...com>
    <h101gv$s44$1@nemesis.news.neostrada.pl>
    <7...@4...com>
    <h103jc$1c4$1@nemesis.news.neostrada.pl>
    <6...@4...com>
    <h11av0$ivi$1@nemesis.news.neostrada.pl>
    <h12dpj$5vq$1@atlantis.news.neostrada.pl>
    NNTP-Posting-Host: control.slupsk.pl
    Mime-Version: 1.0
    Content-Type: text/plain; charset=ISO-8859-2; format=flowed
    Content-Transfer-Encoding: 8bit
    X-Trace: atlantis.news.neostrada.pl 1244975116 18414 80.52.170.66 (14 Jun 2009
    10:25:16 GMT)
    X-Complaints-To: u...@n...neostrada.pl
    NNTP-Posting-Date: Sun, 14 Jun 2009 10:25:16 +0000 (UTC)
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; PL; rv:1.8.1.21) Gecko/20090403
    SeaMonkey/1.1.16
    In-Reply-To: <h12dpj$5vq$1@atlantis.news.neostrada.pl>
    X-Antivirus: avast! (VPS 090613-0, 2009-06-13), Outbound message
    X-Antivirus-Status: Clean
    Xref: news-archive.icm.edu.pl pl.misc.elektronika:565383
    [ ukryj 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

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: