eGospodarka.pl
eGospodarka.pl poleca

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

  • 31. Data: 2009-06-12 20:15:03
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    Chyba kolejny mały kwiatek.

    int GetEncoder(void) {
    cli();
    int e = *pEncoderValue;
    sei();
    return e;
    }

    zostało przetłumaczone na:

    int GetEncoder(void) {
    cli();
    1476: f8 94 cli
    int e = *pEncoderValue;
    sei();
    1478: 78 94 sei
    147a: e0 91 3a 01 lds r30, 0x013A
    147e: f0 91 3b 01 lds r31, 0x013B
    return e;
    }
    1482: 80 81 ld r24, Z
    1484: 91 81 ldd r25, Z+1 ; 0x01
    1486: 08 95 ret

    Nie wiem czemu kompilator wywalił pobieranie zmiennej poza sekcję
    cli/sei ? To samo jest w najnowszej wersji.

    Moim skromnym zdaniem powinno być tak:

    int GetEncoder(void) {
    f8 94 cli
    e0 91 3a 01 lds r30, 0x013A
    f0 91 3b 01 lds r31, 0x013B
    80 81 ld r24, Z
    91 81 ldd r25, Z+1 ; 0x01
    78 94 sei
    08 95 ret

    lub tak:

    int GetEncoder(void) {
    e0 91 3a 01 lds r30, 0x013A
    f0 91 3b 01 lds r31, 0x013B
    f8 94 cli
    80 81 ld r24, Z
    91 81 ldd r25, Z+1 ; 0x01
    78 94 sei
    08 95 ret


    Pozdrawiam
    Grzegorz


  • 32. Data: 2009-06-12 20:30:09
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: J.F. <j...@p...onet.pl>

    On Fri, 12 Jun 2009 22:15:03 +0200, Grzegorz Kurczyk wrote:
    >Chyba kolejny mały kwiatek.
    >int GetEncoder(void) {
    > cli();
    > int e = *pEncoderValue;
    > sei();
    > return e;
    >}

    A cos tu jest volatile ?
    Bo moze mial prawo, jesli uwaza ze tak mu wygodniej ..


    >
    >zostało przetłumaczone na:
    >
    >int GetEncoder(void) {
    > cli();
    > 1476: f8 94 cli
    > int e = *pEncoderValue;
    > sei();
    > 1478: 78 94 sei
    > 147a: e0 91 3a 01 lds r30, 0x013A
    > 147e: f0 91 3b 01 lds r31, 0x013B
    > return e;
    >}
    > 1482: 80 81 ld r24, Z
    > 1484: 91 81 ldd r25, Z+1 ; 0x01
    > 1486: 08 95 ret
    >
    >Nie wiem czemu kompilator wywalił pobieranie zmiennej poza sekcję
    >cli/sei ? To samo jest w najnowszej wersji.
    >
    >Moim skromnym zdaniem powinno być tak:
    >
    >int GetEncoder(void) {
    >f8 94 cli
    >e0 91 3a 01 lds r30, 0x013A
    >f0 91 3b 01 lds r31, 0x013B
    >80 81 ld r24, Z
    >91 81 ldd r25, Z+1 ; 0x01
    >78 94 sei
    >08 95 ret
    >
    >lub tak:
    >
    >int GetEncoder(void) {
    >e0 91 3a 01 lds r30, 0x013A
    >f0 91 3b 01 lds r31, 0x013B
    >f8 94 cli
    >80 81 ld r24, Z
    >91 81 ldd r25, Z+1 ; 0x01
    >78 94 sei
    >08 95 ret
    >
    >
    >Pozdrawiam
    >Grzegorz


  • 33. Data: 2009-06-12 20:30:19
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    Grzegorz Kurczyk pisze:

    > Nie wiem czemu kompilator wywalił pobieranie zmiennej poza sekcję
    > cli/sei ? To samo jest w najnowszej wersji.

    Tutaj akurat kompilator ma rację - może przestawiać instrukcje do woli
    póki nie wpływa to na wynik obliczeń (ani cli, ani sei nie wpływa na
    obliczenia, atomowość nie jest brana pod uwagę). Żeby kompilator nie
    wywlekał obliczeń poza sekcję krytyczną trzeba zrobić barierę na
    pamięci. Twój program powinien wyglądać tak:

    int GetEncoder(void) {
    asm volatile ("cli":::"memory");
    int e = *pEncoderValue;
    asm volatile ("sei":::"memory");
    return e;
    }

    Lepiej będzie jednak jak użyjesz makr zdefiniowanych w pliku atomic.h

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


  • 34. Data: 2009-06-13 01:35:54
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Grzegorz Kurczyk <g...@c...slupsk.pl>

    Użytkownik Zbych napisał:
    > Tutaj akurat kompilator ma rację - może przestawiać instrukcje do woli
    > póki nie wpływa to na wynik obliczeń (ani cli, ani sei nie wpływa na
    > obliczenia, atomowość nie jest brana pod uwagę). Żeby kompilator nie
    > wywlekał obliczeń poza sekcję krytyczną trzeba zrobić barierę na
    > pamięci. Twój program powinien wyglądać tak:
    >
    > int GetEncoder(void) {
    > asm volatile ("cli":::"memory");
    > int e = *pEncoderValue;
    > asm volatile ("sei":::"memory");
    > return e;
    > }
    >
    > Lepiej będzie jednak jak użyjesz makr zdefiniowanych w pliku atomic.h
    >

    Pamiętam, że jakaś starsza wersja (chyba z 2006) kompilowała to bez
    przestawiania. Funkcja jest z biblioteki, którą napisałem dawno temu i
    sprawdzałem kod wynikowy. W wersji WinAVR20090313 faktycznie pomogło
    volatile przy definicji wskaźnika int *pEncoderValue. Zaskoczyło mnie,
    że volatile może być tu przydatne, bo jednak bardziej służy ono do
    lokalnego wyłączenia optymalizacji dotyczącej danej zmiennej, a nie do
    zmiany kolejności operacji nie mających nic wspólnego z tą zmienną.
    Z punktu widzenia zmiennej *pEncoderValue kod jest tak samo optymalny, a
    niemalże identyczny:

    int *pEncoderValue;
    daje w wyniku:
    int GetEncoder(void) {
    151c: f8 94 cli
    151e: 78 94 sei
    1520: e0 91 3a 01 lds r30, 0x013A
    1524: f0 91 3b 01 lds r31, 0x013B
    1528: 80 81 ld r24, Z
    152a: 91 81 ldd r25, Z+1 ; 0x01
    152c: 08 95 ret
    }

    volatile int *pEncoderValue;
    daje
    int GetEncoder(void) {
    1520: f8 94 cli
    1522: e0 91 3a 01 lds r30, 0x013A
    1526: f0 91 3b 01 lds r31, 0x013B
    152a: 20 81 ld r18, Z
    152c: 31 81 ldd r19, Z+1 ; 0x01
    152e: 78 94 sei
    1530: c9 01 movw r24, r18
    1532: 08 95 ret

    Z drugiej strony taka zmiana sekwencji rozkazów sterujących przez
    kompilator wydaje mi się trochę dziwna, bo w pewnych sytuacjach ma ona
    wpływ na wartość obliczeń (właśnie aby tego uniknąć blokowałem
    przerwania). Idąc tym tropem kompilator mógłby "dojść do wniosku", że
    sekwencję:
    sbi(PORTB, 1);
    sbi(PORTB, 2);
    sbi(PORTB, 3);
    można zamienić na:
    sbi(PORTB, 3);
    sbi(PORTB, 2);
    sbi(PORTB, 1);
    lub jeszcze optymalniej (3 takty zegara zamiast 6) na:
    in r24, PORTB
    ori r24, 0x0E
    out PORTB, r24
    bo w sumie efekt końcowy (całkowity wynik operacji) jest ten sam:
    wyjścia 1,2 i 3 portu B zostały ustawione w stan wysoki. Tyle, że jeśli
    te linie są sygnałami CS/CLK/DATA dla jakiegoś rejestru szeregowego, to
    już reszta układu tak samo działać nie będzie. Na szczęście nigdy nie
    zauważyłem aby robił takie podmianki :-)


    Dzięki serdeczne za podpowiedź.
    Pozdrawiam
    Grzegorz


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

    A teraz coś czego już zupełnie nie rozumiem:

    int *pEncoderValue; // celowo bez volatile

    int GetEncoder(void) {
    cli();
    int e = *pEncoderValue;
    sei();
    return e;
    }

    void SetEncoderValue(int Value) {
    cli();
    *pEncoderValue = Value;
    sei();
    }

    kompiluje się na:

    int GetEncoder(void) {
    151c: f8 94 cli
    151e: 78 94 sei
    1520: e0 91 3a 01 lds r30, 0x013A
    1524: f0 91 3b 01 lds r31, 0x013B
    1528: 80 81 ld r24, Z
    152a: 91 81 ldd r25, Z+1 ; 0x01
    152c: 08 95 ret
    }
    void SetEncoderValue(int Value) {
    152e: f8 94 cli
    1530: e0 91 3a 01 lds r30, 0x013A
    1534: f0 91 3b 01 lds r31, 0x013B
    1538: 91 83 std Z+1, r25 ; 0x01
    153a: 80 83 st Z, r24
    153c: 78 94 sei
    153e: 08 95 ret
    }

    Na jakiej podstawie kompilator (najnowszy WinAVR_20090313) stwierdził,
    że w pierwszej funkcji kolejność operacji nie ma znaczenia, a w drugiej
    już ma ? Bug czy tzw. "feature" ;-)

    Jednak trzeba do tego pliku .lss regularnie zaglądać, bo można się mocno
    zdziwić przy uruchamianiu maszynki... ;-) Takie przestawienie rozkazu
    sei w funkcji może być wyjątkowo upierdliwe, bo niby wszystko jest ok i
    program może całymi dniami działać dobrze i nagle funkcja jednorazowo
    oddaje nieprawidłową wartość, aby potem znowu długo wszystko było ok.

    Pozdrawiam
    Grzegorz


  • 36. Data: 2009-06-13 07:28:30
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    Grzegorz Kurczyk pisze:

    > Jednak trzeba do tego pliku .lss regularnie zaglądać, bo można się mocno
    > zdziwić przy uruchamianiu maszynki... ;-) Takie przestawienie rozkazu
    > sei w funkcji może być wyjątkowo upierdliwe, bo niby wszystko jest ok i
    > program może całymi dniami działać dobrze i nagle funkcja jednorazowo
    > oddaje nieprawidłową wartość, aby potem znowu długo wszystko było ok.

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

    Zrób to tak:

    #include <util/atomic.h>

    ATOMIC_BLOCK(ATOMIC_FORCEON)
    {
    int e = *pEncoderValue;
    }

    Albo bezpieczniej:

    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
    int e = *pEncoderValue;
    }

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


  • 37. Data: 2009-06-13 07:44:28
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: J.F. <j...@p...onet.pl>

    On Sat, 13 Jun 2009 03:35:54 +0200, Grzegorz Kurczyk wrote:
    >Pamiętam, że jakaś starsza wersja (chyba z 2006) kompilowała to bez
    >przestawiania. Funkcja jest z biblioteki, którą napisałem dawno temu i
    >sprawdzałem kod wynikowy. W wersji WinAVR20090313 faktycznie pomogło
    >volatile przy definicji wskaźnika int *pEncoderValue. Zaskoczyło mnie,
    >że volatile może być tu przydatne, bo jednak bardziej służy ono do
    >lokalnego wyłączenia optymalizacji dotyczącej danej zmiennej, a nie do
    >zmiany kolejności operacji nie mających nic wspólnego z tą zmienną.

    Volatile nie sluzy do optymalizowania, tylko mowi kompilatorowi ze
    zmienna moze sie zmienic w dowolnym momencie. W zwiazku z czym nie
    wolno mu optymalizowac kodu zakladajac ze sie nie zmienia.

    Bo jak zalozyc ze nie zmienia sie w przerwaniach/samoczynnie, to
    kompilator moze przeprowadzic bardzo gleboka optymalizacje - np
    zalozyc ze zmienna jest zawsze 0 i zlikwidowac caly program.

    >Z drugiej strony taka zmiana sekwencji rozkazów sterujących przez
    >kompilator wydaje mi się trochę dziwna, bo w pewnych sytuacjach ma ona
    >wpływ na wartość obliczeń

    Programisci sa przed tym wyraznie ostrzegani, ze program moze to
    zrobic, i maja stosownie pisac program.
    Albo rybki albo akwarium - albo efektywny program, albo robiacy
    dokladnie to co programista zapisal :-)

    >(właśnie aby tego uniknąć blokowałem
    >przerwania). Idąc tym tropem kompilator mógłby "dojść do wniosku", że
    >sekwencję:
    >sbi(PORTB, 1);
    >sbi(PORTB, 2);
    >sbi(PORTB, 3);
    >można zamienić na:
    >sbi(PORTB, 3);
    >sbi(PORTB, 2);
    >sbi(PORTB, 1);

    Tak to nie, bo to jednak i operacja specjalna i taka "wyjsciowa",
    ale juz kolejnosc odczytow z portow moglby przestawic.

    J.


  • 38. Data: 2009-06-13 10:10:04
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    T.M.F. pisze:

    > Skad masz makra sei() i cli()? To twoja wlasna definicja czy z
    > biblioteki avr-glibc - pliku interrupts.h?
    > Zakladam, ze twoja wlasna, stad problemy. Oryginalna prawidlowa
    > definicja wyglada tak:
    > #define sei() __asm__ __volatile__ ("sei" ::)
    >
    > Zwroc uwage na slowo volatile. Swoja droga przeczytaj jak volatile
    > dziala to rozwiaze sie wiele twoich dziwnych klopotow.

    Volatile w tym przypadku zabezpiecza tylko przed usunięciem i zamianą
    miejscami instrukcji "cli" i "sei" a nie tego co jest pomiędzy nimi.


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


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

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


    Pozdrawiam i dziękuję za udział w dyskusji.
    Grzegorz


  • 40. Data: 2009-06-13 10:18:13
    Temat: Re: Problem lekko OT, ale w WinAVR ;-)
    Od: Zbych <a...@o...pl>

    Grzegorz Kurczyk pisze:

    > nie jest problemem), ale co gorsza kompilacja przechodzi bezbłędnie,
    > tylko program chodzi nie do końca tak jak powinien.

    Ja mam na to jeden sposób, porównuję pliki lss z dwóch kolejnych wersji
    kompilatora. Jeśli zmian jest niewiele, to jest to szybsza metoda niż
    rozpoczynanie od nowa testów programu.

    > 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

    Powinieneś użyć jej wszędzie tam gdzie do tej pory miałeś

    cli();
    [...]
    sei();



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

strony : 1 ... 3 . [ 4 ] . 5 ... 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: