変数が1を超えるISRからアクセスされ、ISRの外部で共有されない場合、揮発性は必要ですか?


9

明確に文書化グローバルデータは、ISRとメインプログラムと共有されている場合、データのニーズが宣言されることをvolatile保証メモリの可視性にするために(それが唯一の1バイトのデータで十分、何も大きなニーズも保証アトミックに特別な手配を) 。ここに良いルールがあります:

  • ISRの外部でのみ使用される変数は、揮発性であってはなりません。
  • ISR内でのみ使用される変数は、揮発性であってはなりません。
  • ISRの内部と外部の両方で使用される変数は、揮発性でなければなりません。

しかしvolatile、変数が1を超えるISRからアクセスされ、ISRの外部で共有されない場合に必要ですか?たとえば、static変数を使用して内部状態を維持する関数があります。

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

この関数は、ピン割り込みから、およびTimerOneライブラリからの2つの方法で呼び出されます

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

ISRに入ると、割り込みは自動的に無効になるためアトミック性の問題はありませんが、これvolatileはコンパイラーの質問です。何がキャッシュされ、何がキャッシュされないかです。

もちろん、申し訳ありませんが安全です。

回答:


9

volatile 変数が生成されるコード以外の何かによって変更される可能性があることをコンパイラのコードジェネレータに通知するだけであり、そのコピーが正確であるとは想定していません。

ISRコードは、開始時にコンテキストがないことを前提に記述/生成され、その(ISRの)自身の操作の周りのCPUのコンテキストを保持する必要があります。したがって、非アトミック操作の不可分性と同様、ボラティリティは、この場合は*、割り込みがネストできるかどうかに依存します。非ネストが保証されている場合、共有変数は、自身の実行中にこのISR以外で変更できません。割り込みがネストできる環境でISRがいつか使用される可能性がある場合、その制約は保持されなくなります。

* この場合
ここでは、ソフトウェアで管理される変数を想定しています。ハードウェアイベント、たとえばタイマーレジスターによって更新できる変数について話している場合、すべての賭けはオフです。変数は何があっても揮発性です。


したがって、Arduinoのデフォルトの「割り込みはネストしない」動作を変更しない限り、変数はである必要はありませんvolatile。生成されるコード以外で変更されないためです。コンパイラは、割り込みが入れ子にならない限り、ISRが線形に実行されると「想定」できます。それは理にかなっている。ありがとう!
Joonas Pulakka 14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.