鳥なき里のマイコン屋(48) ARM Mbed その6、Make-GCC-ARMへイクスポート

Mbed-CLIをも少し使ってみるつもりでおりました。Mbed-CLIはOS5向けのようですが、OS2も可能という記述を見つけたので、「Mbed-CLI用」のOS2サンプルプロジェクトのimportをMbed-CLIから試みたのですが、途中で落ちてしまいました。どうせコマンドラインで作業するのであれば、Web環境から既にツールチェーンMake-GCC-ARM宛てでローカルディレクトリにイクスポート済のOS2のサンプルプロジェクトをビルドするのと大差なくね、ということで、そちらでビルドからgdbデバッグまでを通しでやってみました。実質の作業時間5分くらい。あまり簡単すぎて、本当に良いのだろうか、とも思いましたが、問題ありません。ちゃんと動いていますよ。

イクスポートしたのは、サンプルプロジェクトをチョイ変しただけの以下のような小さなプログラムです。LED2をチカチカするたびに、USBシリアルの先に10進数のループカウンタをprintする、というもの。

#include "mbed.h"

DigitalOut myled(LED2);
Serial pc(USBTX, USBRX);

int main() {
    unsigned int count = 0;
    while(1) {
        if (count > 1000) count = 0;
        pc.printf("%d\r\n",count);
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(1.0);
        count++;
    }
}

Makeするにあたっては、gdbで一応ブレークして、中身の変数を表示させるなどしたい。そこでイクスポート時に生成されたMakefileの中身をば見てみれば、

1行1オプションでとても見通しの良いMakefile

でした。オプティマイズと、デバッグのオプションを見てみれば

  • -Os
  • -g1

指定でした。やはりFlashベースのマイコン向けなので、オプティマイズはサイズ優先、デバッグは何かあったときの必要最小限の指定でした。本来、マイコンなのでそうあるべきですが、今回は、ソースコードデバッグでちゃんとgdbしたいので、敢えて

  • -O0
  • -g2

に変更してMakeしました。ほんと Make 一発。Mbed-CLIでOS5アプリをビルドしたときには結構長い時間がかかりました。OS部分からみなコンパイルかけていたためだと思います。しかし、WebからOS2プロジェクトをイクスポートした場合、前にも書きましたが、OSの部品はオブジェクトファイルで出力され、ユーザコードでオブジェクト内の関数呼ぶためのヘッダがついてくるだけです。よって、上の短いソースコードをコンパイルした後は、オブジェクトとリンクするだけ。makeに何秒もかかりません。

BUILDディレクトリを見れば、bin, hex, elf とオブジェクトが出来ていました。binをUSB経由でボードに送り込めばそのまま動作しますが、今回はgdbで動かすので、まずはボードをUSBで接続した後、 OpenOCD を起動しておきます。

openocd -f st_nucleo_f0.cfg -f stlink-v2-1.cfg -c init -c "reset init"

本当は、cfgファイルはOpenOCDのスクリプトパスの下に入っているのですが、パス名長いので省略しました。

次に、プログラムがUSBシリアルに出力してくる筈の出力を捕まえるためにTeratermを起動、ボードのUSBシリアルが見えている仮想COMポートに接続しておきます。正常に動くとほぼ毎秒くらいに、ループカウンタ値が仮想端末に表示されます。

最後に、3番目のウインドウを開き、gdbを起動

$ arm-none-eabi-gdb オブジェクト名.elf

gdbが起動したら、

(gdb) target remote localhost:3333

(gdb) monitor reset halt (念のため)

(gdb) load

こんな感じでオブジェクトをボードに書き込み完了。後は、gdbの画面コピペを貼り付けておきます(今日は手抜きだな。。。)

(gdb) list main
1 #include "mbed.h"
2
3 DigitalOut myled(LED2);
4 Serial pc(USBTX, USBRX);
5
6 int main() {
7 unsigned int count = 0;
8 while(1) {
9 if (count > 1000) count = 0;
10 pc.printf("%d\r\n",count);
(gdb)
11 myled = 1; // LED is ON
12 wait(0.2); // 200 ms
13 myled = 0; // LED is OFF
14 wait(1.0); // 1 sec
15 count++;
16 }
17 }
(gdb) hbreak 15
Hardware assisted breakpoint 1 at 0x800030c: file ../main.cpp, line 15.
(gdb) continue
Continuing.

Breakpoint 1, main () at ../main.cpp:15
15 count++;
(gdb) print count
$1 = 0
(gdb) c
Continuing.

Breakpoint 1, main () at ../main.cpp:15
15 count++;
(gdb) print count
$2 = 1

抜けるときは、こないだもやりましたが

(gdb) monitor shutdown

でOpenOCDを落としておき、quit.

鳥なき里のマイコン屋(47) Arm Mbedその5 OpenOCD+GDBでデバッグ へ戻る

鳥なき里のマイコン屋(49) Arm Mbedその7 classの行方 へ進む