岡野さんのページを参考にmbedのオフライン開発環境を構築しました。
パッケージ管理ソフトHomebrewとXcodeをインストールします。
App Storeを使ってXcodeをインストールした後、最新に更新してください。 mbed cliではXcode Command line Toolsも必要になりますが、mbed cliがインストールを促してくれます。
以下のコマンドでHomebewがインストールされます。
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brewコマンドでpythonとnpmをインストールします。
$ brew install npm
$ brew install python
pythonのインストールで警告がでるので、以下のコマンドを実行します。
$ brew link --overwrite python
次にgit、Mercurial(hg)とGCCをインストールします。
$ brew tap PX4/homebrew-px4
$ brew update
$ brew install git hg gcc-arm-none-eabi
mbed cliはpipコマンドを使ってインストールします。これでmbedオフライン開発環境が整いました。
$ pip install mbed-cli
動作確認のために、Lチカのサンプル(blink)を作成します。
$ mbed new blink --mbedlib
[mbed] Creating new program "blink" (git)
[mbed] Adding library "mbed" from "https://mbed.org/users/mbed_official/code/mbed/builds" at latest revision in the current branch
[mbed] Updating reference "mbed" -> "https://mbed.org/users/mbed_official/code/mbed/builds/tip"
[mbed] Couldn't find build tools in your program. Downloading the mbed 2.0 SDK tools...
[mbed] Auto-installing missing Python modules...
main.cppは、以下の様にしました。
%%writefile blink/main.cpp
#include "mbed.h"
DigitalOut led1(LED1);
int main()
{
while (1) {
led1 = !led1;
wait_ms(500);
}
}
Writing blink/main.cpp
blinkには、以下のディレクトリとファイルができています。 mbedディレクトリには、必要なライブラリやインクルードファイルがダウンロードされるので、Githubには含めていません。
!ls blink
main.cpp mbed mbed.bld mbed_settings.py mbed_settings.pyc
手元の初期のmbed LPC1768をMacに接続してみます。
mbed cliが正しくmbed LPC1768を認識するかdetectコマンドで確認します。
以下の様に入力すると、LPC1768として認識されていることが分かります。
$ mbed detect
[mbed] Detected LPC1768, port /dev/tty.usbmodem1412, mounted /Volumes/MBED
[mbed] Supported toolchains for LPC1768
+---------+-----------+-----------+-----------+-----------+-----------+
| Target | mbed OS 2 | mbed OS 5 | ARM | GCC_ARM | IAR |
+---------+-----------+-----------+-----------+-----------+-----------+
| LPC1768 | Supported | Supported | Supported | Supported | Supported |
+---------+-----------+-----------+-----------+-----------+-----------+
Supported targets: 1
Supported toolchains: 3
それでは、toolchainをGCC_ARM、ターゲットをLPC1768にセットします。
$ mbed toolchain GCC_ARM
[mbed] GCC_ARM now set as default toolchain in program "blink"
$ mbed target LPC1768
[mbed] LPC1768 now set as default target in program "blink"
mbed OS5では不要ですが、mbed OS2ではライブラリのアップデート(新規の場合ダウンロード)が必要です。
mbed 2.0 9bcdf88f62b0のバグでLPC1768のdefault targetが見つかりません。その場合には、以下のコメントに従ってください。
$ mbed update
準備が整ったのでコンパイルを実行します。
$ mbed compile
Building project blink (LPC1768, GCC_ARM)
Scan: .
Scan: mbed
Scan: env
Compile: main.cpp
Link: blink
Elf2Bin: blink
+-----------+-------+-------+------+
| Module | .text | .data | .bss |
+-----------+-------+-------+------+
| Subtotals | 27529 | 2496 | 632 |
+-----------+-------+-------+------+
Allocated Heap: 2048 bytes
Allocated Stack: 3072 bytes
Total Static RAM memory (data + bss): 3128 bytes
Total RAM memory (data + bss + heap + stack): 8248 bytes
Total Flash memory (text + data + misc): 30025 bytes
Image: ./BUILD/LPC1768/GCC_ARM/blink.bin
正常にビルドが完了したので、Imageファイル(blink.bin)をmbedに書き込みmbedのリセットボタンを押します。LEDが1秒間隔で点滅したら成功です。
$ cp ./BUILD/LPC1768/GCC_ARM/blink.bin /Volumes/MBED/
オフラインの特徴であるデバッグ機能について、順を追って説明します。
私の使っていた初期のものでpyocdを使うには、ファームウェアの更新が必要でした。
更新が必要かどうかは、PCにmbedを差してマウントされたディスクにあるMBED.HTMをテキストエディタで開いて確認します。
<!-- mbed Microcontroller Website and Authentication Shortcut -->
<html>
<head>
<meta http-equiv="refresh" content="0; url=http://mbed.org/start?auth=101000000000000000000002F7F0369Ab9b009f73483a04d0f3d5cd7552c12f1&loader=11972&firmware=141212&configuration=4" />
<title>mbed Website Shortcut</title>
</head>
<body></body>
</html>
firmware=xxxxxの番号が1421212よりも小さい場合には、mbedのファームウェアの更新が必要です。
以下のサイトから最新ファームウェア(mbedmicrocontroller_21164.if)をダウンロードし、mbedに書き込んでmbedの電源を入れ直してください。
正常に更新されたら、MBED.HTMのfirmware=141212になっています。
mbedのデバッグには、compile時にデバッグオプションを付けます。
mbed OS2の場合には、-o debug-infoを付けます。既にBUILDがある場合には、削除してからmbed compileを実行してください。
$ mbed compile -o debug-info
mbed 5.2以降の場合には、add --profile=debugを付けます
mbedのデバッグは、pyocdというPythonベースのOn-Chip Debuggerを使って行います。
ターミナルを開いて、以下のコマンドを入力してください。 pyocd-gdbserverが起動し、デバッグの準備をします。
$ pyocd-gdbserver
INFO:root:DAP SWD MODE initialised
INFO:root:ROM table #0 @ 0xe00ff000 cidr=b105100d pidr=0
INFO:root:[0]<e000e000: cidr=b105e00d, pidr=4002bb000, class=14>
WARNING:root:Invalid coresight component, cidr=0x0
INFO:root:[1]<e0001000: cidr=0, pidr=0, component invalid>
INFO:root:[2]<e0002000:FPB cidr=b105e00d, pidr=4002bb003, class=14>
WARNING:root:Invalid coresight component, cidr=0x0
INFO:root:[3]<e0000000: cidr=0, pidr=0, component invalid>
WARNING:root:Invalid coresight component, cidr=0x0
INFO:root:[4]<e0040000: cidr=0, pidr=0, component invalid>
INFO:root:[5]<e0041000: cidr=b105900d, pidr=4002bb924, class=9, devtype=13, devid=0>
INFO:root:CPU core is Cortex-M3
INFO:root:6 hardware breakpoints, 4 literal comparators
INFO:root:4 hardware watchpoints
INFO:root:Telnet: server started on port 4444
INFO:root:GDB server started at port:3333
OpenOCDと同様pyocdも以下の2つのポートを開いてデバッグコマンドを処理します。
次にARM用のDGB(arm-none-eabi-gdb)を起動します。
別のターミナルを開いて、mbedのプロジェクトのあるディレクトリに移動して、以下のコマンドを入力してください。
$ arm-none-eabi-gdb BUILD/LPC1768/GCC_ARM/blink.elf
GNU gdb (GNU Tools for ARM Embedded Processors) 7.10.1.20160923-cvs
Copyright (C) 2015 Free Software Foundation, Inc.
途中省略
Reading symbols from BUILD/LPC1768/GCC_ARM/blink.elf...(no debugging symbols found)...done.
GDBが起動すると(gdb)のプロンプトが表示されますので、ここで以下のコマンドを入力します。
(gdb) target remote :3333
Remote debugging using :3333
0x0000082c in mbed_error_printf (format=0x0 <osRegisterForOsEvents>)
at ../mbed-os/platform/mbed_board.c:72
72 mbed_error_vfprintf(format, arg);
(gdb) load
Loading section .text, size 0x6c3c lma 0x0
Loading section .ARM.exidx, size 0x8 lma 0x6c3c
Loading section .data, size 0x9c0 lma 0x6c44
Start address 0x4c0, load size 30212
Transfer rate: 8 KB/sec, 1777 bytes/write.
(gdb) br main
Breakpoint 1 at 0x6ca: file ./main.cpp, line 8.
(gdb) c
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
Breakpoint 1, main () at ./main.cpp:8
8 led1 = !led1;
(gdb)
以下のGDBコマンドを使ってblinkをデバッグします。
nを入力すると、次の行に進みます。
(gdb) n
9 wait_ms(500);
もう一度cを入力して、8行目で止め、今度はsを入力してみましょう。 DigitalOUt::operator intのreturn read();で止まりました。 led1で値を参照すると、内部ではled1.read()が呼び出されます。
(gdb) c
Continuing.
Breakpoint 1, main () at ./main.cpp:8
8 led1 = !led1;
(gdb) s
mbed::DigitalOut::operator int (this=0x10000bac <led1>)
at ./mbed/25aea2a3f4e3/DigitalOut.h:117
117 return read();
upコマンドでmainの呼び出し元に戻り、プリントコマンドで値を見てみましょう。
(gdb) up
#1 0x000006d0 in main () at ./main.cpp:8
8 led1 = !led1;
(gdb) p led1.read()
$1 = 1
このようにデバッガ(GDB)を使って処理の流れを確認したり、値をみることができます。
デバッガを終了するには、qを入力してください。 本当に終了するか確認してきますので、yを入力するとGDBが終了し、合わせてpyocd-gdbserverも終了します。
(gdb) q
A debugging session is active.
Inferior 1 [Remote target] will be detached.
Quit anyway? (y or n) y
Detaching from program: /Users/take/proj/jupyter/MySageMath/notebook/letsMbed/blink/BUILD/LPC1768/GCC_ARM/blink.elf, Remote target
Ending remote debugging.
コマンドベースのGDBでは、ソースのどの部分を実行しているのかが、いまいち掴みづらいので、Emacsのgdbモードを使ってみましょう。
通常だとEclipseを使ったデバッグに進むのですが、テキストベースのEmacsの方でも十分デバッグができます。
先ほどと同様にpyocd-gdbserverを起動した後、 別のターミナルを開いて、mbedのプロジェクトのあるディレクトリに移動して、以下のコマンドを入力してください。
$ emacs
Welcome to GNU Emacs, a part of the GNU operating system.
Emacsの使い方の説明画面が表示されます。
ここで、ESC xに続いてgdbを入力すると、以下の様に表示されますので、arm-none-eabi-gdb --annotate=1 BUILD/LPC1768/GCC_ARM/blink.elf と入力してください。
Run gdb (like this): gdb --annotate=1
gdbが起動しますので、先ほどと同様に、target remote :3333, load, br main, cを入力すると画面が上下に分割し、上部にgdbのコマンドが表示され、 現在停止している箇所のソースが表示されます。
ここで先ほどと同様にnコマンドを入力すると下部の画面の=>がwait_ms(500);に移動します。
続いて、p leと入力した後にTABを押すと補完され、led1が表示されます。続いて.reの後にTABを押すと.readがでるので、( )を追加して改行するとled1の値を確認することができます。
n, s, cを入力するとgdb画面でスクロールすので、以下の様に実行するとgdb画面には表示されずにnext, stepを実行できます。
詳しくはGDBモードのCheat Sheetを参照してください。
補完機能の他にCtrl-p, Ctrl-nで前のコマンドや次のコマンドに移動したり、 Ctrl-rで文字列検索で過去のコマンドを検索できるので、キー入力が大幅に省略できます。
Emacsを終了する前に、GDBにqを入力してデバッグを終了しましょう。 この後、Ctrl-x, Ctrl-cでEmacsを終了します。