JF1DIR業務日誌(はてなblog版)

アマチュア無線局JF1DIRのアクティビティをつづっています。

mbed cliをlinuxで構築してみた

これまで書いてきたマイコン記事の通り、ふだんの工作に使っているマイコンはARM mbedです。世の中で最も出回っているマイコンであり、安価で手に入りやすく、それでいてクラウドmbed環境はとても使いやすいからです。しかし日本ではPICやAVR(Arduino)に負けるらしく、日本語で情報を入手できにくい感があります。
今回オフラインコンパイラであるmbed OS 5のmbed CLIコマンドラインインターフェイス)をLinux上に環境構築してみたので、備忘録代わりにブログに記してみます。STの安価なmbedボードであるNUCLEOシリーズをCLIでビルドする際、ハマってしまった点がいくつかあったのでその解決法も記してみます。
まずは、こちらのシステム環境です。

Ubuntu 16.04.3 LTS
Linux kernel 4.4.0-92-generic 64bit
GCC 5.4.0 20160609
Python 2.7.12

usbmountのインストール

USBをマウントして実行権付きで読み書きするパッケージをインストールします。

$sudo apt-get install usbmount

mbedボードをUSBポートに差し込んでUSBストレージとして認識させ、dfコマンドで見ると、/media/usb0などが見えるはずです。しかしこのままではファイルのユーザーがrootなので多少使いにくいです。そこで/etc/usbmount/usbmount.confを編集してみます。

MOUNTOPTIONS="sync,nodev,noatime,nodiratime"
FS_MOUNTOPTIONS="-fstype=vfat,uid=yuji,gid=yuji"

この2箇所を書き換えると実行権が自分のものになるので使いやすくなります(あくまで個人環境で使う場合の設定です)。

Python 2.7を入れる

mbedはpythonスクリプトを多用するので入ってなければPythonを入れておきます。デフォルトでpython3が動く環境だとエラーになるので注意して下さい。Pythonのモジュールインストーラーであるpipも使うので、

$sudo apt-get install python2.7 python-pip

としておきます。続いてmbed cliをpipでインストール。

$sudo pip install mbed-cli

ARM GCC, mercurial, gitをインストール

ツールチェーンであるARM GCC、レポジトリ管理のMercuialと必要ならばGitも入れておきます。

$sudo apt-get install gcc-arm-none-eabi mercurial git

Lチカのプロジェクトを作ってコンパイル

定番テストプログラムである「Lチカ」を動かしてみましょう。オンラインのmbed IDEと同様プロジェクトとしてディレクトリを用意しておきます。

$mkdir mbed-test
$cd mbed-test
$mbed new .

ここでmbed-osのすべてのライブラリをgithubからダウンロードしてくるので結構時間がかかります。
次に、ここのフォルダでUSBにマウントされているmbedボードを認識させます。ここではSTのNucleo F411REをつなげてみた例です。

$mbed detect

[mbed] Detected NUCLEO_F411RE, port /dev/ttyACM0, mounted /media/usb0
[mbed] Supported toolchains for NUCLEO_F411RE
+---------------+-----------+-----------+-----------+-----------+-----------+-----------+
| Target        | mbed OS 2 | mbed OS 5 |    ARM    |  GCC_ARM  |    IAR    |   ARMC6   |
+---------------+-----------+-----------+-----------+-----------+-----------+-----------+
| NUCLEO_F411RE | Supported | Supported | Supported | Supported | Supported | Supported |
+---------------+-----------+-----------+-----------+-----------+-----------+-----------+
Supported targets: 1
Supported toolchains: 4

もしNucleo 4xxを使っていて正しく認識されないようならば、ST-LINKをファームアップしてみて下さい。mbedのページあります。Windows機でST-LINKで接続し(場合によって最新のデバイスドライバが必要かも。場所は先のリンクにあります)、Windows上のファームアップソフトを立ち上げてファームアップできます。
また、この時点で、

[mbed] Auto-installing missing Python modules...

と表示されたら、足りないPythonモジュールがあるようなので、追加で入れておきます。

$sudo pip install -r mbed-os/requirements.txt

まだプロジェクトにプログラムの中身が無いので、Lチカのmain.cppを作っておきます。

#include <mbed.h>
DigitalOut led1(D13);
int main()
{
  led1 = 1;
  while(1) {
    led1 = !led1;
    wait(0.1);
  }
}

D13ピンにLEDのアノードを接続、GNDにカソードを接続しておきます。モジュールとツールチェインの設定を済ませて、ようやくビルドへ。

$mbed target NUCLEO_F411RE
$mbed toochain -G GCC_ARM
$mbed compile

設定とソースに誤りがなければ、

