volatile

名称

volatile

説明

volatileは型修飾子の一つであり、変数のデータ型の前に書き、コンパイラやコンパイラが生成するプログラムによるその変数の取り扱い方法を変更する。

変数をvolatileとして修飾することは、コンパイラに対して指令することである。コンパイラとは、C/C++言語のコードを機械語に翻訳し、ArduinoのAtmegaチップ上の実際の命令セットを生成するものである。

具体的には、プログラムの変数が一時的に配置されて操作されるレジスタではなく、必ずRAMから読み込むように指示する。特定の状況では、レジスタに格納された変数の値は不正確になることがある。

並行処理するスレッドなど、変数が、そのコード以外によって変更されるような場合に、volatile修飾を行う必要がある。Arduinoでは、このようなことが起こりうるのは、割り込みサービスルーチンと呼ばれる、割り込みに関するコードだけである。

int それとも long?

8ビットのマイクロコントローラでは、volatile変数が1バイトよりも大きいとき(例: 16ビットのintや32ビットのlong)は、マイクロコントローラは1ステップではその値を読み込むことができない。これにより、メインコードセクション(例: loop())が、変数の最初の8ビットを読み込んでいるときに、割り込みにより残りの8ビットを変更しているかもしれないことを意味する。これにより、その変数にランダムな値が格納される。

救済措置: volatile変数を読み込む際は、割り込みを禁止し、読み取りの際に変数の変更ができなくする。割り込みの禁止には、いくつかの方法がある。

  • noInterrupts()
  • ATOMIC_BLOCKマクロを使う。アトミック操作は、1回のMCU操作、すなわち、分割できない操作である。

使用例

volatile修飾子は、変数stateに対する変更を即座にloop()内に反映する。volatile修飾子を付けないと、state変数はレジスタに読み込まれ、関数が終わるまで変更されないかもしれない。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Flashes the LED for 1 s if the input has changed
// in the previous second.

volatile byte changed = 0;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2), toggle, CHANGE);
}

void loop() {
  if (changed == 1) {
    // toggle() has been called from interrupts!

    // Reset changed to 0
    changed = 0;

    // Blink LED for 200 ms
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
  }
}

void toggle() {
  changed = 1;
}

マイクロコンピュータの8ビットデータバスよりも大きいサイズの変数にアクセスするには、ATOMIC_BLOCKマクロを使う。このマクロは変数がアトミックに読みこまれることを保証する。すなわち、その変数が読み込まれている間はその内容は変更されない。

1
2
3
4
5
6
7
8
9
#include <util/atomic.h> // this library includes the ATOMIC_BLOCK macro.
volatile int input_from_interrupt;

// Somewhere in the code, e.g. inside loop()
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    // code with interrupts blocked (consecutive atomic operations will not get interrupted)
    int result = input_from_interrupt;
  }
  

参照

言語 attachInterrupt()

オリジナルのページ

https://www.arduino.cc/reference/en/language/variables/variable-scope-qualifiers/volatile/

Last Revision: 2020/09/24

最終更新日

January 4, 2024

inserted by FC2 system