Arm

オープンソースコンパイラからプロプライエタリコンパイラへのTOPPERS/ASP移植事例

<span id="hs_cos_wrapper_name" class="hs_cos_wrapper hs_cos_wrapper_meta_field hs_cos_wrapper_type_text" style="" data-hs-cos-general-type="meta_field" data-hs-cos-type="text" >オープンソースコンパイラからプロプライエタリコンパイラへのTOPPERS/ASP移植事例</span>

近年、オープンソースで開発されたソフトウェアを、商用で実績のあるプロプライエタリコンパイラへ移植したいというご要望が増えています。本ブログでは、オープンソースの代表格であるGCCで作成されたTOPPERS/ASPプロジェクトを、IARシステムズの「IAR Embedded Workbench for Arm (EWARM)」へ移植した事例をご紹介します。 

TOPPERS/ASPの概要と今回の移植環境 

今回の移植対象は、TOPPERSプロジェクトが開発しているリアルタイムOSカーネル「TOPPERS/ASP」のサンプルプロジェクトです。ASPは、μITRONを拡張したリアルタイムOSカーネルであり、RISC-VやArm Cortex-A/M、SHなど様々なマイコンに移植されています。 

今回の移植で使用した環境は以下の通りです。 

  • 元環境(GCC): GCC 10.3、ASPカーネル 1.93、Cortex-M0パッケージ 1.98、コンフィギュレータ 1.94 
  • 移植先(EWARM): EWARM 9.60.3 
  • 評価ボード: STM32F071 (Cortex-M0+) 

GCCプロジェクト移植のステップ 

GCCプロジェクトをEWARMへ移植するにあたり、以下のステップで作業を進めました。

1.ビルドプロセスの確認と分析

まず、GCCでのビルドがどのように行われているかを把握するため、makeコマンドの実行ログを詳細に分析しました。TOPPERS/ASPのサンプルプロジェクトでは、以下の2段階のビルドが必要であることが判明しました。 

1. パラメータ計算用プロジェクトのビルド: 構造体やビットフィールドのアドレスを調べるためのビルド。

2.メインアプリケーションプロジェクトのビルド: リアルタイムOSカーネルとアプリケーションのビルド。 

この分析により、以下の重要なポイントが明らかになりました。 

  • 2つのプロジェクト: 移植先でも2つのプロジェクトを作成する必要がある。 
  • シンボル情報の抽出と変換: 最初のビルドで生成されるシンボル情報(GCCのnmコマンドで出力される形式)を、EWARMで実行する場合にはGCC形式に変換する必要がある。 
  • 個別ファイルの修正: Cファイルやアセンブラファイルの一部に修正が必要となる。 
オプション・リンカ設定の変更: コンパイラやリンカのオプション、リンカ設定ファイルはGCCとEWARMで互換性がなく、書き換えが必要である。

 

2.ファイルとオプションの設定


ログ分析で抽出した情報をもとに、EWARMのプロジェクトに以下の設定を行いました。 

  • 必要なソースファイルの抽出: 各プロジェクトに必要なCファイル、アセンブラファイルを特定し、プロジェクトに追加しました。 
  • コンパイラ・アセンブラオプションの設定: GCCのビルドログから、デファイン定義、インクルードパス、CPU関連の設定(エンディアン、命令セット、CPUコアなど)を抽出し、EWARMのGUIで対応する設定を行いました。特にインクルードパスとデファインマクロはそのまま移植可能でした。 

3.リンカ設定ファイルの作成


GCCとEWARMではリンカ設定ファイルの文法が全く異なります。GCCのリンカ設定ファイルの内容を分析し、EWARM用に以下の要素を含むリンカ設定ファイルを作成しました。 

  • ROM/RAMの使用領域指定: メモリマップを定義します。 
  • PROVIDEキーワードの対応: GCCのリンカで使用するPROVIDEキーワードは、ユーザー定義関数が存在しない場合にNULLアドレスを設定する機能です。EWARMには直接対応する機能がないため、Cソースコード側で__weak宣言を追加することで同等の機能を実現しました。 
  • スタートアップファイルの指定: どのオブジェクトファイルをスタートアップとして使用するかを指定します。 
  • セクション配置情報: 各セクション(コード、データなど)の配置を指定します。 

EWARMのリンカ設定ファイルはGCCと比較して非常に簡潔に記述できます。 

4.ソースコードの修正

移植作業で最も時間を要したのがソースコードの修正でした。一つずつコンパイルし、エラーが出た箇所を修正していく作業を繰り返しました。 

