2001/Dec./29


●開発Tips

このモニタを作っていて気付いたネタを並べてみます。

●セクションに気をつけろ

秋月の環境では、セクションという奴をきちんと理解しないと、コンパイルできてもROM化できない事があります。特に、グローバル変数や初期値のある変数を使用する場合は非常に重要です。

CPUボードを購入すると付属しているツールの中にアセンブラとリンカがありますが、実はこれらを使ってうまくブートコードを記述し、リンクするための指示ファイルを作成して正しくリンクできるようにならないと、Cで書いてコンパイルしたコードが実行できないのですね。

で、その中でももっともわかりにくいのが、リンケージエディタへのサブファイルの記述にある「START」というパラメータでしょう。このパラメータの指定方法ですが、基本的にはそこにセクション名を並べる事で、最終的なバイナリの順番を決定する事になっています。例えば、

START A,B,C,D

と書けば、これは0番地から順番にABCDのそれぞれのセクションが並ぶ事になります。問題は絶対アドレス上の配置を変更したい場合で、例えばAは0番地から、BCDは100番地からという時に、このような記述をしなければなりません。

START A(0),B,C,D(100)

私も最初は「え?」っと思ったんですが、カッコ書きになっているアドレスは、それ以前にアドレス指定された後につながっている一連のセクションの先頭という意味らしいんですわ。でもこれ、普通ぢゃないですよねぇ。

また、アセンブラのブート用コードでは、C言語のランタイムの役割としてDセクション(初期値を持つグローバル変数の領域で、constでないもの。ただし、ROM上)をRAM上へコピーする必要がありますが、このRAM上のセクションの定義とサイズをDセクションと同じにするために

ROM (D,DR)

という記述を行う必要があります。ここで、DRはSTARTパラメータでRAM上に割り付けたセクションですが、他に実体があるわけではなく、ここでROM宣言して初めて意味を持つんですね。これがないと、CコードはROM上のDセクションをアクセスしてしまい、書き換えができないという事になってしまいます。

さらに、コピーはアセンブラ上から行わなければなりませんが、アセンブラ側ではC言語で自動的に作成されたDセクションの事は知りません。しかし、セクションのルールには「別のモジュールに入っている同じ名前のセクションは一ケ所に集める」というのがあります。これを逆手に取り、アセンブラでもDセクションやDRセクションを定義(ただし、空で)し、そのアドレスやサイズを使うようにコードを書けば、最終的にリンクが成立した時点で正しいアドレスやサイズになるという案配です。

やっぱりややこしいよね。

●送信割込に気をつけろ

文字列の送信には、前段の送信バッファ(TDR)が空になった事を示す割込か、送信が終了した事を示す割込を使って連続的にキャラクタを送信する事になります。

私は今回、TDRが空になった時の割込を利用したルーチンを書いたのですが、何度やってもデタラメな送信ばかりになってしまっていました。

原因は、どうやらこの割込がレベル割込で、TDRが空の時は常に割込を発生させるという点にありました。リセット後すぐに割込をイネーブルにしてしまったために、常になんらかのデータが流れ続けてしまっていたというワケです。

従って、必要なデータをセットしてから割込をイネーブルにし、最後のキャラクタを送信したら割込をディスエーブルにするようにコードを組み直した所、正しく動作するようになりました。


Go Home GoBack

Copyright 2001 All Rights Reserved by Kazutaka 'Zak' Sawa .