平成30年度 春期 エンベデッドシステムスペシャリスト試験 午前Ⅱ 問1
テクノロジ/ソフトウェアメモリマップド I/O の I/O ポートにアクセスするプログラムを C 言語で記述するときの注意点として,適切なものはどれか。
出典:平成30年度 春期 エンベデッドシステムスペシャリスト試験 午前Ⅱ 問1
- アアセンブラの IN/OUT 命令を用いたアクセス用関数を呼び出して,アクセスする。
- イコンパイラによる最適化を抑止するために,volatile 型修飾子を付けて宣言した変数へのポインタとしてアドレスを指定して,アクセスする。
- ウ他の関数からアクセスされるのを防ぐために,静的広域変数として宣言してアクセスする。
- エポインタではアクセスできないので,配列として実体を宣言してアクセスする。
正解:イ
解説
メモリマップド I/O では,I/O ポートも主記憶と同じアドレス空間上に配置され,通常のメモリアクセス命令でアクセスされます。しかし,I/O ポートの値はハードウェアの状態変化(センサ入力の変化や割込みフラグのクリアなど)によってプログラムの制御外で変化することがあるため,コンパイラが「同じアドレスへの複数回のアクセスは同じ値を返す」と誤って最適化(読み込みの省略やキャッシュ)してしまうと,実際のハードウェアの状態を正しく読み書きできなくなります。これを防ぐために,I/O ポートに対応する変数は volatile 型修飾子を付けて宣言し,そのアドレスを指すポインタを介してアクセスすることで,アクセスのたびに必ずメモリ(レジスタ)へ読み書きするようにコンパイラの最適化を抑止します。
選択肢ごとの解説
- ア誤り。メモリマップド I/O は,I/O ポートを主記憶と同じアドレス空間にマッピングして通常のメモリアクセス命令でアクセスする方式であり,IN/OUT 命令は用いません。IN/OUT 命令を使うのはスタンダード I/O(I/O マップド I/O)方式であり,本問の前提と矛盾します。
- イ正しい。コンパイラによる最適化(読み込みの省略やレジスタへのキャッシュ)を抑止するために,volatile 型修飾子を付けて宣言した変数へのポインタとしてアドレスを指定してアクセスすることが,メモリマップド I/O へのアクセスの注意点として適切です。
- ウ誤り。静的広域変数として宣言することは,他の関数からのアクセスを防ぐスコープの制御であり,コンパイラの最適化によって実際のハードウェアへの読み書きが省略されてしまう問題を防ぐものではありません。
- エ誤り。ポインタを用いてもメモリマップド I/O のアドレスには正しくアクセスできます。配列として実体を宣言する方法は,volatile 修飾がなければ同様に最適化の問題が残り,本質的な注意点への対処になっていません。