Mbed OS 2のサポートがいつ終わっても良いようにローカル環境を構築する方法

この記事は古い内容です。改訂版を作成しましたので、そちらをご参照ください。

https://qiita.com/toyowata/items/86a312158187cafe3f7d


## はじめに

最初のバージョンのMbed OS 5 がリリースされてから約3年が経ちました。Mbed OS 5 では、四半期ごとに比較的大きな機能を追加するFeature releaseと、二週間ごとに新しいボードの追加やバグフィックスが含まれるPatch releaseを行っています。

https://os.mbed.com/docs/mbed-os/v5.12/introduction/how-we-release-arm-mbed-os.html

一方で、Mbed OS 2 (Mbed classic)は、メンテナンスリリースのサイクルは Mbed OS 5ほど頻繁ではありません。最近は、三か月に1度のリリースが行われています。

主要なライブラリやMbed OS 5 への移行がほぼ終了していますが、個人での開発や古いソフトウェア資産の継続利用の目的で、Mbed OS 2 を使い続けなければならないケースもあるかもしれません。

ここでは、オンラインコンパイラではなくローカルPCにMbed OS 2のビルド環境を構築し、Mbed 開発サイトの状態になるべく依存しない閉じた環境での運用方法を説明します。古いプロジェクトもローカル環境で保守することが出来ます。

Mbed対応ボードは、スイッチサイエンス製のmbed LPC1114FN28を使用します。

## 事前準備

### mbed-cliのインストール

使用するPCにコマンドラインの開発環境mbed-cliをインストールします。こちらの情報を参考にしてください。
https://os.mbed.com/docs/mbed-os/v5.12/tools/installation-and-setup.html

### DAPLinkのアップデート

せっかくなので、MbedボードのインタフェースファームウェアDAPLinkも最新版にアップデートしておきます。もちろんそのままでも使用できますが、Windows 10でのシリアルドライバのインストールが不要だったり、既存の不具合が修正されていたり様々なメリットがあります。

最新版のDAPLinkインターフェースファームウェアはこちらです。
https://armmbed.github.io/DAPLink/

`Name of board`の部分に使用するMbedボードの名称を入力すると、適切なファームウェアをダウンロードすることが出来ます。

ファームウェアアップデートの方法は、こちらを参考にしてください。
https://os.mbed.com/teams/Switch-Science/wiki/Firmware-LPC1114FN28

ファームウェアのバージョンは、`mbedls`コマンドで知ることが出来ます。

（変更前）

```
PS C:\work> mbedls
| platform_name | platform_name_unique | mount_point | serial_port | target_id                                        | daplink_version |
|---------------|----------------------|-------------|-------------|--------------------------------------------------|-----------------|
| LPC1114       | LPC1114[0]           | D:          | COM19       | 11140000e48dccfb00000000000000000000000097969902 | 0241            |
```

（変更後）

```
PS C:\work> mbedls
| platform_name | platform_name_unique | mount_point | serial_port | target_id                                        | daplink_version |
|---------------|----------------------|-------------|-------------|--------------------------------------------------|-----------------|
| LPC1114       | LPC1114[0]           | D:          | COM20       | 11140001e48dccfb00000000000000000000000097969902 | 0254            |
```

`v0241`から`v0254`にアップデートすることが出来ました。

## プログラムのダウンロードとビルド

使用するプログラムもローカル環境にダウンロードする必要があります。
ここでは、mbed_blinkyをダウンロードしてみます。
https://os.mbed.com/teams/mbed/code/mbed_blinky/

このページの右部分にある、Clone repository to desktop: に記載されている文字列をコピーし、コマンドプロンプトやPowerShellのウィンドウにペーストして実行します。

```
PS C:\work> hg clone https://MACRUM@os.mbed.com/teams/mbed/code/mbed_blinky/
複製先ディレクトリ: mbed_blinky
全リビジョンを取得中
リビジョンを追加中
マニフェストを追加中
ファイルの変更を追加中
25 個のリビジョン(28 の変更を 3 ファイルに適用)を追加
ブランチ default へ更新中
ファイルの更新数 2、 マージ数 0、 削除数 0、 衝突未解消数 0
PS C:\work>
```

このコマンドでは、プログラムで使用しているソースファイルと、Mbedライブラリへのリンクが記載されたファイルがダウンロードされます。

