Armマイコン(Cortex-M0)でNewlibを使いたいので自分でビルドしてみました.
たいていツールチェーンにバイナリとして付属してるけどね.
実行環境
項目 | 説明 |
---|---|
OS | Ubuntu 20.04 LTS |
コンパイラ・バイナリツール (Toolchain) | Arm GNU Toolchain 12.3Rel1 (x86_64 Linux hosted cross toolchains AArch32 bare-metal target (arm-none-eabi)) |
ツールチェーンの取得
Linuxで動くArch32用のクロスコンパイラを入手します. Arm公式から圧縮ファイルを入手し解凍しましょう.
ディレクトリを短い名前にリネームし、ユーザーフォルダ直下に置きます.
#クロスパイルツールチェーンをリネームしてユーザーフォルダ直下に配置 ~/ --- /arm-gcc
このツールチェーン内のコマンドが置かれたディレクトリへのパスを通すため.bashrcを編集します. 必要であれば.bashrcを読み込みなおします.
# ~/.bashrc #追記 export PATH=$PATH:path_to_arm_gnu_toolchain/bin
$ source ~/.bashrc
arm-none-eabi用のビルドの流れ
まずはNewlibのソースコードを入手します. 面倒なのでミラーからサクッと手に入れました. 公式から入手したい場合ははFTPかhttpを使えと書いてありました.
# ミラーからNewlibのソースを入手 $ git clone https://github.com/bminor/newlib.git
公式 https://sourceware.org/newlib/download.html
ミラー https://github.com/bminor/newlib.git
解凍しユーザー直下に置きましょう. ついでにout-of-sourceビルド用にbuildディレクトリも作っておきましょう.
# out-of-sourceビルドのための配置 ~/ --- /arm-gcc | |-- /new-lib | |__ /build
buildフォルダに入りconfigureスクリプトを叩きます. 以下のオプションを指定すればとりあえずビルド出来ました.
#buildディレクトリに入る $ cd ~/build #configure $ ../newlib/newlib/configure --target=arm-none-eabi --enable-newlib-io-long-long --enable-newlib-register-fini --enable-newlib-retargetable-locking --disable-newlib-supplied-syscalls CC=arm-none-eabi-gcc --host=arm-none-eabi --build=i686-pc-linux-gnu #make $ make
ビルドが無事終了するとbuildディレクトリ直下に libc.a、libg.a、libm.aが生成されます. また、ヘッダファイルは newlib/libc/include に入っています. math.hもこのフォルダに入っています.
また、バイナリのサイズはそれぞれ以下でした.
アーカイブ名 | サイズ |
---|---|
libc.a | 4,680kB |
libg.a | 4.680kB |
libm.a | 1,718kB |
arm-none-eabi用のビルドは出来ましたが、 目的のCortex-M0では動きませんでした (実行可能ファイルを作ることは出来たが、正常に動作しませんでした).
動かなかった原因
正常に動くNewlibと何が違うのかを探るため、STM32CubeIDEに付属するツールチェーンに同梱されているNewlibのバイナリと、自分でビルドしたNewlibのバイナリをreadelfして差分を取りました. なお、ツールチェーンには各アーキテクチャごとにバイナリが分かれているため、一度-Wl,--verboseオプションをつけてビルドすることでCortex-M0用にリンクされるバイナリを同定しました. WinMergeで両者のreadelfの結果を比較すると、以下の決定的な違いが見つかりました.
つまり、arm-none-eabiの中でもアーキテクチャが分かれているので、Cortex-M0用のアーキテクチャを明示的に指定しないといけないということですね. 前述のNewlibビルドにおいてarm-none-eabi以外にそれらしきものを指定した覚えはないので、デフォルトではARM v6Kというアーキテクチャ用にビルドされるのでしょう.
Cortex-M0用にビルド
ここが躓きポイントだったのですが、アーキテクチャの指定は configure時ではなく、make時に行います . これはアーキテクチャの指定の方法が汎用的なものではなくマシン依存オプションというcpuごとに異なるものだからだと推測されます. 前述のconfigureに加え、make時には以下のコマンドを打つことでCortex-M0用のバイナリをビルドすることが出来ました.
$ make CFLAGS="-mcpu=cortex-m0"
実際にCortex-M0で試した記事がこちらになります.
まとめ
とりあえず以下のおまじないでCortex-M0用に動くNewlibがビルド出来ました.
# configure $ configure --target=arm-none-eabi --enable-newlib-io-long-long --enable-newlib-register-fini --enable-newlib-retargetable-locking --disable-newlib-supplied-syscalls CC=arm-none-eabi-gcc --host=arm-none-eabi --build=i686-pc-linux-gnu $ make CFLAGS="-mcpu=cortex-m0"