CQ-FRK-FM3 基板用FM音源プログラム -- TGFM3 (7)

「インターフェース」誌 2012 年 7 月号の付属 DVD-ROM には、Eclipse/CDT + gcc ツールチェイン (gcc 4.6.0) による、無償で使える統合開発環境PizzaFactory 8 (CQ 版)」が収録されています。
CQ 版」という表現からは、6 月号付属の FM3 基板にカスタマイズされたバージョンという印象を受けますが、実際には、特に何もカスタマイズされておらず、デフォルトではターゲット CPU が Cortex-M3 であるということすら設定されていません。
いろいろと設定しないと、FM3 基板用のプログラムのコンパイルには不都合が生じますが、解決の「めど」がついたので、近日中に PizzaFactory8 (CQ 版) でビルド可能なソース・パッケージを公開したいと思います。
gcc に対する最低限のオプションとして、「-mcpu=cortex-m3 -mthumb」を指定してビルドした場合の不具合を下に列挙します。

  1. libc、libm などの標準ライブラリをリンクする時点でエラーとなり、オブジェクトが生成されない。

  2. アセンブラで記述したスタートアップ・ルーチン (startup_mb9bf61xt.s」が処理されず、.o ファイルが生成されないので、結局、オブジェクト・ファイルも生成されない。

  3. アセンブラで記述したスタートアップ・ルーチンが処理されるように設定しても、割り込みベクタテーブルの T バリアント・ビット (b0) が「1」とならず、リセット・ハンドラすら実行されない。

  4. T バリアント・ビットの問題を解決しても、FM3 のペリフェラルレジスタの定義 (mb9b610t.h) が正しくコンパイルされず、正しくペリフェラルレジスタへアクセスできないので、system_mb9f61xt.c で最初に設定されるハードウェア・ウォッチドッグ・タイマの解除すらされない。

という問題があります。
ここで、2. の問題は、Eclipse/CDT が「.s」のファイルをビルド対象のソースファイルとして「拾って」くれないのが原因であり、サフィックス「.S」あるいは「.asm」にすれば解決します。
Windows では「.s」「.S」はファイル・システムとしては両者は存在できますが、ファイル操作ではファイル名の大文字、小文字は区別して扱われず、「.s」「.S」を混在させるとトラブルの原因となりうるので、「.asm」にするのが良いと思います。
1. と 3. とは関連しており、PizzaFactory8 (CQ 版) 付属の gcc ツールチェインのターゲットが「eabi」ではなく、「elf」として生成されていることが原因です。
eabi は Embedded ABI (Appication Binary Interface) の略で、elf ターゲットでは OABI (Old ABI) のオブジェクトが生成されます。
「Old」と言うだけあって、OABI では、Cortex-M3 のように、ARM プロセッサのアーキテクチャでありながら、「ARM ステート」がなく、「THUMB ステート」のみが実装されているプロセッサのことについては考慮されていません。
それに対し、EABI では、新しいだけあって、対象のプロセッサの細かい属性を表現できるようになっています。
「elf」ターゲットでコンパイルされたライブラリでは、対象のプロセッサは ARM ステートがあるのが当たり前、FPU があるのが当たり前、と見なされるので、リンカでは、

「ライブラリはハード FP で生成されているのに、プログラムの方はソフト FP でコンパイルされているよ」

と言う意味のエラーメッセージを出して、ライブラリをリンクしてくれません。
実際には、該当するライブラリでは、ハード FP を使用しておらず、動作に問題はなく、これは単に elf ヘッダのフラグ・チェックの不一致だけなので、「バッド・ノウハウ」としては、「不一致」を無視してリンクしてしまえば良いことになります。
リンカへのオプションとしては、「--no-warn-mismatch」を指定すれば、「不一致」を検出しなくなります。
あるいは、「--noinhibit-exec」オプションを指定すれば、(他の)エラーがあっても、強制的にオブジェクトを生成します。
これらは「バッド・ノウハウ」であり、動作に影響するようなエラーを無視してしまう可能性があります。
幸い、FM 音源プログラムでは、ライブラリ・ルーチンは strlen()、memset()、memcpy()、memcmp() しか使っていないので、「自前」のソースを用意して、ライブラリ自体をリンクしないようにする予定です。
3. の T バリアント・ビットの問題は、eabi コンパイラだと何も指定しなくても、アセンブラで書かれた関数も正しく thumb ステートの関数と認識してくれるのに対し、elf コンパイラだとアセンブラ・ソース内に thumb ステートの関数であることの宣言が必要になることが原因です。
具体的には、「.thumb_func」ディレクティブを追加します。
C で記述した関数は、もちろん正しく T バリアント・ビットが立つので、スタートアップ・ルーチンをアセンブラではなく C で記述する方法でも解決できます。
4. の問題は、struct / union のパッキングの問題です。
結論から言うと、コンパイル・オプションとして「-mstructure-size-boundary=8」を指定します。
(6/9 訂正: -mstructure-size-bounary= を -mstruct-size-bounary= と誤記していたのを訂正しました)
この数値は、8、32 および 64 のみが指定可能です。
このオプションは、struct / union での、ビット・フィールド換算で何ビットまでをパッキングするかということの指定です。
ARM 向けのコンパイラでは -mstructure-size-boundary=8、つまり、1 バイト単位のパッキングにすることがデフォルトになっているようですが、なぜか、PizzaFactory8 (CQ 付属) 付属のツールチェインでは -mstructure-size-boundary=32。つまり 4 バイト・パッキングに相当する設定になっているようです。
長くなってきたので、具体的な話は次回の記事に回します。