BBC micro:bit (V1.5) の C/C++プログラミング - Windows10上のPython3仮想環境で、Mbed CLI オフラインコンパイルができる

# The BBC micro:bit development using the Mbed CLI in a Python3 environment on Widows 10 - this target micro:bit v1.5

BBC micro:bitは、MCUにnRF51822を採用した学習用マイコンボードです。Mbed開発環境を使えば、nRF51822の機能を存分に楽しむことができるでしょう。micro:bit単体はもちろんのこと、電子工作や無線通信など、いろいろと活用方法の幅が広がります。
本記事では、Windows10上でもコンパイルができる Mbed CLI オフラインツールを使って、その開発環境の構築における問題点と解決方法を試行錯誤で説明していきます。

## 主な内容

- Windows10とPython3での問題点
- microbit_blinky サンプル
- microbit-hello-world サンプル
- mbed new (create-only) コマンド
- パッケージ化とテンプレート化

尚、BBC micro:bit V2 が2020年11月25日に日本国内でも発売されましたが、手元にある従来のV1.5で動作確認しています。

# 【問題点】 - Mbed CLI（オフライン）でのmicro:bitプログラミング開発

1. Mbed CLI のツールは、Python2に依存している（2つの仕様変更）
2. Windows10上では、microbit-dalでコンパイルエラーが発生する
3. micro:bit用のmbedライブラリを使う為にコツがいる

## 【原因1】Python3の仕様変更

* Python3では、`basestring`抽象型が廃止された（`b'' != ''`が真となった）  
  → https://docs.python.org/3.1/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit
* Python3では、`dict.has_key()`が廃止された   
  → https://docs.python.org/3.1/whatsnew/3.0.html#builtins

Ptyhon3環境でMbed CLI ツールで、mbedプロジェクトを作成しようとすると、次のようにライブラリのダウンロード中のまま、永久ループに陥ってしまいます。

```mbed_new.cmd
[mbed] Adding library "mbed" from "https://mbed.org/users/mbed_official/code/mbed/builds" at branch/tag "tip"
[mbed] Downloading library build "65be27845400" (might take a while)
```

これは、`mbed-cli/mbed/mbed.py`内のダウンロード関数で、データを1MBずつ読み取っていますが、その`while`ループから抜け出せないためです(`data = inurl.read(1024 * 1024)`で最終的に`data`が`b''`となるが、`b'' != ''`が常に真である為)。

```mbed-cli/mbed/mbed.py
 action("Downloading library build \"%s\" (might take a while)" % rev) 
 inurl = urlopen(url) 
 with open(rev_file, 'wb') as outfd: 
     data = None 
     while data != '': 
         # Download and write the data in 1 MB chunks 
         data = inurl.read(1024 * 1024) 
         outfd.write(data) 
```


また、`dict.has_key()`が廃止された為、mbedプロジェクトをコンパイルしようとすると、次のようにmbed CLI ツールの実行時エラーが発生してしまいます。

```mbed_compile.cmd
AttributeError: 'dict' object has no attribute 'has_key'
```

## 【原因2】ヘッダーファイルBLE.hとble.hの混乱

Windows OSは、通常、ファイル名の大文字と小文字を区別しませんので、ツールチェーン（コンパイラ）がヘッダーファイルのBLE.h(microbit-dal)またはble.h(nrf5 SDK)を正しく検索できずに、コンパイルエラーが発生してしまいます。

## 【原因3】mbed CLI （mbed OS）の仕組み

よくわからないコンパイルエラーが発生します。これは、mbedlibがどのように組み込まれるのか、その仕組みを理解できていないために発生しています。ですので、回避策（コツ）しか思いついていません。m(__)m

# Mbed CLI micro:bit チュートリアル（対策・回避策）

## 事前準備

次の3つのツールをインストールしてください。

