組み込みの埋まってるとこ

システム寄りの組み込みCプログラミングBLOG

Arm用GCCでのコンパイルオプションの選び方

組み込みで使用するARM用クロスコンパイラであるarm-none-eabi-gccを使用する際に必要となる ARM固有のオプションについて紹介します。

Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer

コンパイラオプションがとる引数の詳細はGCCの公式でご確認ください。

ARM Options (Using the GNU Compiler Collection (GCC))

ARM用GCCに伝えるべきこと

arm-none-eabi-gccは組み込み用であるた細かいことをいろいろとオプションで指定しなければ正しく動作するバイナリを生成することができません。 ここはホストで動作するLinuxgccのようにあらゆるオプションが既に合わせこまれているGCCとは大きく違うところです。

arm-none-eabi-gccに伝えておかなければならないことには次のようなことがあります。

ARMアーキテクチャの指定

まずはアーキテクチャの指定から始めます。 アーキテクチャを指定する方法には-marchを使う方法と-mcpuを使う方法があります。 -mcpuはそれを1つ指定するだけで-marchとさらに関連する-mtuneやアーキテクチャ拡張をまとめて指定したときと同じ効果があります。 -mcpuと-march等を同時し指定した場合は校舎での指定が優先します。

またアーキテクチャには多くの拡張があり、 対象としているチップのコアやOSがサポートしているアーキテクチャ拡張にGCCの想定外のものがあれば、そらも同時に指定します。

(例) -mcpu=cortex-a9
(例) -march=armv7-a -mtune=cortex-a9

(例) -mcpu=cortex-a9+nosimd
(例) -march=armv7-a+simd -mtune=cortex-a9

命令セットの指定

ARMにはARM命令とThumb命令があり、どちらの命令セットでコードを生成するかを指定します

(例) -marm
(例) -mthumb

VFPの指定

浮動小数点演算器はアーキテクチャ拡張としてして指定できますが、 他のCPU用のGCCを同じように-mfpuオプションを使用して指定することもできます。

(例) -mfpu=vfpv3-d16
(例) -mfpu=neon

浮動小数点ABIの指定

浮動小数点ABIは関数の引数として浮動小数レジスタを使用する場合の受け渡し方法になります。 ここは自由に決めることはできず、リンクするライブラリやOSと同じにしなければなりません。

浮動小数点ABIは-mfloat-abiでsoft, softfp, hardの3種類から1つを指定します。 softは浮動小数点命令も浮動小数レジスタも無し、softfpは浮動小数点命令は生成するが関数の引数では整数レジスタを使用、 hardは浮動小数点命令を生成し関数の引数にも浮動小数レジスタを使用します。

関数での引数の受け渡しとは関係なく-mfloat-abiでの指定は単純にコンパイラ浮動小数点命令を生成するかどうかにも影響します。 float型やdouble型を使用しいければ浮動小数点命令が生成されないという保障はなく、 組み込みOSには浮動小数点命令自体に対応していないものもありますので注意が必要です。

(例) -mfloat-abi=hard

古いアーキテクチャやABIに由来するオプション

古いARM用プロジェクトのコンパイラオプションには今となっては何のためにあるのか分からないものがあります。 そのようなオプションをいくつか取り上げます。

アラインメントの指定

-maligned-access -mno-unaligned-accessによってワード界を跨いだメモリアクセスの生成を有効または無効にすることができます。 このオプションは通常アーキテクチャに連動してコンパイラが自動的に決定します。

Abort例外の発生を回避するために-mno-unaligned-accessを使用することは、 重大なシステム設定の間違いを温存してしまう危険性があるためどうしてもやむを得ないとき以外はやめましょう。

インターワーキングの指定

ARMv5Tよりも古いARMアーキテクチャでARM命令のコードとThumb命令のコードを一緒にリンクすることがある場合に -mthumb-interworkによってインターワーキングを有効にします。

Documentation – Arm Developer

ただしarm-none-eabiを使うのであればデフォルトでABIがAAPCSになっているためこのオプションは無効です。 かつてIAR CにARMv5T以降にもインターワーキングのオプションがあったのはEABIではない独自ABIだったからではないかと思います。

プラットフォームに由来するオプション

arm-none-eabi-gccには標準CライブラリとしてNewlibがポーティングされていますが、これがすべてそのまま正常に動作するようなプラットフォームは組み込みの規模では無理であり、動作するところだけを使うか、あるいは別途提供される標準Cライブラリに差し替える必要がありそうです。またスタートアッププログラムもBSP等として提供されているものやCMSISをカスタマイズしたものを用意しなければならないはずです。

ここでその詳細に触れることはできませんが、そういう意味では--sysroot -nostdlib -nostartfiles のようなオプションの設定もおそらく必要になるでしょう。

まとめ

一緒に使おうとするOSやライブラリがバイナリで提供されている場合は原則としてそれと同じオプションを選択します。 自由に決めてよいときはまずCPUのコア構成を調べるところから始めるとよいでしょう。

GCCは歴史がありレガシーなオプションがたくさん残っていますので、今から始めようとするとある程度歴史の勉強が必要になることもあります。

細かいコンパイラオプションがたくさんついているのを見かけたときは、EABI用としてコンパイルされていないGCCを転用していないかや、OSやブートローダー等にソフト的な制約がないかを確認するとよいでしょう。