Zephyr でビルドした RISC-V コードを Eclipse でデバッグする

(更新

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 してしまい、よく分からないことが多いですね…。

今日はここまで。

2019年12月12日 カテゴリー: RISC-V