ビルドに必要なファイルは、`mbed deploy`コマンドで取得できます。Mbed OS 2の場合は、すべてのターゲットのプリビルド済みバイナリが含まれるので、ファイルのダウンロードにかなり時間がかかります。私の環境では、15分ほどかかりました。

```
PS C:\work> cd .\mbed_blinky\
PS C:\work\mbed_blinky> mbed deploy
[mbed] Working path "C:\work\mbed_blinky" (program)
[mbed] Adding library "mbed" from "https://os.mbed.com/users/mbed_official/code/mbed/builds" at rev #3a7713b1edbc
[mbed] Downloading library build "3a7713b1edbc" (might take a while)
[mbed] Unpacking library build "3a7713b1edbc" in "C:\work\mbed_blinky\mbed"
[mbed] Couldn't find build tools in your program. Downloading the mbed 2.0 SDK tools...
[mbed] Updating the mbed 2.0 SDK tools...
PS C:\work\mbed_blinky>
```

`mbed compile`コマンドでビルドします。ここでは、`-t gcc_arm`を指定してGCCを使用していますが、ライセンスをお持ちの場合は、ARMコンパイラも使用可能です（`-t ARM` を指定）。

```
PS C:\work\mbed_blinky> mbed compile -m lpc1114 -t gcc_arm
[mbed] Working path "C:\work\mbed_blinky" (program)
[mbed] WARNING: Could not find mbed program in current path "C:\work\mbed_blinky".
       You can fix this by calling "mbed new ." in the root of your program.
---
Building project mbed_blinky (LPC1114, GCC_ARM)
Scan: mbed_blinky
Compile [100.0%]: main.cpp
[Fatal Error] main.cpp@1,18: mbed.h: No such file or directory
[ERROR] .\main.cpp:1:18: fatal error: mbed.h: No such file or directory
 #include "mbed.h"
                  ^
compilation terminated.

[mbed] ERROR: "c:\python27\python.exe" returned error.
       Code: 1
       Path: "C:\work\mbed_blinky"
       Command: "c:\python27\python.exe -u C:\work\mbed_blinky\.temp\tools\make.py -t gcc_arm -m lpc1114 --source . --build .\BUILD\LPC1114\GCC_ARM"
       Tip: You could retry the last command with "-v" flag for verbose output
```

おっと、エラーが出てしまいました。多分、ここでレポートしたのと同じ原因だと思います。
https://github.com/ARMmbed/mbed-cli/issues/805#issuecomment-465017205

なので、mbedライブラリのバージョンを少し戻します。上記レポートで問題のなかったバージョン`e95d10626187`を使います。バージョンを指定して再度ダウンロードします。

まず今のバージョンの確認