1. [Git](https://git-scm.com/) - version 1.9.5 以上
2. [Mercurial](https://www.mercurial-scm.org/) - version 2.2.2 以上
3. [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) - [**6-2017-q2-update**](https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe)  
※ GNU Arm Embedded Toolchainのバージョンに注意してください。  
  → [gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe](https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe)

## Python3環境とその仮想環境の構築

1. Windows10用のPtyhon3インストーラーを[ダウンロードページ](https://www.python.org/downloads/)からダウンロードします。  
   → https://www.python.org/ftp/python/3.9.1/python-3.9.1-amd64.exe
1. ダウンロードしたインストーラーを実行し、Python3(3.9.1)をインストールします。  
   `Add Python 3.9 to PATH`をチェックし、`Install Now`でインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/0317a2d2-79c6-9e62-45d6-9ffa969efeb5.png)

### 仮想環境の構築(virtualenv)

1. コマンドプロンプトで、`py -3 -m pip install --upgrade virtualenv`を実行し、virtualenvをインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/c994d8c8-ea5f-1104-e1db-fa544ce46c46.png)
1. `mkdir c:\workubit`コマンドでフォルダを作成し、作成したフォルダに移動して、`venv`仮想環境（フォルダ）を作成します。  
   コマンド：`py -3 -m virtualenv venv`
1. 仮想環境を有効化するには、`C:\workubit\venv\Scripts\activate.bat`を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/d1d86aec-9a63-0704-fafc-bbe5db1fa638.png)

## Mbed CLI のインストールと設定

Python3仮想環境(venv)で、Mbed CLIと関連ツールをインストールします(`pip install`)。

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
pip install mbed-cli jsonschema pyelftools
mbed --version
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/8a0fa2c1-5436-b2a0-1cdb-a3d3e78af68c.png)

`mbed`コマンドに`GNU Arm Embedded Toolchain`の実行形式ファイルの保存フォルダーを設定します。

```コマンドプロンプト
C:\workubit\venv\Scripts\activate.bat
mbed config --global GCC_ARM_PATH "C:\Program Files (x86)\GNU Tools Arm Embedded\6 2017-q2-update\bin"
mbed config --list
```


## サンプル - microbit_blinky

`microbit_blinky`というLED点滅のサンプルをインポートし、コンパイルしてみます。
コマンドプロンプトを開き、Python3仮想環境を有効化し、mbed CLI ツールを実行します。

``` コマンドプロンプト.cmd
cd c:\workubit
C:\workubit\venv\Scripts\activate.bat

mbed import http://os.mbed.com/teams/BBC/code/microbit_blinky/

cd microbit_blinky
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/e9c82634-157f-94c6-9dcb-4411c21ab590.png)


### mbed CLI ツールの実行時エラー

ところが、`mbed compile ...`でコンパイルコマンドを実行すると、`has_key`属性（メソッド）エラーが発生してしまいます。これは、Python3で、`dict.has_key()`が廃止された為です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/0ec27af9-5815-efc5-bdb8-f87978b95f6c.png)

grepツールで検索すると、次のように3つのモジュールで`has_key()`が使われています。

```grep.txt
□検索条件  "has_key"
検索対象   *.py
フォルダ   C:\workubit\microbit_blinky\.temp\tools
    (サブフォルダも検索)
    (英大文字小文字を区別する)
    (文字コードセットの自動判別)
    (一致した行を出力)


C:\workubit\microbit_blinky\.temp\tools\build_api.py(530,31)  [SJIS]:                 if self.flags.has_key(k):
C:\workubit\microbit_blinky\.temp\tools\build_profiles.py(37,29)  [SJIS]:         if MBED_SDK_REV_MAP.has_key(build):
C:\workubit\microbit_blinky\.temp\tools\project.py(157,31)  [SJIS]:                 if self.flags.has_key(k):
3 個が検索されました。

```

### has_keyの修正方法（パッチあて）

これらを一つずつ手作業で修正しても良いのですが、パッチファイルを用意しましたので、これを使ってください。

**手順１．プロジェクトフォルダにパッチファイルを保存**

`c:\workubit\microbit_blinky`フォルダにファイル名を`has_key.patch`として次のパッチ情報をテキストエディタで保存します。

```has_key.patch
--- ./.temp/tools/build_api.py
+++ ./.temp/tools/build_api.py
@@ -529,3 +529,3 @@
             for k,v in profile_data.items():