アセンブラコードの修正点 

  1. ディレクティブ・キーワードの相違: GCCとEWARMでは、セクション定義などのアセンブラディレクティブの書式や文法が異なります。これらをEWARMの記述に修正しました。
  2. 外部宣言シンボル: Cファイルで定義された関数をアセンブラから呼び出す際に、EWARMでは明示的な外部宣言(C言語のexternに相当)が必要でした。
  3. 命令フォーマット: GCCではユニファイド形式で記述された命令が、EWARMではArmのリファレンスマニュアルに準拠した形式(シャープ記号が必要)でないとコンパイルエラーになりました。
  4. ファイル終端の指定: EWARMではアセンブラファイルの終端にENDディレクティブが必要です。
  5. マクロの変更: GCC版で使用されていたアセンブラマクロがEWARMではエラーになったため、該当マクロをコメントアウトしました。
  6. 変数初期化ルーチン: TOPPERS/ASPのスタートアップには独自の変数初期化ルーチンが含まれていましたが、EWARMが持つ圧縮機能付きのライブラリ関数(__iar_data_init3)を呼び出すように変更しました。これにより、ROMフラッシュ上の初期化データのサイズを削減できます。 

C言語コードの修正点 

  1. PROVIDEキーワードの対応 (再掲): リンカ設定で対応できないPROVIDE機能は、Cソースコード側で該当関数を__weak宣言することで対応しました。
  2. インラインアセンブラの記述: GCCで使用されていた__asm__ 式のインラインアセンブラ記述がEWARMではサポートされていないか、異なる挙動を示したため、EWARMでサポートされている__asm形式に変更しました。
  3. スタック初期化の問題: リセット直後から使用されるスタック(カーネルの初期スタック)が、変数初期化ルーチンによって上書きされてしまい、暴走する問題が発生しました。これを避けるため、IAR独自の拡張機能である__no_init宣言を用いて、この特定のスタック変数を初期化対象外としました。
  4. インライン関数の強制: インラインキーワードの効果が弱いため、EWARMで強力にインライン化を強制する_Pragma(“inline=forced”)を使用しました(機能的には必須ではありませんが、意図を明確にするため)。
  5. 型不一致の警告をエラーに変更: 関数ポインタの型不一致でEWARMがエラーと判定する箇所がありました。GCCでは警告に留まっていたため、EWARMのコンパイラオプションでこのエラーを警告レベルに引き下げ、ビルドが通るようにしました(本来はソースコードを修正することが望ましいです)。

デバッガ設定と動作確認

EWARMのデバッガを使用するため、評価ボードのデバッガインターフェース(今回はSP-Link)に合わせて設定を行いました。また、リアルタイムOSアプリケーションでmain関数がないため、デバッガをリセット直後で停止するように設定を変更しました。 

移植を終えての考察とTips 

今回の移植作業は、筆者はTOPPERSおよびIAR Embedded Workbenchに関する知識があったため、実質2時間程度で完了しました。しかし、知識がない場合は数週間から数ヶ月かかる可能性もあります。移植を成功させるためには、以下の点が非常に重要です。 

  • 移植元のソフトウェア構造とツールの理解: GCCでのビルドプロセスやリンカ設定を深く理解することが不可欠です。 
  • 移植先のコンパイラ・リンカの理解: EWARMのオプション、リンカ設定、独自拡張などを把握しておく必要があります。 
  • マイコンの知見: 使用するマイコン(Cortex-M0+)のアーキテクチャ特性を理解していると、不要なコードの削除や問題箇所の特定が容易になります。例えば、FPUやスタックリミットレジスタの有無などです。 
  • 段階的なデバッグ: EWARMのデバッガは、GCCで生成されたDwarf Version 4のデバッグ情報を持つバイナリをサポートしています(Dwarf Version 5には非対応)。そのため、GCCコンパイル時にDwarf Version 4で生成するようにオプションを設定すれば、EWARMのデバッガでステップ実行しながら移植元の挙動を確認できます。 

特に今回の移植でハマった点として、以下の2点が挙げられます。 

  • リンカログにスタートアップファイルが表示されない問題: GCCのリンカ設定ファイル内で明示的にスタートアップファイルが指定されていたため、ビルドログには表示されず、初期段階でどこからリンクされているか把握するのに苦労しました。 
  • スタートアップ時の暴走: IARの変数初期化ルーチンを使用する際に、リセット直後に使用されるスタックが初期化されてしまい、暴走する問題が発生しました。これは__no_init宣言で回避しました。 

これらの経験から、移植作業においては、単純なコード変換だけでなく、各コンパイラやリンカの特性、そしてマイコンのアーキテクチャまで踏み込んだ理解が求められることが改めて認識されました。 

移植結果 

今回の移植により、TOPPERS/ASPサンプルプロジェクトはEWARM上で問題なく動作しました。 

コンパイラの最適化効果として、GCCと比較してコードサイズが大幅に削減されるという結果が得られました。これは、EWARMが商用コンパイラとして長年培ってきた最適化技術の強みを示すものです。コードサイズが小さくなることで、より小さなマイコンでも高度な機能を搭載できるようになり、大きなメリットとなります。 

まとめ 

本ブログでは、GCCで作成されたTOPPERS/ASPプロジェクトをIAR Embedded Workbenchへ移植した事例をご紹介しました。移植は、ビルドプロセスの分析、オプションやリンカ設定の適切な設定、そしてC/アセンブラソースコードの修正を丁寧に行うことで実現可能です。 

IARシステムズは、このような移植作業をサポートするためのツールと知識を提供しています。もしオープンソースプロジェクトの商用コンパイラへの移植をご検討でしたら、ぜひIARシステムズにご相談ください。