```
PS C:\work\mbed_blinky> mbed ls
[mbed] Working path "C:\work\mbed_blinky" (program)
mbed_blinky (#a9f5798bf27e)
`- mbed (#3a7713b1edbc)
```

Mbedライブラリバージョンを再指定してダウンロード

```
PS C:\work\mbed_blinky> cd mbed
PS C:\work\mbed_blinky\mbed> mbed update e95d10626187
[mbed] Working path "C:\work\mbed_blinky\mbed" (library)
[mbed] Program path "C:\work\mbed_blinky\mbed"
[mbed] Updating library "mbed" to rev #e95d10626187
[mbed] Downloading library build "e95d10626187" (might take a while)
[mbed] Unpacking library build "e95d10626187" in "C:\work\mbed_blinky\mbed"
[mbed] Updating reference "mbed" -> "https://os.mbed.com/users/mbed_official/code/mbed/builds/e95d10626187"
[mbed] WARNING: Cannot find the mbed tools directory in "C:\work\mbed_blinky\mbed"
```

バージョンの確認

```
PS C:\work\mbed_blinky\mbed> cd ..
PS C:\work\mbed_blinky> mbed ls
[mbed] Working path "C:\work\mbed_blinky" (program)
mbed_blinky (#7f14b70fc9ef, tag: tip)
`- mbed (#e95d10626187)
```

無事に変更されているのでビルドします。今度は、`-f`オプションをつけて、バイナリをそのままMbedボードのフラッシュメモリに書き込んでみます。LPC1114FN28は、USBケーブルでPCと接続してください。

```
PS C:\work\mbed_blinky> mbed compile -m lpc1114 -t gcc_arm -f
[mbed] Working path "C:\work\mbed_blinky" (program)
[mbed] WARNING: Could not find mbed program in current path "C:\work\mbed_blinky".
       You can fix this by calling "mbed new ." in the root of your program.
---
Using targets from C:\work\mbed_blinky\mbed\e95d10626187\targets.json
Building project mbed_blinky (LPC1114, GCC_ARM)
Scan: mbed_blinky
Compile [100.0%]: main.cpp
Link: mbed_blinky
Elf2Bin: mbed_blinky
| Module            |         .text |     .data |      .bss |
|-------------------|---------------|-----------|-----------|
| BUILD\LPC1114     |     221(+221) |     4(+4) |   16(+16) |
| [fill]            |     208(+208) |     0(+0) |     9(+9) |
| [lib]\c_nano.a    |   3569(+3569) | 100(+100) |   12(+12) |
| [lib]\gcc.a       |   1668(+1668) |     0(+0) |     0(+0) |
| [lib]\mbed.a      |   2937(+2937) |     4(+4) | 183(+183) |
| [lib]\misc        |     244(+244) |   12(+12) |   28(+28) |
| mbed\e95d10626187 |   4041(+4041) | 264(+264) |   32(+32) |
| Subtotals         | 12888(+12888) | 384(+384) | 280(+280) |
Total Static RAM memory (data + bss): 664(+664) bytes
Total Flash memory (text + data): 13272(+13272) bytes

Image: .\BUILD\LPC1114\GCC_ARM\mbed_blinky.bin
        1 個のファイルをコピーしました。
```

これで、フラッシュメモリに書き込まれました。LPC1114FN28のdp14ピンにLEDを接続すると、blinky（Lチカ）が実行されるはずです。

![lpc1114.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75582/a2ddbf72-c046-bb75-4203-df1458adbb49.png)

プログラムを以下のように書き換えて、再度ビルドしてみます。

```cpp
#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);

int main() {
    int cnt = 0;
    printf("hello, Mbed world.\r\n");
    while(1) {
        led1 = !led1;
        led2 = !led1;
        printf("count = %d\r\n", cnt++);
        wait(1);
    }
}
```

mbed-cliはシリアルターミナル機能も含まれているので、以下のようにしてターゲットからのシリアル出力を表示することが出来ます。

```
PS C:\work\mbed_blinky> mbed sterm
[mbed] Working path "C:\work\mbed_blinky" (program)
[mbed] Detecting connected targets/boards to your system...
[mbed] Opening serial terminal to "LPC1114"
--- Terminal on COM20 - 9600,8,N,1 ---
hello, Mbed world.
count = 0
count = 1
count = 2
count = 3
count = 4
count = 5
count = 6
count = 7
--- [QUIT] ---
```

### 自分のプログラムを使用する場合

基本的にやり方は全く同じです。自分のプログラムをpublishして、そのプログラムをデスクトップにクローンします。他人にプログラムを公開したくない場合は、public (unlisted) または private 属性でpublishしてください。

https://os.mbed.com/docs/mbed-os/v5.12/tools/publishing-code.html


以上です。

## トラブルシューティング

### mbed-cli で utf8 関連のエラーが出る場合

mbed-cliのバージョンが古いと、以下のようなエラーが出る場合があります。

```
PS C:\work\eVY1_SMF_player_mod> mbed deploy
[mbed] Adding library "DirectoryList" from "https://developer.mbed.org/users/okano/code/DirectoryList" at rev #0233769f991c
[mbed] ERROR: Unknown Error: 'utf8' codec can't decode byte 0x91 in position 0: invalid start byte
---
PS C:\work\eVY1_SMF_player_mod> mbed --version
1.8.2
```
このような場合は、mbed-cliを最新版にアップデートします。

```
PS C:\work\eVY1_SMF_player_mod> pip install -U mbed-cli
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.
Collecting mbed-cli
  Using cached https://files.pythonhosted.org/packages/f8/2d/a40a9ef436094dd6fcdf05fd010446baa5c336d36f97ff50415208f31f18/mbed-cli-1.10.0.tar.gz
Installing collected packages: mbed-cli
  Found existing installation: mbed-cli 1.8.2
    Uninstalling mbed-cli-1.8.2:
      Successfully uninstalled mbed-cli-1.8.2
  Running setup.py install for mbed-cli ... done
Successfully installed mbed-cli-1.10.0
PS C:\work\mbed_blinky> mbed --version
1.10.0
```
これで、utf8関連のエラーは発生しません。

### ライブラリのリビジョンが見つからない場合

`mbed deploy`した時にライブラリのリビジョンが見つからない場合があります（依存関係が解決できない）。

```
PS C:\work> hg clone https://MACRUM@os.mbed.com/users/MACRUM/code/eVY1_SMF_player_mod/
複製先ディレクトリ: eVY1_SMF_player_mod
全リビジョンを取得中
リビジョンを追加中
マニフェストを追加中
ファイルの変更を追加中
5 個のリビジョン(9 の変更を 4 ファイルに適用)を追加
ブランチ default へ更新中
ファイルの更新数 4、 マージ数 0、 削除数 0、 衝突未解消数 0
PS C:\work> cd .\eVY1_SMF_player_mod\
PS C:\work\eVY1_SMF_player_mod> mbed deploy
[mbed] Working path "C:\work\eVY1_SMF_player_mod" (program)
[mbed] Adding library "DirectoryList" from "https://developer.mbed.org/users/okano/code/DirectoryList" at rev #0233769f991c
[mbed] Adding library "mbed" from "https://mbed.org/users/mbed_official/code/mbed/builds" at rev #4336505e4b1c
[mbed] Downloading library build "4336505e4b1c" (might take a while)
[mbed] Unpacking library build "4336505e4b1c" in "C:\work\eVY1_SMF_player_mod\mbed"
[mbed] Adding library "SDFileSystem" from "https://developer.mbed.org/teams/mbed/code/SDFileSystem" at rev #7b35d1709458
[mbed] Adding library "SDFileSystem\FATFileSystem" from "https://mbed.org/users/mbed_official/code/FATFileSystem" at rev #e960e2b81a3c
中止: 'e960e2b81a3c' は未知のリビジョンです!
中止: 'e960e2b81a3c' は未知のリビジョンです!
[mbed] ERROR: Unable to update "FATFileSystem" to rev #e960e2b81a3c
```

この場合は、SDFileSystem (7b35d1709458) からリンクしているFATFileSystem (e960e2b81a3c)が見つからないようです。SDFileSystem を最新バージョンに更新します。
ここを見ると、SDFileSystemの最新バージョンは、8db0d3b02cecのようです。
https://os.mbed.com/teams/mbed/code/SDFileSystem/shortlog/

```
PS C:\work\eVY1_SMF_player_mod> cd .\SDFileSystem\
PS C:\work\eVY1_SMF_player_mod\SDFileSystem> mbed update 8db0d3b02cec
[mbed] Working path "C:\work\eVY1_SMF_player_mod\SDFileSystem" (library)
[mbed] Program path "C:\work\eVY1_SMF_player_mod\SDFileSystem"
[mbed] Updating library "SDFileSystem" to rev #8db0d3b02cec (tag: tip)
[mbed] Updating reference "SDFileSystem" -> "https://developer.mbed.org/teams/mbed/code/SDFileSystem/#8db0d3b02cec"
[mbed] Removing library "FATFileSystem" (changed URL). Will add from new URL.
[mbed] Adding library "FATFileSystem" from "https://developer.mbed.org/teams/mbed-official/code/FATFileSystem" at rev #e2ab678eb692
[mbed] WARNING: Cannot find the mbed tools directory in "C:\work\eVY1_SMF_player_mod\SDFileSystem"
```

念のため、再度`mbed deploy`を実行します。

```
PS C:\work\eVY1_SMF_player_mod\SDFileSystem> cd ..
PS C:\work\eVY1_SMF_player_mod> mbed deploy
[mbed] Working path "C:\work\eVY1_SMF_player_mod" (program)
[mbed] Updating library "DirectoryList" to rev #0233769f991c (tag: tip)
[mbed] Updating library "mbed" to rev #4336505e4b1c
[mbed] Updating library "SDFileSystem" to rev #8db0d3b02cec (tag: tip)
[mbed] Updating library "SDFileSystem\FATFileSystem" to rev #e2ab678eb692
[mbed] Couldn't find build tools in your program. Downloading the mbed 2.0 SDK tools...
[mbed] Updating the mbed 2.0 SDK tools...
```

無事にライブラリを取得できました。

## その他
### Mbed OS ２から5への移行方法
https://os.mbed.com/docs/mbed-os/v5.12/tutorials/migrating-to-mbed-os-5.html