組込み・ファームウェア

上のプログラムを最適化を有効にしてコンパイルすると、タイマ割り込みが起きてもled_on()が呼ばれないことがある。原因と対策の組み合わせとして正しいものはどれか。

int flag = 0;
void timer_isr(void) { flag = 1; }
int main(void) {
    while (flag == 0) { }
    led_on();
}
  1. Aコンパイラがflagを一度だけ読んでループの中で読み直さないため。flagにvolatileを付ける
  2. B割り込みが起きるとflagが0に戻るため。flagをlongにする
  3. Cwhileの中身が空だとCPUが止まるため。ループの中に足し算を入れる
答えと解説を見る

正解:A. コンパイラがflagを一度だけ読んでループの中で読み直さないため。flagにvolatileを付ける

コンパイラはmainの中だけを見て「ループの中でflagを変えるものはない」と判断し、flagを1回だけレジスタに読んで、その値で回り続けるコードを作ることがあります。割り込みハンドラがメモリ上のflagを書き換えても、ループはそれを見ません。volatileを付けると、アクセスのたびにメモリから読み書きするようになります。複数バイトの変数では、さらに読み書きの途中で割り込まれないための工夫も必要です。

  • A. 正しい。毎回メモリから読み直すように指示します。
  • B. ハンドラは1を書いていて、型も原因ではありません。
  • C. 空のループでもCPUは止まりません。
この分野を解く 分野ページへ

組込み・ファームウェアのほかの問題

  1. 8ビットのマイコンで、タイマ割り込みが32ビットの変数ticksを1ずつ増やし、メイン処理がticksを読んで経過時間を求めている。まれに大きくずれた値が読めてしまう原因として正しいものはどれか。
  2. UARTによるシリアル通信の特徴として正しいものはどれか。
  3. 115200 bpsのUARTで、データ8ビット・パリティなし・ストップビット1(8N1)の形式で送るとき、1秒間に送れるバイト数に最も近いものはどれか。
  4. UARTの送信側と受信側のボーレートが少しずれていると、文字化けが起こることがある。ずれの許容範囲がおよそ数%程度に限られる理由として正しいものはどれか。
  5. SPI通信の特徴として正しいものはどれか。