![]()
|
処理系によると思いますが、gcc-2.95.2では0b101010のような2進数表記ができません。もともとANSIにはないと思うので仕方がないのですが、どうしてもビット操作が多くなりがちな組み込み用途では不便です。そこで、0bXXXXXXを扱えるようにするパッチを作りました。でも、ソース配布時に問題あるかも・・・ % cd gcc-2.95.2
% cat > bin.cエラーが出なければOKです。生成されたbin.sを開いて確認してみてください。
H8マイコンはCCRというレジスタにグローバルな割り込み許可・禁止のフラグを持っています。割り込みを発生させるには割り込みコントローラの割り込み許可フラグを立てるほかに、このCCRレジスタの変更が必要です。割り込みコントローラはメモリマップドI/OなのでC言語で直接アクセスすることができますが、CCRレジスタにはC言語で
次のように使います。
gccでは割り込み処理ルーチンもC言語で作成できます。割り込みハンドラ関数の定義の前に次のような宣言をすればOKです。 "#pragma interrupt"がその宣言です。割り込みハンドラは当然ですが引数なしで、戻り型はvoidでなければなりません。 通常、関数名はリンカスクリプト内で設定されている名前を使わなければなりません。先頭の_(アンスコ)は外してください。
printfに代表されるような変数を可変長にすることができる関数があります。このような関数をH8で利用する場合、必ずプロトタイプ宣言が必要です。printfについてはstdio.hをインクルードするだけで済みますので乱暴に作らなければ大丈夫ですが、ユーザが可変長引数の関数を作成する場合は注意が必要です。例えば、 のようなプログラムを作成しておいて、他の別のソースファイルから呼び出した場合、 上記の例では正しく動作しますが、赤字の部分"extern int debug(char *fmt, ...);"がないと正しく動作しません。これは、コンパイラの引数渡しの方法に原因があります。 通常のプロセッサでは、引数をスタックに積んでから関数をコールします。呼ばれた関数ではスタックの上の方をみて、親関数からの値を得ます。必ずスタックを使うような設計になっているのですが、H8は違います。 引数の個数が少ない場合、コンパイラは引数をスタックに積まず、レジスタに直接値をセットして関数をコールします。これにより、メモリアクセスが少なくなり実行が速くなります。H8はCPUの汎用レジスタが多いので引数をレジスタにセットしても、問題になりません。 今回のケースでは変数が可変なので、上記のdebug関数は引数がスタックに積まれているものとしてコードを生成します。 呼び出す側では、プロトタイプ宣言の定義に従ってレジスタ渡しにするか、スタック渡しにするかが決まります。コンパイラはできるだけ、速いコードになるようにしたいので、レジスタ渡しを優先します。上記の場合プロトタイプ宣言が無いと、引数がレジスタ渡しになってしまい、呼び出し側と受け取る関数側で食い違ってしまいます。これが暴走の原因です。 ここでは可変引数の関数についてだけ説明していますが、それ以外のタイプの引数についても、プロトタイプ宣言がないとトラブルが発生する可能性がありますので、必ずやっておいた方がいいでしょう。戻り値がintだから宣言しなくても動くというふうに思わないように!!
すでにH8メーリングリストで挙がっていた問題です。H8Tinyにおいて、引数を4つ以上(可変個引数も対象)渡すと、呼ばれた側で正しく引数を受け取れないというものでした。これは佐藤 嘉則さんによって解決されています。パッチのあてかたについては開発環境の準備のLinuxをみてください。
次のようなプログラムを書くとxxにデータを書き込めません。
注意しないといけないのは上記でyy=0と記述しても、同じ現象が発生します。
gccコンパイラは非常な優秀な最適化を行ってくれます。特に68000系は、昔X68000を使って いたこともあってしばらく使っていましたが、かなり高速なコードを出力してくれました。 多分H8も68000系なので、優れたコードを出力することが予想されます。 速いことはおおいに結構なことなのですが、組み込み系システム、特に割り込みを多用するプログラム においてはその最適化がトラブルのもとになることがあります。
上記のようなプログラムの場合、intという関数が割り込みハンドラとして定義されており、割り込みが発生すると変数start
組み込み系システムではvolatileは重要です!
でも、うまく活用されていないのが実状のような気がします。マクロ(プリプロセッサ)命令について思い付いたものから掲載します。この項目はH8に限ったことではなくて、C言語の一般的な内容です。
ANSIコンパイラは次のようにすると変数名をくっつけたり、文字列として扱うことができるので便利です。これを知ってるとかなりcppを使いこなせます。
上記のプログラムを入力、実行してみてください。ANSI準拠のコンパイラならできるはずです。すると
のように表示されます。DUMP(*y)とやっただけで、自動的に
"*y="を付けてくれるのです。
となどとやってもいいのですが、普通コピー&ペーストでプログラム組みますから、絶対に変数と文字列の修正を忘れます。10行以上ならかなりの率です。
このマクロの説明をするとい、まずvarが引数になりますが、ここでDUMP(counter)というマクロの展開を考えます。スタートは
です。次にvarがcounterに置き換わりますから、
と等価になります。それで#counterをみて?と思うかもしれません。そうです、#という演算子はC言語にありません。でも#演算子はプリプロセッサ命令として存在するのです。#はプリプロセッサ命令についています。#includeにも頭についてるでしょ。
"AAAAA" "BBBBB"のように文字列を並べて書くとコンパイラがその文字列を連結しますので、
となり、うまいことcounter=12345のように表示できるようになります。これで、知らない人に教えてあげよう!
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||