-                if self.flags.has_key(k):
+                if k in self.flags:
                     self.flags[k] = v
--- ./.temp/tools/build_profiles.py
+++ ./.temp/tools/build_profiles.py
@@ -36,3 +36,3 @@
     for build in builds:
-        if MBED_SDK_REV_MAP.has_key(build):
+        if build in MBED_SDK_REV_MAP:
             idx = MBED_SDK_REV_MAP[build]
--- ./.temp/tools/project.py
+++ ./.temp/tools/project.py
@@ -156,3 +156,3 @@
             for k,v in profile_data.items():
-                if self.flags.has_key(k):
+                if k in self.flags:
                     self.flags[k] = v

```

**手順２．Git Bashでpatchを実行**

Gitをインストールすると、`patch`コマンドを使用できるようになります。
スタートメニューから`Git`→`Git Bash`を選択し、`MINGW64`(Git Bash)を起動し、次のコマンドを順に実行します。

```git.bash
cd /c/workubit/microbit_blinky
patch -p1 < has_key.patch
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/e0c18e53-9c12-8516-c52c-9ea56e9c5bb7.png)

### コンパイルの再実行

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit\microbit_blinky
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/f9c9249e-9e5c-3cce-ae13-91c9020ce3bd.png)

### ヘッダーファイルエラー

次に出るエラーは、`mbed.h`というヘッダーファイルを見つけられない旨のエラーです。
これは、標準のmbedライブラリーがmicro:bitに対応していないためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/9ac5b567-a30a-c57c-3e9d-f52f24b2a6ec.png)

そこで、Lancaster University が公開している`mbed-src`ライブラリを追加します。
`mbed add ...`でエラーが出ますが、無視します。

``` コマンドプロンプト.cmd
cd c:\workubit\microbit_blinky
C:\workubit\venv\Scripts\activate.bat
mbed add http://os.mbed.com/teams/Lancaster-University/code/mbed-src/
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/ce955bd7-9224-86db-ff77-b1b621d9c425.png)

### まだまだ続くエラー

まだまだ、エラーは続きます。
これは、既存の`mbed`ライブラリと混乱していることが原因かと思われます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/5329509f-930f-b1dd-f264-bdc565ce061e.png)

そこで、`mbed`ライブラリ（フォルダ）を削除して、コンパイルを実行します。

``` コマンドプロンプト.cmd
cd c:\workubit\microbit_blinky
C:\workubit\venv\Scripts\activate.bat
rmdir /s /q  mbed
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/c287daa9-ab88-2c58-7bbd-eca1936dec9f.png)

コンパイルに成功するとHEX形式ファイルが、`.\BUILD\NRF51_MICROBIT\GCC_ARM\microbit_blinky.hex`に生成されるため、それをmicro:bitドライブ（例えば、D:\）へ`copy`コマンドでコピーします。

```コマンドプロンプト.cmd
copy .\BUILD\NRF51_MICROBIT\GCC_ARM\microbit_blinky.hex d:\
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/25601673-2868-8aa8-1c48-c81b1495da0e.png)

これで、やっと、`micro_blinky`をコンパイルしすることができました。micro:bit本体へHEXファイルの転送（コピー）が成功するとLEDディスプレイの右上のドットが１つだけ点滅します。

## 困難な道のり - microbit-hello-world

次に`microbit-hello-world`というサンプルプログラムをコンパイルしてみます。

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit

mbed import http://os.mbed.com/teams/microbit/code/microbit-hello-world

cd microbit-hello-world
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/22dfed7a-16a1-24c3-4ba4-598f80b6fb7a.png)

コンパイルをしてみると、`mbed deploy`コマンドを実行して、依存モジュールとツールをインストールするように促されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/1641164e-ad44-0c29-342b-cfb6d90f9b3a.png)

次のように`mbed deploy`コマンドを実行してもツールが見つからない旨のメッセージが出ます。

```コマンドプロンプト.cmd
mbed deploy
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/795915cd-950d-c0d2-f065-012faf59c42c.png)

