Czy zmienność jest potrzebna, gdy zmienna jest dostępna z> 1 ISR, ale nie jest dzielona poza ISR?

9

Jest wyraźnie udokumentowane, że gdy dane globalne są udostępniane ISR i programowi głównemu, dane muszą zostać zadeklarowane volatilew celu zagwarantowania widoczności pamięci (i to wystarcza tylko dla danych 1-bajtowych; cokolwiek większego wymaga specjalnych ustaleń, aby zagwarantować również atomowość) . Tutaj mamy dobre zasady:

  • Zmienne używane tylko poza ISR nie powinny być niestabilne.
  • Zmienne używane tylko wewnątrz ISR nie powinny być lotne.
  • Zmienne stosowane zarówno wewnątrz, jak i na zewnątrz ISR powinny być niestabilne.

Ale czy jest volatilepotrzebny, gdy zmienna jest dostępna z> 1 ISR, ale nie jest dzielona poza ISR? Na przykład mam funkcję, która utrzymuje stan wewnętrzny za pomocą staticzmiennej:

void func() {
    static volatile long counter; // volatile or not?
    // Do stuff with counter etc.
}

Ta funkcja jest wywoływana na dwa sposoby: z przerwań pinów i z biblioteki TimerOne :

  1. attachInterrupt(0, func, CHANGE);
  2. Timer1.attachInterrupt(func);

Nie ma problemów z atomicznością, ponieważ po wprowadzeniu ISR przerwania są automatycznie wyłączane , ale volatilejest to raczej pytanie kompilatora: co jest buforowane, a co nie.

Oczywiście lepiej niż żałować ...

Joonas Pulakka
źródło

Odpowiedzi:

9

volatile informuje tylko generator kodu kompilatora, że ​​zmienna może być modyfikowana przez coś innego niż generowany kod, więc nie zakładaj, że żadna jej kopia pozostanie dokładna.

Kod ISR musi zostać napisany / wygenerowany przy założeniu, że nie ma kontekstu przy wejściu i musi zachowywać kontekst procesora wokół własnej operacji (ISR). Tak więc, podobnie jak w przypadku niepodzielności operacji nieatomowych, zmienność zależy w tym przypadku * od tego, czy przerwania mogą się zagnieżdżać. Jeśli gwarantowane jest brak zagnieżdżenia, zmienna współdzielona nie może się zmienić w inny sposób niż ten ISR podczas własnego wykonywania. Jeśli twój ISR może kiedyś być używany w środowisku, w którym przerwania mogą się zagnieżdżać, wówczas to ograniczenie nie będzie dłużej obowiązywać.

* w tym przypadku :
zakładam, że zmienna obsługiwana przez oprogramowanie jest tutaj. Jeśli mówimy o zmiennej, która może zostać zaktualizowana przez zdarzenie sprzętowe, na przykład rejestr timera, wszystkie zakłady są wyłączone: zmienna jest zmienna bez względu na wszystko.

JRobert
źródło
Tak długo, jak nie zmieniam domyślnego zachowania Arduino „przerwania nie zagnieżdżają”, zmienna nie musi być volatile, ponieważ nie jest modyfikowana przez nic innego niż generowany kod; kompilator może „założyć”, że ISR wykonuje się liniowo i robi to, o ile przerwania nie zagnieżdżają się. To ma sens. Dzięki!
Joonas Pulakka