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プログラミング開発
- Mbed CLI のツールは、Python2に依存している(2つの仕様変更)
- Windows10上では、microbit-dalでコンパイルエラーが発生する
- 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] 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'' != ''
が常に真である為)。
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 ツールの実行時エラーが発生してしまいます。
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つのツールをインストールしてください。
- Git - version 1.9.5 以上
- Mercurial - version 2.2.2 以上
-
GNU Arm Embedded Toolchain - 6-2017-q2-update
※ GNU Arm Embedded Toolchainのバージョンに注意してください。
→ gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe
Python3環境とその仮想環境の構築
- Windows10用のPtyhon3インストーラーをダウンロードページからダウンロードします。
→ https://www.python.org/ftp/python/3.9.1/python-3.9.1-amd64.exe - ダウンロードしたインストーラーを実行し、Python3(3.9.1)をインストールします。
Add Python 3.9 to PATH
をチェックし、Install Now
でインストールします。
仮想環境の構築(virtualenv)
- コマンドプロンプトで、
py -3 -m pip install --upgrade virtualenv
を実行し、virtualenvをインストールします。 -
mkdir c:\workubit
コマンドでフォルダを作成し、作成したフォルダに移動して、venv
仮想環境(フォルダ)を作成します。
コマンド:py -3 -m virtualenv venv
- 仮想環境を有効化するには、
C:\workubit\venv\Scripts\activate.bat
を実行します。
Mbed CLI のインストールと設定
Python3仮想環境(venv)で、Mbed CLIと関連ツールをインストールします(pip install
)。
C:\workubit\venv\Scripts\activate.bat
pip install mbed-cli jsonschema pyelftools
mbed --version
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 ツールを実行します。
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
mbed CLI ツールの実行時エラー
ところが、mbed compile ...
でコンパイルコマンドを実行すると、has_key
属性(メソッド)エラーが発生してしまいます。これは、Python3で、dict.has_key()
が廃止された為です。
grepツールで検索すると、次のように3つのモジュールでhas_key()
が使われています。
□検索条件 "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の修正方法(パッチあて)
これらを一つずつ手作業で修正しても良いのですが、パッチファイルを用意しましたので、これを使ってください。
手順1.プロジェクトフォルダにパッチファイルを保存
c:\workubit\microbit_blinky
フォルダにファイル名を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
手順2.Git Bashでpatchを実行
Gitをインストールすると、patch
コマンドを使用できるようになります。
スタートメニューからGit
→Git Bash
を選択し、MINGW64
(Git Bash)を起動し、次のコマンドを順に実行します。
cd /c/workubit/microbit_blinky
patch -p1 < has_key.patch
コンパイルの再実行
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit\microbit_blinky
mbed compile -m NRF51_MICROBIT -t GCC_ARM
ヘッダーファイルエラー
次に出るエラーは、mbed.h
というヘッダーファイルを見つけられない旨のエラーです。
これは、標準のmbedライブラリーがmicro:bitに対応していないためです。
そこで、Lancaster University が公開しているmbed-src
ライブラリを追加します。
mbed add ...
でエラーが出ますが、無視します。
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
まだまだ続くエラー
まだまだ、エラーは続きます。
これは、既存のmbed
ライブラリと混乱していることが原因かと思われます。
そこで、mbed
ライブラリ(フォルダ)を削除して、コンパイルを実行します。
cd c:\workubit\microbit_blinky
C:\workubit\venv\Scripts\activate.bat
rmdir /s /q mbed
mbed compile -m NRF51_MICROBIT -t GCC_ARM
コンパイルに成功するとHEX形式ファイルが、.\BUILD\NRF51_MICROBIT\GCC_ARM\microbit_blinky.hex
に生成されるため、それをmicro:bitドライブ(例えば、D:\)へcopy
コマンドでコピーします。
copy .\BUILD\NRF51_MICROBIT\GCC_ARM\microbit_blinky.hex d:\
これで、やっと、micro_blinky
をコンパイルしすることができました。micro:bit本体へHEXファイルの転送(コピー)が成功するとLEDディスプレイの右上のドットが1つだけ点滅します。
困難な道のり - microbit-hello-world
次にmicrobit-hello-world
というサンプルプログラムをコンパイルしてみます。
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
コンパイルをしてみると、mbed deploy
コマンドを実行して、依存モジュールとツールをインストールするように促されます。
次のようにmbed deploy
コマンドを実行してもツールが見つからない旨のメッセージが出ます。
mbed deploy
microbit_blinky
との違いを比べてみると、mbed.bld
ファイルが存在していません。
そこで、次のようにmbed.bld
ファイルを追加し、mbed deploy
とmbed compile ...
を実行します。
@echo http://mbed.org/users/mbed_official/code/mbed/builds/87f2f5183dfb > mbed.bld
mbed deploy
mbed compile -m NRF51_MICROBIT -t GCC_ARM
microbit_blinky
と同様にhas_key
属性(メソッド)エラーが発生しますので、MINGW64
(Git Bash)を起動し、has_key.patch
ファイルをコピーして、patch
を実行します。
cp /c/workubit/microbit_blinky/has_key.patch /c/workubit/microbit-hello-world/
cd /c/workubit/microbit-hello-world
patch -p1 < has_key.patch
さらに、違うエラーが出ますが、これは、mbed-src
ライブラリを追加すれば、解消します。
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
algorithmが見つからない
再度、コンパイルすると、新たに、'algorithm'が見つからない旨のエラーが出ます。これは、BLE.h
とble.h
をWindows OSでは区別できず、コンパイラがヘッダーファイルを正しく検索できないためです。
そこで、小文字のble.h
ヘッダーファイルを参照している行をheaders/ble.h
と明示的に親フォルダを追記し、BLE.h
と区別できるようにします。
ここでも、sdk_ble_h.patch
ファイルを作成し、MINGW64
(Git Bash)上で、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"
cd /c/workubit/microbit-hello-world
patch -p1 < sdk_ble_h.patch
CortexContextSwitch.s のエラー
さらにコンパイルを続けると、CortexContextSwitch.s
で、エラーが発生します。
C:\workubit\venv\Scripts\activate.bat
cd c:\workubit\microbit-hello-world
mbed compile -m NRF51_MICROBIT -t GCC_ARM
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
おっと、mbed
ライブラリ(フォルダ)を削除しなければいけませんでした。
最終的に、コンパイルに成功すると、HEX形式ファイルが生成されますので、これをmicro:bitへ転送(コピー)します。
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:\
micro:bit本体へHEXファイルの転送(コピー)が成功するとLEDディスプレイに、"HELLO WORLD! :)"と1度だけスクロール表示されます。
自力で構築 - 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
ところが、20分を過ぎても、ダウンロードが完了せず、ディスク容量も増えていないように見えます。
これが、while data != '':
の一番初めの問題点です。これまでと同様にパッチファイルを作成し、patch
を実行します。
--- ./mbed.py
+++ ./mbed.py
@@ -397 +397 @@
- while data != '':
+ while data != b'':
cd /c/workubit/venv/Lib/site-packages/mbed
patch -p1 < mbed_chunk.patch
これですべての問題点を解決(回避)したと思いますので、改めて、新規作成します。
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:\
今回の成果物 - 完成版
本記事で得たノウハウをPythonパッケージとGitHubテンプレートにしたものがありますので、それを使ってみます。
- Pythonパッケージ
mbedubitwin10 - https://github.com/jp-rad/mbed-microbit-win10-setup.git - GitHubテンプレート
mbed-microbit-template - https://github.com/jp-rad/mbed-microbit-template.git
事前準備
次のツールをインストールしてください(最初から読み進んでいる方は、既にインストール済み)。
- Git - version 1.9.5 以上
- Mercurial - version 2.2.2 以上
-
GNU Arm Embedded Toolchain - 6-2017-q2-update
※ GNU Arm Embedded Toolchainのバージョンに注意してください。
→ gcc-arm-none-eabi-6-2017-q2-update-win32-sha2.exe -
Python3 -
Add Python 3.x to PATH
のチェックは任意
仮想環境の構築(virtualenv)
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 のインストールと設定
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
git cloneとコンパイル
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サービスが全体的にダウンしています。
オフライン環境一式を手元に保管しておく方が良さそうです。