`microbit_blinky`との違いを比べてみると、`mbed.bld`ファイルが存在していません。
そこで、次のように`mbed.bld`ファイルを追加し、`mbed deploy`と`mbed compile ...`を実行します。

```コマンドプロンプト.cmd
@echo http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb > mbed.bld
mbed deploy
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/21537ff3-36f3-7c2b-0794-4dde2381605b.png)

`microbit_blinky`と同様に`has_key`属性（メソッド）エラーが発生しますので、`MINGW64`(Git Bash)を起動し、`has_key.patch`ファイルをコピーして、`patch`を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/5d7652a9-eca7-a192-1beb-d1d06d03a4ea.png)

```git.bash
cp /c/workubit/microbit_blinky/has_key.patch /c/workubit/microbit-hello-world/
cd /c/workubit/microbit-hello-world
patch -p1 < has_key.patch
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/5c5ed4ee-1310-16dc-eecd-b67ca8755d6a.png)

さらに、違うエラーが出ますが、これは、`mbed-src`ライブラリを追加すれば、解消します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/3cf4bac7-1db9-0087-e5e9-b21e2e8ee69a.png)

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat

cd c:\workubit\microbit-hello-world
mbed add http://os.mbed.com/teams/Lancaster-University/code/mbed-src/
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/66e75157-42a9-a4d3-8719-62bf3b69e108.png)


## algorithmが見つからない

再度、コンパイルすると、新たに、'algorithm'が見つからない旨のエラーが出ます。これは、`BLE.h`と`ble.h`をWindows OSでは区別できず、コンパイラがヘッダーファイルを正しく検索できないためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/533df30c-df29-4389-9281-20033cf1355a.png)

そこで、小文字の`ble.h`ヘッダーファイルを参照している行を`headers/ble.h`と明示的に親フォルダを追記し、`BLE.h`と区別できるようにします。

ここでも、`sdk_ble_h.patch`ファイルを作成し、`MINGW64`(Git Bash)上で、`patch`を実行します。

```sdk_ble_h.patch
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/ble_services/ble_dfu/ble_dfu.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/ble_services/ble_dfu/ble_dfu.h
@@ -53 +53 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_advdata.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_advdata.h
@@ -48 +48 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_conn_params.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_conn_params.h
@@ -45 +45 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_conn_state.c
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_conn_state.c
@@ -37 +37 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_conn_state.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_conn_state.h
@@ -65 +65 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_gatt_db.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_gatt_db.h
@@ -38 +38 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_srv_common.c
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_srv_common.c
@@ -42 +42 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_srv_common.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/common/ble_srv_common.h
@@ -48 +48 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/device_manager/device_manager.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/device_manager/device_manager.h
@@ -91 +91 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/peer_manager/id_manager.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/ble/peer_manager/id_manager.h
@@ -38 +38 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/softdevice/common/softdevice_handler/ble_stack_handler_types.h
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/softdevice/common/softdevice_handler/ble_stack_handler_types.h
@@ -49 +49 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/softdevice/common/softdevice_handler/softdevice_handler.c
+++ microbit\microbit-dal\nRF51822/nrf51-sdk/source/nordic_sdk/components/softdevice/common/softdevice_handler/softdevice_handler.c
@@ -47 +47 @@
-    #include "ble.h"
+    #include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/source/btle/custom/custom_helper.h
+++ microbit\microbit-dal\nRF51822/source/btle/custom/custom_helper.h
@@ -21 +21 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/source/btle/btle.h
+++ microbit\microbit-dal\nRF51822/source/btle/btle.h
@@ -27 +27 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/source/nRF5xGap.h
+++ microbit\microbit-dal\nRF51822/source/nRF5xGap.h
@@ -38 +38 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\nRF51822/source/nRF5xGattServer.h
+++ microbit\microbit-dal\nRF51822/source/nRF5xGattServer.h
@@ -23 +23 @@
-#include "ble.h" /* nordic ble */
+#include "headers/ble.h" /* nordic ble */
--- microbit\microbit-dal\nRF51822/source/nRF5xServiceDiscovery.h
+++ microbit\microbit-dal\nRF51822/source/nRF5xServiceDiscovery.h
@@ -24 +24 @@
-#include "ble.h"
+#include "headers/ble.h"
--- microbit\microbit-dal\source/bluetooth/MicroBitBLEManager.cpp
+++ microbit\microbit-dal\source/bluetooth/MicroBitBLEManager.cpp
@@ -43 +43 @@
-#include "ble.h"
+#include "headers/ble.h"

```

