Debugging HiFive1 program built with Zephyr OS, on Eclipse IDE.
昨日は Zephyr OS 環境を使って SiFive HiFive1 のソフトを書く練習をしてみました。今日は、ビルドしたコードを Eclipse 上の GDB でデバッグしてみましょう。
こちらでいろいろ調べてみると、ARM ターゲットのデバッグはうまく Zephyr(zephyr-sdk-0.10.3)でサポートされているようなのですが、どうも RISC-V の対応はまだまだのようです。実際 HiFive1 でも、Zephyr のコマンド west build や west flash はできるのですが、west debug –runner openocd はできません。。。(エラーになります。)
そんなことも言っていられない(?)ので、いろいろ試行錯誤してみました。
GDB コマンドラインでデバッグ
まずは、Eclipse を使わずにコマンドラインでデバッグしてみます。プログラムは、昨日作ったこれ(LED ホワホワ点滅)を使いましょう。(GitHub へのリンクになっています。)
まず、上記 GitHub のコードを git clone して、README.md 通りにビルドおよびフラッシュ書き込みしておいてください。次に、ボードのリセットボタンを押してプログラムの実行状態(動作中)にしておきます。どうもこれが肝心で、その状態でないとうまくデバッグができません。
次に、SiFive freedom-e-sdk の scripts/debug を利用して OpenOCD と GDB を起動します。こんな感じです。
$ cd my_first_zephyr $ ~/freedom-e-sdk/scripts/debug \ --elf build/zephyr/zephyr.elf \ --openocd $RISCV_OPENOCD_PATH/bin/openocd \ --gdb $RISCV_PATH/bin/riscv64-unknown-elf-gdb \ --openocd-config ~/freedom-e-sdk/bsp/sifive-hifive1/openocd.cfg
環境変数は、SiFive freedom-e-sdk の説明に従って設定されているものとします。
無事に GDB が起動すると、どこか実行中の C 言語コードを表示し、そこで halt するはずです。例えばこんな感じです。
on_irq_stack () at /home/yokoyama/zephyrproject/zephyr/arch/riscv/core/isr.S:258 258 RV_OP_LOADREG t1, RV_REGSIZE(t0)
そうしたら、次のように GDB コマンド(太字の部分)を実行します。
(gdb) tbreak main Info : Retrying memory read starting from 0x204006d4 with more delays (略) Temporary breakpoint 1 at 0x204006d4: file ../src/main.c, line 17. (gdb) j main Continuing at 0x204006d4. Note: automatically using hardware breakpoints for read-only addresses. halted at 0x204006d4 due to hardware trigger Temporary breakpoint 1, main () at ../src/main.c:17 17 printk("My first app for Zephyr\n");
ここで、next コマンドを実行するとステップ実行されます。
(gdb) next halted at 0x204006d8 due to step (略) 19 if ((dev = device_get_binding(PWM_DEV)) == NULL)
うまく行きましたか? Zephyr カーネルの割込ルーチンなどクリティカルなところでブレークさせようとするとおかしな挙動になることもありますが、大抵は普通の(GDB の)やり方でデバッグできるはずです。
Eclipse でデバッグしてみる
次に Eclipse でデバッグしてみましょう。System Workbench for STM32 や Code Composer Studio に慣れている人は、そのほうが嬉しいですよね。
まずは、こちらを参考にして、Eclipse と CDT と GNU MCU Eclipse plug-in をインストールします。インストール後、Eclipse が起動していない場合は起動します。
Zephyr プロジェクトの上記のサイトを見ると、CMake で Eclipse プロジェクトファイル群(.project など)を生成する方法が書かれていますが、今回は使いません。私は Eclipse で開発していても基本的にソースコードは vi で書いているので、デバッグさえできれば問題ないのでした。
Eclipse を起動したら、debug configuration を作ります。メニューから、Run → Debug Configurations… を選びます。ウィンドウ(ダイアログ)が開いたら、左側のペインの GDB OpenOCD Debugging をダブルクリックします。次のような画面になると思いますので、Name という場所に好きな名前を入力し、まずは Main タブを開きます(最初に開いていると思います)。そうしたら、赤い楕円で囲った部分を設定します。
GNU MCU Eclipse サイトのこちらにある説明も参考にしてください。
次に、Debugger タブを選び、次のように設定します。もちろん、パス名は皆さんの環境に合わせて適宜変更してください。一番下の楕円で示しているのは、gdb コマンドのパスです。
最後に、Startup タブです。Load executable と Continue を外します。
最後に Apply ボタンを押します。
まずは、ボード上でプログラムが実行中の状態になっていることを確認します。デバッグを開始するには画面上部で、下記のように今設定した debug configuration(ここでは hifive1_config)を選び、その左のほうに見える「虫」アイコンをクリックします。
デバッグ画面が開いたら、ウィンドウ最下部から「Debugger Console」のタブを開きます。表示されていない場合は、メニューから Window → Show View → Debugger Console とします。
Debugger Console が表示されたら、その中で(プロンプトはありませんが)以下のように入力します。
tbreak main j main
main() 関数が表示され、その行でブレークしていますでしょうか。
あとは通常の MCU GNU Eclipse、あるいは System Workbench for STM32 や Code Composer Studio と似たような使い方でデバッグができます。便利ですね!
いずれは、Zephyr や MCU Eclipse で、もう少し簡単に RISC-V に対応できるようになればいいなあ、と思います。
補足
こちらの GitHub README.md でも書きましたが、OpenOCD のバージョンにより、west flash がうまくいったり、うまくいかなったりするようです。SiFive OpenOCD 2018.7.0 で試したときは OK でした。うまくいかないときは、~/zephyrproject/zephyr/boards/riscv/hifive1/support/openocd.cfg を、freedom-e-sdk に含まれる openocd.cfg で差し替えると良いようです。OpenOCD は、あちこちにバージョンが fork してしまい、よく分からないことが多いですね…。
今日はここまで。