私のコードは C で書かれています。グローバル変数を使用してメイン コードと通信する ISR (割り込みサービス ルーチン) があります。ISR は、メイン コードとは異なるコンパイル ユニットにあります。メイン コードに「揮発性」を使用できないが、ISR では使用しない理由はありますか?
私の理由は次のとおりです。volatile 修飾子が、コンパイラによる ISR の完全な最適化を妨げています。ISR の観点からは、変数は揮発性ではありません。つまり、ISR の期間中は外部から変更できず、ISR の期間中は値を出力する必要はありません。さらに、ISR が独自のコンパイル ユニット内にある場合、コンパイラは ISR が最初に使用する前にメモリからグローバルを読み取らせなければならず (MUST)、戻る前に変更を保存し直さなければなりません (MUST)。これについての私の理由は次のとおりです。異なるコンパイルユニットを同時にコンパイルする必要がないため、コンパイラは ISR の範囲を超えて何が起こっているのかを認識できず (またはそのふりをする必要があります)、グローバルが read/ であることを確認する必要があります。 ISR の境界に書かれています。
おそらく、コンパイル単位の重要性を誤解していますか? 私が見つけた参考文献の 1 つは、GCC がこの揮発性の不一致をコンパイル時のエラーにしたと述べています。それらが異なるコンパイル単位にある場合、それらは独立しているべきではないのでしょうか。ライブラリ関数を個別にコンパイルして後でリンクすることはできませんか?
volatile を使用してシステム コードを解読する 9 つの方法
おそらく、シーケンス ポイントの概念から議論を行うことができます。シーケンス ポイントまたは副作用の概念を完全には理解していません。しかし、C99 仕様は 5.1.2.3 パラグラフ 2 で次のように述べています。 "
附属書 C には、以下を含むシーケンス ポイントがリストされています。
- 引数が評価された後の関数の呼び出し。
- ライブラリ関数が戻る直前。
参照: WG14 ドキュメント: N1013、日付: 2003 年 5 月 7 日
注: 前の質問、関数呼び出しと戻り値に関連するグローバル変数アクセスでは、関数呼び出しと戻り値の前/後にグローバルが格納/書き込まれるかどうかを尋ねました。しかし、これは別の質問であり、グローバル変数が異なるコンパイル単位で「揮発性」として異なって修飾される可能性があるかどうかを尋ねます。私は予備的な結論を正当化するために同じ推論の多くを使用したため、一部の読者は同じ質問であると考えるようになりました.