```git.bash
cd /c/workubit/microbit-hello-world
patch -p1 < sdk_ble_h.patch
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/e349937e-5b6e-96fd-8627-3f2c6a8faddb.png)

## CortexContextSwitch.s のエラー

さらにコンパイルを続けると、`CortexContextSwitch.s`で、エラーが発生します。

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit\microbit-hello-world
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/8ac14f02-1b59-ea44-2d4e-9d22f0fafd45.png)

`microbit-dal`用の`CortexContextSwitch.s`ファイルが用意されていますので、これをコピーします。

```
copy /Y .\microbit\microbit-dal\source\asm\CortexContextSwitch.s.gcc .\microbit\microbit-dal\source\asm\CortexContextSwitch.s
mbed compile -m NRF51_MICROBIT -t GCC_ARM
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/bd6e52e2-57a3-03cb-3341-05b570eb13bb.png)

おっと、`mbed`ライブラリ（フォルダ）を削除しなければいけませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/c97b1abf-0a88-1b14-9e81-20c1dfb9b244.png)

最終的に、コンパイルに成功すると、HEX形式ファイルが生成されますので、これをmicro:bitへ転送（コピー）します。

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit\microbit-hello-world
rmdir /s /q  mbed
mbed compile -m NRF51_MICROBIT -t GCC_ARM

copy .\BUILD\NRF51_MICROBIT\GCC_ARM\microbit-hello-world.hex d:\
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/fb5aa66a-0daa-7280-1ce2-991afe444972.png)

micro:bit本体へHEXファイルの転送（コピー）が成功するとLEDディスプレイに、"HELLO WORLD! :)"と1度だけスクロール表示されます。

## 自力で構築 - microbit_mbedテンプレート化

ここまでのノウハウを踏まえて、改めて、新しくプロジェクトを作成し、コンパイルしてみます。

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat

mbed config --list
REM mbed config --global GCC_ARM_PATH "C:\Program Files (x86)\GNU Tools Arm Embedded\6 2017-q2-update\bin"
REM mbed config --list

cd c:\workubit
mbed new microbit_mbed --create-only --scm=none
cd microbit_mbed

@echo http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb > mbed.bld
mbed deploy

```

ところが、20分を過ぎても、ダウンロードが完了せず、ディスク容量も増えていないように見えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/df318226-897f-e4a4-d5d2-720b993dba56.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/3c0f3f67-5001-8fa4-437d-fb1bd5c11907.png)

これが、`while data != '':`の一番初めの問題点です。これまでと同様にパッチファイルを作成し、`patch`を実行します。

```venv/Lib/site-packages/mbed/mbed_chunk.path
--- ./mbed.py
+++ ./mbed.py
@@ -397 +397 @@
-                    while data != '':
+                    while data != b'':

```

```git.bash
cd /c/workubit/venv/Lib/site-packages/mbed
patch -p1 < mbed_chunk.patch
```

これですべての問題点を解決（回避）したと思いますので、改めて、新規作成します。

```コマンドプロンプト.cmd
rmdir /s /q c:\workubit\microbit_mbed

C:\workubit\venv\Scripts\activate.bat

mbed config --list
REM mbed config --global GCC_ARM_PATH "C:\Program Files (x86)\GNU Tools Arm Embedded\6 2017-q2-update\bin"
REM mbed config --list

cd c:\workubit
mbed new microbit_mbed --create-only --scm=none
cd microbit_mbed

@echo http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb > mbed.bld
mbed deploy

rem mbed config root .
mbed target NRF51_MICROBIT
mbed toolchain GCC_ARM

