logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Zmienne globalne wykorzystywane przez przerwania i inne.

kamil3211 29 Mar 2021 12:03 2943 47
Najlepsze odpowiedzi

Czy odczyt globalnej zmiennej w przerwaniu na AVR może dać błędną wartość i kiedy potrzebuję volatile albo blokady przerwań?

Jeśli w przerwaniu tylko odczytujesz 8-bitową zmienną na AVR, zobaczysz albo starą, albo nową, spójną wartość; „losowy” wynik pojawia się przy operacjach wielobajtowych albo gdy ta sama zmienna jest modyfikowana z obu stron [#19348310] [#19349797] Dla `int` 16-bitowego na AVR może dojść do odczytu „połówki starej i połówki nowej” wartości, bo aktualizacja odbywa się bajt po bajcie, więc przerwanie może wejść w środku operacji [#19348290] `volatile` wymusza ponowny odczyt/zapis zmiennej przez kompilator, ale nie zapewnia atomowości ani nie chroni przed przerwaniem w trakcie odczytu/zapisu [#19351204] [#19351337] Dlatego `volatile` stosuje się, gdy zmienna jest używana w ISR i w kodzie głównym, ale przy modyfikacji wielobajtowej lub operacjach typu `++` trzeba wyłączyć odpowiednie przerwanie albo użyć `atomic.h`/`ATOMIC_BLOCK` [#19348334] [#19348330] [#19348307] Przy samym odczycie z ISR i bez modyfikacji w ISR problem zwykle sprowadza się do tego, że zobaczysz poprzednią wartość, a nie „śmieci” [#19348482]
Wygenerowane przez model językowy.
REKLAMA
  • #1 19348266
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    Cześć.
    Na stronie o przerwaniach zewnętrznych http://akademia.nettigo.pl/arduino_przerwania/
    jest napisane coś takiego
    "Zwróć uwagę na problem komunikacji w drugą stronę. Jeżeli program w loop miałby zmieniać wartość zmiennych używanych przez funkcję obsługującą przerwania, to warto zapewnić by przerwanie nie zaskoczyło programu w momencie modyfikacji zmiennej. Jeżeli jest to operacja złożona z więcej niż jednej komendy kodu maszynowego procesora, może się zdarzyć, że przerwanie zostanie wywołane "pośrodku" i jako rezultat stan zmiennej będzie błędny."

    Ale z operacjami atomowymi już z czymś podobnym się spotkałem w javie
    https://www.samouczekprogramisty.pl/watki-w-jezyku-java/

    tu piszą
    "Tutaj należy Ci się kolejne wyjaśnienie. Operacja atomowa to taka operacja, która jest niepodzielna. Operacja atomowa realizowana jest przy pomocy jednej instrukcji w bytecode (w skompilowanej klasie). Operacja value += 1 nie jest operacją atomową, jest ona równoważna z value = value + 1. Wykonanie tej operacji składa się z kilku kroków:
    a)pobrania aktualnej wartości value do zmiennej tymczasowej (niewidocznej w kodzie źródłowym)5,
    b)dodania 1 do zmiennej tymczasowej,
    c)przypisanie powiększonej wartości do value."

    Zastanawiam czy czy ta zmienna w przerwaniu będzie błędna w sensie, że np zamiast 1 będzie 99992323 czy w takim sensie błędna że nie aktualna(volatile nie pomoże w tym przypadku).(w przerwaniu tylko odczyta się zmienną globalną).

    Celowo podaję że zmienna w przerwaniu nie jest modyfikowana bo jak by chyba wystąpi chyba to samo zjawisko opisane na stronie o javie.?
  • REKLAMA
  • #2 19348290
    JacekCz
    Poziom 42  
    Posty: 8670
    Pomógł: 760
    Ocena: 1461
    Np w trakcie aktualizacji int >=16 bitów na AVR, pomiędzy jednym a drugim bajtem wskoczy przerwanie.
    Przerwanie zobaczy zmienną pól słowa starszego, pól nowego. Obie polówki <w jakimś sensie> sensowne, tzn dające się uzasadnić - nie jest to wartośc randomowa - ale realnie bezsensowna

    Przyjmijmy, ze aktualizacja jest z 0x1234 na 0x789A.
    Przerwanie zobaczy 0x129A (ewentualnie 0x7834)

    Dodano po 5 [minuty]:

    prawdziwa tragedia się zaczyna, jak procedura przerwania też chce aktualizować

    Błędy są tym bardziej bolesne, bo rzadkie. One nie wyjdą na przypadkowych, nawet dość obszernych testach, tylko na "produkcji"
  • #3 19348302
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    JacekCz napisał:
    Np w trakcie aktualizacji int >=16 bitów na AVR, pomiędzy jednym a drugim bajtem wskoczy przerwanie.
    Przerwanie zobaczy zmienną pól słowa starszego, pól nowego. Obie polówki <w jakimś sensie> sensowne, tzn dające się uzasadnić - nie jest to wartośc randomowa - ale realnie bezsensowna

    A w przypadku kiedy używam zmiennej byte 8 bitowej jak procesor 8 bitowy AVR ? to tu nie zajdzie to co powyżej napisałeś?
  • REKLAMA
  • #4 19348307
    krzysiek_krm
    Poziom 40  
    Posty: 4612
    Pomógł: 716
    Ocena: 598
    A nie lepiej na czas modyfikacji zmiennej wyłączyć na moment odpowiednie przerwanie ?
  • #5 19348310
    JacekCz
    Poziom 42  
    Posty: 8670
    Pomógł: 760
    Ocena: 1461
    kamil3211 napisał:

    A w przypadku kiedy używam zmiennej byte 8 bitowej jak procesor 8 bitowy AVR ? to tu nie zajdzie to co powyżej napisałeś?


    jednosttronna aktualizcja takiej zmiennej jest bezpieczna *) - przerwanie widzi stary lub nowy stan, ale spójny.
    Dwustronna nadal nie.


    *) jakbyś dłużej romansował z ekosystemem Javy, zauważysz, że programiści bardzo cenią klasy niezmiennicze, immutable. Bezpieczeństwo przy wątkach, to jeden z istotnych powodów.
  • REKLAMA
  • #6 19348317
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    krzysiek_krm napisał:
    A nie lepiej na czas modyfikacji zmiennej wyłączyć na moment odpowiednie przerwanie ?
    Faktycznie.
    Ale jeśli będzie jak ze zmienną 8 bitową na 8 bit procesorze to będę wiedział, że nie trzeba. i trochę mniej mocy zmarnuję.
  • #7 19348327
    Konto nie istnieje
    Poziom 1  
  • #8 19348330
    JacekCz
    Poziom 42  
    Posty: 8670
    Pomógł: 760
    Ocena: 1461
    krzysiek_krm napisał:
    A nie lepiej na czas modyfikacji zmiennej wyłączyć na moment odpowiednie przerwanie ?


    Tak.
    To jest węższy sposób z szerszej grupy "synchronizacja".

    W bardziej złożonym systemie ciężko będzie wskazać to jedno przerwanie, o które chodzi
  • REKLAMA
  • #10 19348371
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    Nie zastanawiać się i zawsze wstawiać atomic block? Etam...
    Można sobie wyobrazić funkcję zabezpieczoną blokiem z atrybutem RESTORE, która jest wyoływana zarówno w mainie jak i przerwaniu. I co? Można sobie zrobić kuku, nieprawdaż?
  • #11 19348387
    excray
    Poziom 41  
    Posty: 5500
    Pomógł: 739
    Ocena: 656
    ex-or napisał:
    Można sobie wyobrazić funkcję zabezpieczoną blokiem z atrybutem RESTORE

    I co ma się niby stać? Bo jakoś nie widzę tutaj żadnego "kuku".
  • #12 19348406
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    khoam napisał:
    Może wystąpić problem, jeżeli zmienna 8-bitowa będzie tymczasowo przechowywana w rejestrze MCU, a nie w pamięci. W tym wypadku akurat pomaga specyfikator volatile na taką okoliczność.

    Czy mógłbyś ten problem bardziej opisać bo ja myślę że jedyny to taki że jest większa szansa że zmienna będzie nie aktualna.
  • #13 19348425
    Konto nie istnieje
    Poziom 1  
  • #14 19348445
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    excray napisał:
    I co ma się niby stać?
    Przedwczesne odblokowanie przerwań.
  • #15 19348457
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    Tu kiedy zmienna globalna jest NIE volatile to tylko nie aktualna zmienna może się zdarzyć ? kiedy akurat trafi się pomiędzy operacje atomowe przypisania w pętli loop ? Wcześniej złe wysłałem.
    te liczba++; widzę tak:

    1. pobranie liczba do zmiennej tymczasowej.
    2. w zmiennej tymczasowej dodanie 1
    3. przypisanie do liczba;
    a przerwanie wykona się pomiędzy 2 i 3

    oczywiście celowo zrobiłem nie volatile ale zawsze z przerwaniami ją daję . Może te kroki wyglądają inaczej ?
    Załączniki:
    • Zmienne globalne wykorzystywane przez przerwania i inne. wazne.PNG (8.71 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #16 19348476
    excray
    Poziom 41  
    Posty: 5500
    Pomógł: 739
    Ocena: 656
    ex-or napisał:
    Przedwczesne odblokowanie przerwań.

    To najwyraźniej nie rozumiesz do końca tego, jak działa parametr ATOMIC_RESTORESTATE.
  • #17 19348482
    Konto nie istnieje
    Poziom 1  
  • #18 19348495
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    Chyba jak Pan pisał to ja zmodyfikowałem zdjęcie bo złe dałem. A Pan myślał o tym przypisaniu 0 lub 1 ze starego.
  • #19 19348503
    Konto nie istnieje
    Poziom 1  
  • #20 19348504
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    Skąd pan to wie ? a co by było gdyby +=2; ?
  • #21 19348523
    ex-or
    Poziom 28  
    Posty: 785
    Pomógł: 147
    Ocena: 151
    excray napisał:
    jak działa parametr ATOMIC_RESTORESTATE

    No dobra, niech będzie, ze palnąłem głupstwo. Odblokowanie nastąpi przy FORCEON.
    Co nie zmienia faktu, że brak namysłu nad tym co się robi jest...zresztą nieważne.
  • #22 19348527
    Konto nie istnieje
    Poziom 1  
  • #23 19348536
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    Nie da się jakoś podglądnąć tego co wypluje kompilator??? ja podglądnąłem coś takiego z pliku z rozszerzeniem hex (to tylko część) ale to nie po ludzku
    :100000000C9435000C9455020C942E020C945D0057
    :100010000C945D000C945D000C945D000C945D00EC
    :100020000C945D000C945D000C945D000C945D00DC
    :100030000C945D000C945D000C945D000C945D00CC
    :100040000C94E4010C945D000C94B2010C948C01AE
    :100050000C945D000C945D000C945D000C945D00AC
    :100060000C945D000C945D00070311241FBECFEFBC
    :10007000D8E0DEBFCDBF11E0A0E0B1E0E8E7F6E0F8
    :1000800002C005900D92A631B107D9F721E0A6E193
    :10009000B1E001C01D92AD3BB207E1F710E0C5E34E
    :1000A000D0E004C02197FE010E943403C433D1077D
    :1000B000C9F70E947C020C943A030C940000089546
    :1000C000AF92BF92CF92DF92EF92FF920F931F9366
    :1000D000CF93DF936C017B018B01040F151FEB01A4
    :1000E0005E01AE18BF08C017D10759F06991D6015B
  • #24 19348541
    krzysiek_krm
    Poziom 40  
    Posty: 4612
    Pomógł: 716
    Ocena: 598
    kamil3211 napisał:
    Nie da się jakoś podglądnąć tego co wypluje kompilator??? ja podglądnąłem coś takiego z pliku z rozszerzeniem hex (to tylko część) ale to nie po ludzku

    Powinien być jakiś "asm".
  • #25 19348544
    Konto nie istnieje
    Poziom 1  
  • #26 19348565
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    Znalazłem było ale pod rozszerzeniem .lst jakiś NASM Listing
    to fragment z loop ale więcej tego było
    void loop()
    {
    liczba++;
    1b8: 80 91 09 01 lds r24, 0x0109 ; 0x800109 <liczba>
    1bc: 8f 5f subi r24, 0xFF ; 255
    1be: 80 93 09 01 sts 0x0109, r24 ; 0x800109 <liczba>
    delay():
    #endif // 0
    }

    zrobiłem to dla programu takiego

    byte liczba;
    void setup()
    {}
    void loop()
    {
    liczba++;
    delay(5000);
    }

    a kiedy byte zmieniłem na int(16bit) to coś takiego
    void loop()
    {
    liczba++;
    1b8: 80 91 09 01 lds r24, 0x0109 ; 0x800109 <liczba>
    1bc: 90 91 0a 01 lds r25, 0x010A ; 0x80010a <liczba+0x1>
    1c0: 01 96 adiw r24, 0x01 ; 1
    1c2: 90 93 0a 01 sts 0x010A, r25 ; 0x80010a <liczba+0x1>
    1c6: 80 93 09 01 sts 0x0109, r24 ; 0x800109 <liczba>
    delay():
    #endif // 0
    }
  • #27 19348665
    Janusz_kk
    Poziom 39  
    Posty: 5741
    Pomógł: 219
    Ocena: 1441
    No a gdzie przerwanie?
  • #28 19348676
    kamil3211
    Poziom 10  
    Posty: 474
    Ocena: 57
    usunąłem chciałem zobaczyć ile operacji atomowych generuje inkrementacja.
  • #29 19349177
    JacekCz
    Poziom 42  
    Posty: 8670
    Pomógł: 760
    Ocena: 1461
    khoam napisał:
    Inkrementacja zmiennej 8-bitowej to też operacja atomowa.


    Może i jest.
    W moim własnym projekcie bałbym się korzystać. Szczegóły się zapomną, za długi czas kod będzie miał dalsze życie itd ... cho cby skoiowany do następnego projektu.
    Jest w kodzie widoczna synchronizacja, to się inaczej to czyta (ja jestem z tych, co uznają kod PO PIERWSZE dla czytajacego, dopiero po drugie dla kompilatora)

    moje zdanie
  • #30 19349307
    Konto nie istnieje
    Poziom 1  

Podsumowanie tematu

✨ W dyskusji poruszono problematykę zmiennych globalnych w kontekście przerwań w systemach opartych na mikrokontrolerach AVR. Użytkownicy zwracają uwagę na ryzyko błędów, gdy przerwanie może wystąpić w trakcie modyfikacji zmiennej, co prowadzi do nieprawidłowych wartości. Zasugerowano stosowanie operacji atomowych oraz specyfikatora `volatile`, aby zapewnić spójność danych. Wskazano również na możliwość wyłączenia przerwań podczas modyfikacji zmiennych oraz na użycie biblioteki `atomic.h` w AVR. Dyskutowano także o różnicach w zachowaniu zmiennych w systemach 8-bitowych, takich jak AVR i PIC, oraz o znaczeniu synchronizacji w kontekście programowania wątkowego.
Wygenerowane przez model językowy.
REKLAMA