Building project mbed-test (NUCLEO_F411RE, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Compile [  5.8%]: TimerEvent.cpp
Compile [  6.1%]: Timeout.cpp
Compile [  6.4%]: Timer.cpp
・
・
・
Compile [ 99.7%]: stm_spi_api.c
Compile [100.0%]: test_env.cpp
Link: mbed-test
Elf2Bin: mbed-test
+------------------+-------+-------+------+
| Module           | .text | .data | .bss |
+------------------+-------+-------+------+
| [fill]           |   115 |     4 |   11 |
| [lib]/c.a        | 17219 |  2472 |   89 |
| [lib]/gcc.a      |  3120 |     0 |    0 |
| [lib]/misc       |   252 |    16 |   28 |
| main.o           |    80 |     4 |   28 |
| mbed-os/drivers  |   136 |     4 |  100 |
| mbed-os/hal      |   863 |     0 |   26 |
| mbed-os/platform |  1246 |     4 |  270 |
| mbed-os/rtos     |  8539 |   180 | 5988 |
| mbed-os/targets  |  6102 |     4 |  820 |
| Subtotals        | 37672 |  2688 | 7360 |
+------------------+-------+-------+------+
Total Static RAM memory (data + bss): 10048 bytes
Total Flash memory (text + data): 40360 bytes

Image: ./BUILD/NUCLEO_F411RE/GCC_ARM/mbed-test.bin

と表示されbinファイルが生成されます。このファイルをmbedにコピーすれば完了。

$cp ./BUILD/NUCLEO_F411RE/GCC_ARM/mbed-test.bin /media/usb0

無事にLチカが動くはずです。

NUCLEO F746ZGでは最新のtoolchainが必要!

別のmbedボードにつなぎ直して動作するか確かめていたところ、mbed OS 5に対応のSTMのNucleo F746ZGでは、うまくコンパイルできませんでした。

$mbed target NUCLEO_F746ZG
$mbed compile
・
・
・
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: error: /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o): Conflicting CPU architectures 13/1
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o)
collect2: error: ld returned 1 exit status
[ERROR] /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: error: /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o): Conflicting CPU architectures 13/1
/usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/bin/ld: failed to merge target specific data of file /usr/lib/gcc/arm-none-eabi/4.9.3/../../../arm-none-eabi/lib/libc.a(lib_a-setjmp.o)
collect2: error: ld returned 1 exit status

リンカの設定がおかしいの?pythonもモジュールがおかしいのか?いろいろ悩んだり調べてみた挙句、最新のGCC Toolchainを使えば治るっぽいことがわかりました。早速、GNU ARM Embedded Toolchainのページへ行ってLinux版のライブラリをダウンロードしてきました。
これをbunzip2+tarで展開し、展開場所が/usr/localだとすると、そこにパスを通しておくのを忘れずに。

$mbed config -G GCC_ARM_PATH="/usr/local/gcc-arm-none-eabi-6-2017-q2-update/bin"

とし、compileをかけると、

$mbed compile
・
・
・
Compile [100.0%]: test_env.cpp
Link: mbed-test
Elf2Bin: mbed-test
+------------------+-------+-------+-------+
| Module           | .text | .data |  .bss |
+------------------+-------+-------+-------+
| [fill]           |   104 |     4 |    19 |
| [lib]/c.a        | 17219 |  2472 |    89 |
| [lib]/gcc.a      |  3120 |     0 |     0 |
| [lib]/misc       |   252 |    16 |    28 |
| main.o           |    80 |     4 |    28 |
| mbed-os/drivers  |   136 |     4 |   100 |
| mbed-os/features |    44 |     0 | 12556 |
| mbed-os/hal      |   863 |     0 |    26 |
| mbed-os/platform |  1246 |     4 |   270 |
| mbed-os/rtos     |  8809 |   180 |  5988 |
| mbed-os/targets  |  9727 |     4 |  1084 |
| Subtotals        | 41600 |  2688 | 20188 |
+------------------+-------+-------+-------+
Total Static RAM memory (data + bss): 22876 bytes
Total Flash memory (text + data): 44288 bytes

Image: ./BUILD/NUCLEO_F746ZG/GCC_ARM/mbed-test.bin

と、無事にビルドが通りました。

mbed CLIを使ってみて

mbed OS 5に対応していないとダメなのが残念ですが、使い慣れたLinux上のCエディタ(Emacs)でサクサクとコードが書けるのが快適です。mbed OS 5に対応しているNucleoのようなボードでソースのトライアンドエラーを済ませて、またオンラインコンパイラに戻って古いmbedボードを動かす、というのも悪くないと思っています。しかし、mbed-osを一々ダウンロードしてくるのには閉口しました・・・^^;まだまだ洗練度が足りない感じですね。
Windowsにもオフラインコンパイラがほしいですが、CLIではなくWindowsらしくEclipseで動かしてみたいと思います。