mbed add https://developer.mbed.org/teams/Lancaster-University/code/microbit/
mbed add http://os.mbed.com/teams/Lancaster-University/code/mbed-src/

copy /Y .\microbit\microbit-dal\source\asm\CortexContextSwitch.s.gcc .\microbit\microbit-dal\source\asm\CortexContextSwitch.s

rmdir /s /q mbed

copy /Y C:\workubit\microbit-hello-world\main.cpp .\
copy /Y C:\workubit\microbit-hello-world\sdk_ble_h.patch .\
copy /Y C:\workubit\microbit-hello-world\has_key.patch .\

>>>bash
cd /c/workubit/microbit_mbed
patch -p1 < has_key.patch
patch -p1 < sdk_ble_h.patch
<<<bash

mbed compile

copy .\BUILD\NRF51_MICROBIT\GCC_ARM\microbit_mbed.hex d:\
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/ce919c4e-50f0-1c5a-eefb-612e52a3fad8.png)

# 今回の成果物 - 完成版

本記事で得たノウハウをPythonパッケージとGitHubテンプレートにしたものがありますので、それを使ってみます。

- Pythonパッケージ  
  [mbedubitwin10 - https://github.com/jp-rad/mbed-microbit-win10-setup.git](https://github.com/jp-rad/mbed-microbit-win10-setup.git)
- GitHubテンプレート  
  [mbed-microbit-template - https://github.com/jp-rad/mbed-microbit-template.git](https://github.com/jp-rad/mbed-microbit-template.git)

## 事前準備

次のツールをインストールしてください（最初から読み進んでいる方は、既にインストール済み）。

1. [Git](https://git-scm.com/) - version 1.9.5 以上
2. [Mercurial](https://www.mercurial-scm.org/) - version 2.2.2 以上
3. [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) - [**6-2017-q2-update**](https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe)  
※ GNU Arm Embedded Toolchainのバージョンに注意してください。  
  → [gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe](https://developer.arm.com/-/media/Files/downloads/gnu-rm/6-2017q2/gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe)
4. [Python3](https://www.python.org/downloads/) - `Add Python 3.x to PATH`のチェックは任意

## 仮想環境の構築(virtualenv)

```コマンドプロンプト.cmd
py -3 -m pip install --upgrade virtualenv
mkdir c:\workubit
cd c:\workubit
py -3 -m virtualenv venv
C:\workubit\venv\Scripts\activate.bat
```

## Mbed CLI と mbedubitwin10 のインストールと設定

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
pip install mbed-cli git+https://github.com/jp-rad/mbed-microbit-win10-setup.git

mbed config --global GCC_ARM_PATH "C:\Program Files (x86)\GNU Tools Arm Embedded\6 2017-q2-update\bin"

```

## GitHubリポジトリの作成

- https://github.com/jp-rad/mbed-microbit-template  
   [→ `Use this template` - https://github.com/jp-rad/mbed-microbit-template/generate](https://github.com/jp-rad/mbed-microbit-template/generate)

## git cloneとコンパイル

```コマンドプロンプト.cmd
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit
git clone <<your repository>>
cd <<your directory>>
mbedubitwin10
mbed compile
copy .\BUILD\NRF51_MICROBIT\GCC_ARM\microbit-mbed.hex d:\
```

# おわりに

- Windows10のPython3環境でMbed CLIを使用する際の問題点と解決策や回避策を検討しました。
- microbit_blinky サンプルとmicrobit-hello-world サンプルをコンパイルし、HEX形式ファイルをmicro:bit本体へ転送（コピー）しました。
- `mbed new`コマンドで、ゼロからプロジェクトを作成・コンパイルしました。
- PythonパッケージやGitHubテンプレートを使って、より簡単にMbed CLIプログラミングができることを確認しました。

## 追伸
この記事を書いている2020年12月31日（日本時間）に、mbed.comサービスが全体的にダウンしています。
オフライン環境一式を手元に保管しておく方が良さそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/1ea75ebc-076d-d2fe-9dd0-01fa979833df.png)