組込み・ファームウェア
上のプログラムを最適化を有効にしてコンパイルすると、タイマ割り込みが起きてもled_on()が呼ばれないことがある。原因と対策の組み合わせとして正しいものはどれか。
int flag = 0;
void timer_isr(void) { flag = 1; }
int main(void) {
while (flag == 0) { }
led_on();
}
- Aコンパイラがflagを一度だけ読んでループの中で読み直さないため。flagにvolatileを付ける
- B割り込みが起きるとflagが0に戻るため。flagをlongにする
- Cwhileの中身が空だとCPUが止まるため。ループの中に足し算を入れる
答えと解説を見る
正解:A. コンパイラがflagを一度だけ読んでループの中で読み直さないため。flagにvolatileを付ける
コンパイラはmainの中だけを見て「ループの中でflagを変えるものはない」と判断し、flagを1回だけレジスタに読んで、その値で回り続けるコードを作ることがあります。割り込みハンドラがメモリ上のflagを書き換えても、ループはそれを見ません。volatileを付けると、アクセスのたびにメモリから読み書きするようになります。複数バイトの変数では、さらに読み書きの途中で割り込まれないための工夫も必要です。
- A. 正しい。毎回メモリから読み直すように指示します。
- B. ハンドラは1を書いていて、型も原因ではありません。
- C. 空のループでもCPUは止まりません。