Keil μVision試用版でEZUSB FX2LPの開発をしてたんですが、試用版の4KBの壁にぶつかってしまい、別のコンパイラに移植する事にしました。
今回使ったのはSDCCというオープンソースのコンパイラです。
SDCC - Small Device C Compiler
公開されているSDCCには2.x版と3.x版があります。新しいのを使いたくなりますが、Keil C51コンパイラ(μVisionに付属の8051コンパイラ)からの移植を考えると、2.x版の方が若干楽です。
Keil C51コンパイラの独自キーワードとの互換性
Keil C51コンパイラにはANSI-Cに無い独自キーワードとして
- bit
- sfr
- sbit
- interrupt
- xdata
- code
などが用意されています。 SDCC 2.xではこれらをそのまま使用する事が出来ます。
この理由から、今回はSDCC2.9.0を使う事にしました。
とはいっても、そのまま使えるわけではなく、いくつか修正が必要です。Kail C51コンパイラからSDCC 2.9.0に移植する際のポイントをまとめます。
_at_の記述
Keil C51コンパイラでは
int hoge at 0x1000;
と書きますが、SDCCでは
int __at (0x1000) hoge;
と書きます。
fx2regs.hなどatを使用しているファイルは全てこの形式に書き直します。
sfr, sbitの記述
sfr,sbitも同様に書き換えが必要です。
Keil C51コンパイラでは
sfr hoge = 0x80;
と書きますが、SDCCでは__atを使って
sfr __at (0x80) hoge;
と書きます。
fx2regs.hなどsfr,sbitを使用しているファイルは全てこの形式に書き直します。
interruptの記述
Keil C51コンパイラでは割り込みルーチンを記述する際に、全ての割り込みルーチンをinterrupt 0指定する事が可能です(割り込みテーブルを自動生成しない場合)。 SDCCでは、割り込み番号の重複が許されないので全ての割り込みルーチンにユニークな番号を付ける必要があります。
また、main()のあるファイル中に割り込みルーチンの定義か宣言が必要になる様です。割り込みルーチンを別ファイルに記述した際には割り込みルーチンのextern宣言をmain()のあるファイルに書けば(もしくは、extern宣言したヘッダをincludeすれば)OKです。
バイトオーダー
Keil C51コンパイラはBig-Endian、SDCCはLittle-Endianでコードを生成します。 これがKeil C51コンパイラとSDCCの一番大きな違いです。
記述方法が違うだけなら、Syntax errorが出ますから簡単に修正できるんですが、バイトオーダーの違いによるものはコンパイラじゃ検出できませんからね。
これが問題になるのは、外部機器との通信データ処理や、intやlongなどを共用体でcharに分割する場合などです。
ライブラリの移植
μVisionとSDCCではライブラリに互換性はありません(そもそもバイトオーダーも違いますしね)ので、ライブラリなどは再ビルドする必要があります。
EZ-USBの場合、ezusb.libというライブラリが付属しています。このライブラリもSDCCで再ビルドする必要があります(ソースはezusb.libと同じディレクトリにあります)。
アセンブラの記述
Keil A51アセンブラ(μVisionに付属のアセンブラ)とasx8051(SDCC 2.9に付属のアセンブラ)では若干、描き方が違います。詳しくは、SDCCのドキュメントを参照してください。
ディスクリプタの配置アドレス
EZ-USBでは_DeviceDscrなど、ディスクリプタのデータは偶数アドレスに配置する必要がありますが、SDCCではそれをリンカに指定する術がありません。 そこで、.orgディレクティブを使って絶対アドレスを指定し、偶数アドレスに配置しました。
今回の移植に当たり、こちらのサイトを参考にさせて頂きました。有益な情報ありがとうございます。
sdccKnowHow (Japanese)
Fenrir's BLog: EZUSB FX2LP Keilからsdccへ