「組み込み」ならではの基礎知識 ――スタートアップ・ルーチンからハードウェアまで

セサミアン3人組

tag: 組み込み

技術解説 2003年5月14日

 さて次に,「見かけ上,冗長な」を説明します.例えば,シリアル・インターフェースを使ったデータの受信を考えてみます.メモリ・マップ方式のシリアル・ポートを持つマイコン注4-1の場合,受信状態を表すレジスタ(ステータス・レジスタと呼ばれる)を読み出せば,そのシリアル・インターフェース経由でデータを受け取ったかどうかがわかります注4-2.では,そのレジスタを読み出すにはどうすればよいのでしょうか?

 メモリ・マップ方式の場合は,一つのレジスタに対してあるアドレスが割り付けられます.つまり,割り当てられたアドレスの内容を読み出せばよいわけです.受信状態を表すレジスタのアドレスを0x00efd00c番地,レジスタの長さを4バイトと仮定すると,受信状態を表すレジスタの読み出しは,

  *(unsigned long int *)(0x00efd00c)

となります.レジスタのアドレスが0x00efd00c,レジスタ長が4バイトなので,0x00efd00cを(unsigned long int *)でポインタ型にキャストして読み出すわけです(前項の「3.array[-1]はなぜ動くのか」を参照).さらに,受信が完了したかどうかはレジスタの特定のビットが立っているかどうかによって判定すると仮定すれば,その判定とそれに続く受信処理は,例えば次のように書けます.

  if (((*(unsigned long int *) 
    (0x00efd00c))&4) != 0) {/* 受信完了か */
   受信処理 
  }

 しかし,いつ受信が完了するかわからないので,while(1)でループを回して(ポーリング方式注4-3)レジスタをチェックしに行くことにします.これでプログラミングは完了です.

while (1) { 
 if ((*(unsigned long int *) 
  (0x00efd00c))&4) != 0) {/* 受信完了か */
   受信処理 
 } 
}

 何か気づきませんか? このプログラムは先ほど説明した最適化のパターンにはまってしまいます.つまり,Cコンパイラが,

  if ((*(unsigned long int *)
     (0x00efd00c))&4) != 0) {/* 受信完了か */ 
   while (1) {
     受信処理 
   } 
  }

と最適化してしまうかもしれません.これでは,レジスタを読みに行く最初の1回で受信完了になっていないと,永遠にデータを受信できないかもしれません.

 注4-1;メモリ・マップ方式のI/Oの詳細については,「8.メモリとポート」を参照していただきたい.
 注4-2;受信状態を表すレジスタはいくつかのフィールドに分けて,それぞれのフィールドに意味を持たせているのが普通である.ここでは受信が完了したか未完了かがわかればよいので,レジスタ内の完了/未完了を表すフィールド(1ビットが割り当てられている)のビットが立っているかどうかを確認すればよい.
 注4-3;ポーリング方式の詳細については,「6.ポーリングと割り込み」を参照していただきたい.

組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! FPGAマガジン No.12『ARMコアFPGA×Linux初体験』好評発売中

FPGAマガジン No.11『性能UP! アルゴリズム×手仕上げHDL』好評発売中! PDF版もあります

PICK UP用語

EV(電気自動車)

関連記事

EnOcean

関連記事

Android

関連記事

ニュース 一覧を見る
Tech Villageブログ

渡辺のぼるのロボコン・プロモータ日記

2年ぶりのブログ更新w

2016年10月 9日

Hamana Project

Hamana-8最終打ち上げ報告(その2)

2012年6月26日