niedziela, 10 lipca 2016

C - Zmienna volatile

Ten bardzo krótki post chciałbym poświęcić zagadnieniu modyfikatorowi volatile, która jest najczęściej wykorzystywana w procedurze obsługi przerwania.

[Źródło: https://docs.microsoft.com/pl-pl/cpp/c-language/?view=msvc-160]
Zmienna volatile jest tzw. zmienną ulotną. Wartość z takim parametrem nie będzie brana do optymalizacji programu. Dla kompilatora jest to informacja, że wartość tej zmiennej może się zmienić w różnych momentach, nieprzewidywalnych momentach. Czyli wartość nie będzie brana z rejestrów, jak w przypadku wykonywania szeregu operacji na zmiennej, tylko bezpośrednio z pamięci. Dodatkowo kolejność działań wykonywanych na zmiennej nie ulegnie zmianie.

W przypadku nie zastosowania takiej zmiennej mogą wystąpić problemy po włączeniu optymalizacji w programie, niepoprawne działanie podczas wywoływania zmiennej w przerwaniach, operacji na rejestrach czy zmiennych globalnych wykorzystywanych w wielu elementach w programie.

Specyfikator volatile musi być zastosowany w zmiennych wykorzystywanych w przerwaniach.

Cały program najlepiej zademonstrować na funkcji przerwania dla mikrokontrolerów. Przykładowe funkcje obsługi przerwania zostały opisane w sekcji bloga poświęconej STM32.

Zmienną typu volatile deklaruje się w następujący sposób.

  1. volatile uint8_t zmienna = 0;

Modyfikator volatile można użyć także do zmiennych wskaźnikowych:

  1. volatile uint8_t * val1;
  2. uint8_t volatile * val2;
  3. uint16_t volatile * volatile val3;

Pierwszy wskaźnik wskazuje na zmienną typu volatile, drugi wskaźnik wskazuje na zmienną bez modyfikatora volatile. Trzeci wskaźnik jest wskaźnikiem volatile na zmienną volatile.

W przypadku struktur jako volatile można zapisać całą zdeklarowaną strukturę lub pojedyncze pola. 

Jako podsumowanie należy pamiętać o tym, że zmienna volatile może ulec zmianie w każdym momencie. Co oznacza, że np. przy zdeklarowaniu tablicy volatile to podczas kopiowania, lub sprawdzania zapisanych danych informacje mogą zostać zamienione. Dlatego należy wyłączyć możliwość zmiany tych danych z innego miejsca niż aktualnie obsługiwane (np. wyłączenie wywoływania przerwań, utworzenie flagi nie pozwalające na modyfikację zmiennych itp.). 

Źródła: