eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.misc.elektronika › Problem lekko OT, ale w WinAVR ;-)
Ilość wypowiedzi w tym wątku: 61

  • 51. Data: 2009-06-13 14:37:28
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: "T.M.F." <t...@n...mp.pl>

    W dniu 12.06.2009 07:27, Zbych pisze:
    > T.M.F. pisze:
    >
    >>>> Sprawdziłem to u siebie i nic takiego się nie dzieje. Musiałem
    >>>> zdefiniować dodatkowo dziwna funkcje Babla bo mi kompilator to
    >>>> optymalizował i ją wywalał.
    >>>
    >>> Ja na potrzeby przykładu w ogóle jej nie zdefiniowałem (nie jest to
    >>> potrzebne, disasemblację zrobiłem po kompilacji, bez linkowania).
    >>
    >> To wtedy petla sie totalnie zoptymalizowala i wywalilo mi te wywolania
    >> w ogole.
    >
    > Eeee, coś musiałeś skopać. Jak kompilator może zoptymalizować coś czego
    > nie widzi?

    Bo zdefiniowalem takze cialo funkcji, zeby przejsc kompilacje i linkowanie.

    --
    Inteligentny dom - http://idom.wizzard.one.pl
    http://idom.sourceforge.net/
    Teraz takze forum dyskusyjne
    Zobacz, wyslij uwagi, dolacz do projektu.


  • 52. Data: 2009-06-13 17:48:18
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: "T.M.F." <t...@n...mp.pl>

    W dniu 13.06.2009 06:10, Grzegorz Kurczyk pisze:
    > Użytkownik Zbych napisał:
    >>
    >> Dlatego napisałem, że do takich rzeczy jak sekcje atomowe są makra
    >> zdefiniowane w pliku atomic.h, a ty uparcie chcesz rzeźbić ręcznie
    >> (pomijając przy tym barierę).
    >
    > Nie, no nie chcę nic robić uparcie. Sugestie Kolegi bardzo mi pomogły,
    > za co serdecznie dziękuję. Akurat w moim przypadku wystarczyło volatile,
    > ale gdybym nie spojrzał do .lss to żyłbym w błogiej nieświadomości będąc
    > pewnym, że zablokowałem przerwania w krytycznej sekcji programu i
    > zastanawiając się dlaczego program kiksuje raz na ruski miesiąc. Tym
    > bardziej, że w poprzedniej wersji kompilatora kolejność działań była
    > taka jak w źródłówce. Z biblioteki atomic.h nie miałem jeszcze okazji
    > korzystać, ale widzę, że chyba najwyższy czas :-) Nie narzekam na
    > WinAVR, bo to niezły kompilator, ale główny problem w tym, że program,
    > który w danej wersji WinAVR bez problemu się kompilował i co
    > najważniejsze działał poprawnie, w nowszej wywala błędy kompilacji (co
    > nie jest problemem), ale co gorsza kompilacja przechodzi bezbłędnie,
    > tylko program chodzi nie do końca tak jak powinien. Z tego powodu z dużą
    > rezerwą podchodzę do nowych wersji kompilatora.
    > Problem w tym skąd mam wiedzieć (poza "brutalnym" zajrzeniem do pliku
    > .lss), w którym momencie muszę posiłkować się sztuczką typu ATOMIC_BLOCK
    > lub czymś podobnym, bo kompilator może wygenerować kod, nie do końca
    > zgodny z założeniami autora kodu źródłowego. W podanym wcześniej
    > przykładzie w jednej procedurze było źle, a w następnej już dobrze i
    > nijak nie mogę wydedukować z czego to wynika. W przypadku volatile
    > sytuacja jest jasna, ale z tym sei to kompilator zrobił mi psikusa, bo
    > jest to pierwszy taki przypadek. Przecież sekcji cli() {..} sei() używa
    > się dość często. W większych programach mam ich dużo i to jest jak na
    > razie jedyna funkcja, w której takie zjawisko mi wystąpiło (choć po tym
    > kwiatku nie jestem już tego taki pewien i dla pewności skorzystam z rady
    > Kolegi Zbycha i porobię klamerki ATOMIC_BLOK).

    To nie jest tak jak piszesz. W twoim przykladzie kompilator zachowal sie
    zupelnie poprawnie. Zauwaz, ze nie podales nigdzie, ze pEncoderValue
    jest volatile, w efekcie kompilator slusznie uznal, ze wartosc tej
    zmiennej nie moze sie zmienic nigdzie poza aktualnie kompilowana sekcja,
    a wiec miejsce gdzie nastapi przypisanie:
    int e = *pEncoderValue;
    jest zupelnie dowolne. W koncu skoro nic w miedzyczasie nie modyfikuje
    pEncoderValue to umieszczanie tego w sekcji krytycznej nie ma sensu i
    kompilator sobie zoptymalizowal to tak jak mu pasowalo. Dopiero
    okreslenie tej zmiennej jako volatile mowi kompilatorowi, ze z ta
    zmienna trzeba uwazac i nie mozna sobie dowolnie jej przekladac.
    Z kolei jesli pEncoderValue jest modyfikowane poza procedura, ktora
    pokazales np. w jakims przerwaniu to okreslenie tej zmiennej jako
    volatile jest obowiazkowe! Inaczej masz efekty takie jak pokazales. Co
    wiecej gdybys dalej cops robil z ta zmienna w swojej procedurze to
    kompilator jej pewnie ponownie by nie ladowal, czyli mialbys kolejne
    dziwne bledy. Ale to ciagle twoja wina i nie ma co zwalac na gcc.



    --
    Inteligentny dom - http://idom.wizzard.one.pl
    http://idom.sourceforge.net/
    Teraz takze forum dyskusyjne
    Zobacz, wyslij uwagi, dolacz do projektu.


  • 53. Data: 2009-06-13 22:49:03
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    Użytkownik J.F. napisał:
    >
    > Inna sprawa ze w tym miejscu to volatile powinienes z przyzwyczajenia
    > pisac :-)
    >

    W tym sęk, że tak jak pisałem wcześniej co innego było moim pierwotnym
    celem i volatile załatwiło problem niejako niechcący ;-) Przy okazji,
    jak to Kolega zauważył, nie do końca optymalnie. W zasadzie tak w 100%
    sprawę załatwia rozwiązanie zaproponowane przez Kolegę Zbycha. To jest
    to o co mi chodziło i optymalnie.
    Tak jak wspomniałem moim celem było: nie dopuścić do przerwania
    określonego fragmentu procedury przez inny wątek. To, że kompilator
    pomiędzy cli/sei skopiuje sobie wartość zmiennej do rejestrów tylko raz
    i będzie później banglał na tych rejestrach wcale mi nie przeszkadza,
    więc jakoś nie widziałem w tym momencie miejsca na volatile, bo zmienna
    w tej sekcji tak naprawdę wcale nie była ulotna.

    Pozdrawiam i życzę Miłej Niedzieli.
    Grzegorz

    --

    Że też mnie coś podkusiło powiedzieć jego ten "sęk"...
    Staropolszczyznę sie mnie zachciało... sęk, sęk...
    Tak samo mogłem powiedzieć:
    ja wiem... "tu leży pies pochowany"... ;-)


  • 54. Data: 2009-06-14 09:34:58
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    T.M.F. pisze:

    > 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.

    Nie wiem czemu twierdzisz, że dla zachowania atomowości potrzebne ci
    jest volatile. To volatile jest w tym przypadku zbędne.

    --
    przeciez moje rozumowanie bylo bez skazy,
    no sam bym wskoczyl do tego wulkanu,
    ale kto by tak pieknie gwizdal...


  • 55. Data: 2009-06-14 10:23:08
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    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


  • 56. Data: 2009-06-14 10:46:15
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    Użytkownik Grzegorz Kurczyk napisał:
    > Tym bardziej, że bezpieczniejszą formą funkcji będzie:

    Errata. Miało być:
    Bezpieczniejszą formą funkcji będzie:


  • 57. Data: 2009-06-14 12:35:53
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    T.M.F. pisze:

    >> Nie wiem czemu twierdzisz, że dla zachowania atomowości potrzebne ci
    >> jest volatile. To volatile jest w tym przypadku zbędne.
    >
    > Dlatego jest potrzebne, zeby kompilator zdawal sobie sprawe, ze nie jest
    > to zwykla zmienna i nie robil takich kwiatkow jak na przykladzie.

    Ale ty pisałeś, że jest to potrzebne do zachowania atomowości. A to nie
    jest prawda.

    --
    przeciez moje rozumowanie bylo bez skazy,
    no sam bym wskoczyl do tego wulkanu,
    ale kto by tak pieknie gwizdal...


  • 58. Data: 2009-06-14 14:51:02
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: "T.M.F." <t...@n...mp.pl>

    > Tak jak wspomniałem moim celem było: nie dopuścić do przerwania
    > określonego fragmentu procedury przez inny wątek. To, że kompilator
    > pomiędzy cli/sei skopiuje sobie wartość zmiennej do rejestrów tylko raz
    > i będzie później banglał na tych rejestrach wcale mi nie przeszkadza,
    > więc jakoś nie widziałem w tym momencie miejsca na volatile, bo zmienna
    > w tej sekcji tak naprawdę wcale nie była ulotna.

    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. 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.
    Zobacz tu:
    http://www.nongnu.org/avr-libc/user-manual/group__ut
    il__atomic.html
    wraz z wyjasnieniem i przykladami - powinno sie przydac.

    --
    Inteligentny dom - http://idom.wizzard.one.pl
    http://idom.sourceforge.net/
    Teraz takze forum dyskusyjne
    Zobacz, wyslij uwagi, dolacz do projektu.


  • 59. Data: 2009-06-14 18:20:34
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: "T.M.F." <t...@n...mp.pl>

    >> 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.

    Teoretycznie tak. Problem w tym, ze skad kompilator ma wiedziec, ze
    wartosc zmiennej moze sie zmieniac poza glownym ciagiem instrukcji? Do
    tego wlasnie sluzy volatile. Bez tego kompilator nic nie wie, ze cos
    moze zmienic twoja zmienna np. w przerwaniu, w efekcie optymalizuje to
    sobie jak uwaza za stosowne i z tego punktu widzenia umiejscowienie cli
    w stosunu do pobrania zmiennej jest bez znaczenia.

    > 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 ;-)

    Zapewne problem z bardziej agresywnym inlinowaniem funkcji. Mozna to
    wylaczyc.

    --
    Inteligentny dom - http://idom.wizzard.one.pl
    http://idom.sourceforge.net/
    Teraz takze forum dyskusyjne
    Zobacz, wyslij uwagi, dolacz do projektu.


  • 60. Data: 2009-06-14 18:23:06
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: "T.M.F." <t...@n...mp.pl>

    >> 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.
    >
    > Nie wiem czemu twierdzisz, że dla zachowania atomowości potrzebne ci
    > jest volatile. To volatile jest w tym przypadku zbędne.

    Dlatego jest potrzebne, zeby kompilator zdawal sobie sprawe, ze nie jest
    to zwykla zmienna i nie robil takich kwiatkow jak na przykladzie. To
    oczywiscie z atomowoscia nie ma nic wspolnego, ale lacznie generuje
    poprawny kod. Ogolna zasada mowi, ze kazda zmienna uzywana w przerwaniu
    i programie glownym powinna byc volatile. W szczegolnych przypadkach nie
    musi byc, ale nalezy sobie zdawac sprawe z konsekwencji.

    --
    Inteligentny dom - http://idom.wizzard.one.pl
    http://idom.sourceforge.net/
    Teraz takze forum dyskusyjne
    Zobacz, wyslij uwagi, dolacz do projektu.

strony : 1 ... 5 . [ 6 ] . 7


Szukaj w grupach

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: