エンベデッドシステムスペシャリスト 2020年 午前2 問01
問題文
メモリマップドI/OのI/OポートにアクセスするプログラムをC言語で記述するときの注意点として、適切なものはどれか。
選択肢
ア:アセンブラのIN/OUT命令を用いたアクセス用関数を呼び出して、アクセスする。
イ:コンパイラによる最適化を抑止するために、volatile型修飾子を付けて宣言した変数へのポインタとしてアドレスを指定して、アクセスする。(正解)
ウ:他の関数からアクセスされるのを防ぐために、静的広域変数として宣言してアクセスする。
エ:ポインタではアクセスできないので、配列として実体を宣言してアクセスする。
🔒 解説は解答すると表示されます
メモリマップドI/Oのアクセス【午前2解説】
正解の理由
メモリマップドI/Oでは、I/Oポートをメモリ上の特定のアドレスに割り当てます。そのため、C言語ではそのアドレスをポインタで指定し、読み書きします。
このとき、I/Oポートへのアクセスは、プログラムから見た通常の変数アクセスとは異なり、実際に読み書きすることが重要です。コンパイラが値をレジスタに保持したり、不要なアクセスと判断して省略したりしないよう、対象を
volatile 修飾します。したがって、アドレスを指定したポインタを通じて、
volatile を付けた変数としてアクセスするイが適切です。解法ステップ
-
「メモリマップドI/O」に注目します。
I/Oポートがメモリ空間上のアドレスに割り当てられている方式です。 -
アクセス方法を判断します。
メモリ上のアドレスを扱うため、ポインタを使ってアクセスします。 -
コンパイラ最適化への対策を確認します。
I/Oポートへの読み書きが省略・変更されないよう、volatileを指定します。
選択肢別の誤答解説
-
ア:誤りです。
アセンブラのIN/OUT命令は、独立したI/Oアドレス空間を持つ方式で使われるものです。メモリ上のアドレスを介してアクセスするメモリマップドI/Oの説明としては適切ではありません。 -
イ:適切です。
I/Oポートのアドレスをポインタで指定し、volatileによってコンパイラがアクセスを省略・最適化しないようにします。 -
ウ:誤りです。
静的広域変数にしても、コンパイラによるアクセスの最適化を防げるわけではありません。また、staticは主に変数の有効範囲や外部からの参照可能性に関係する指定です。 -
エ:誤りです。
メモリマップドI/Oは、ポインタでアドレスを指定してアクセスできます。配列として実体を宣言する必要はありません。
よくある誤解
-
volatileを付ければ、どのようなアクセスも安全になると思う
volatileは、主にコンパイラによるアクセスの省略や統合などを防ぐ指定です。アクセスの原子性や、複数のアクセス順序まで保証するものではありません。 -
staticが付けば、I/Oアクセスの最適化も防げると思う
staticとvolatileは役割が異なります。I/Oアクセスを実際に発生させるための指定はvolatileです。 -
I/Oアクセスには必ず専用命令を使うと思う
メモリマップドI/Oでは、通常のメモリアクセスと同じ形式で、指定されたメモリアドレスを読み書きします。
補足コラム
実際の組込みシステムでは、I/Oレジスタのアドレスやアクセス幅、ポインタの型などは、プロセッサやコンパイラ、開発環境に依存します。また、複数のレジスタ操作の順序が重要な場合は、
volatile だけでは不十分なことがあり、メモリバリアなどが必要になる場合もあります。FAQ
Q.
A. 必ず省略されるとは限りません。ただし、コンパイラがプログラム上不要と判断したアクセスを省略・変更する可能性があるため、I/Oレジスタへのアクセスでは
volatile を付けないと、I/Oアクセスは必ず省略されますか?A. 必ず省略されるとは限りません。ただし、コンパイラがプログラム上不要と判断したアクセスを省略・変更する可能性があるため、I/Oレジスタへのアクセスでは
volatile を指定します。Q. メモリマップドI/Oのアドレスは、通常の変数のように宣言できますか?
A. アドレスをポインタで指定してアクセスします。ただし、具体的なアドレスや型の指定方法は、使用する環境に合わせる必要があります。
A. アドレスをポインタで指定してアクセスします。ただし、具体的なアドレスや型の指定方法は、使用する環境に合わせる必要があります。
関連キーワード: メモリマップドI/O、volatile、I/Oポート、ポインタ、コンパイラ最適化

\ せっかくなら /
エンベデッドシステムスペシャリストを
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

