3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ZYNQのLinuxアプリをVSCodeでデバッグする方法

Last updated at Posted at 2021-04-29

前編の ZYNQのLinuxアプリをVSCodeでビルドする方法 でビルド方法を紹介したので、次はデバッグできるようにしましょう。

VSCode側の設定

C++のプログラムを編集している画面でF5を押します。Launchのキーだそうですが、launchがまだ設定されていないので下のようなメニューが開きます。GDBかWindowsかはどちらでもいい(どうせ後で書き換えるから)のですが、とりあえずはC++ (GDB/LLDB) を選んでおきましょう。

image.png
launch.json が作られるので、以下のように書き換えます。

launch.json
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Remote unit test",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.elf",
            "MIMode": "gdb",
            "miDebuggerPath": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gdb.exe",
            "miDebuggerServerAddress": "cszmini:9999",
            "args": [],
            "cwd": "${workspaceFolder}",
            "stopAtEntry": false,
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        },
    ]
}

環境に応じて書き換えるべきポイントは以下の2点です。

デバッガのパスの設定

Windows上のARM用GDBのパスを指定します。

"miDebuggerPath": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gdb.exe",

ターゲットのアドレスの設定

ターゲットのIPアドレス(またはホスト名)と、ポート番号を指定します。

"miDebuggerServerAddress": "cszmini:9999",
"miDebuggerServerAddress": "192.168.1.4:12345",

のようにします。

とりあえず実行

F5を押すとlaunchに書かれたコマンドが実行されます。この時点ではターゲットボードでLinuxは動いていないのでエラーダイアログが出ます。
image.png

Linux側の準備

apt install gdbserverで、gdbserverをインストールしておきます。
Linuxのシェル上で、

# gdbserver localhost:9999 ./test.elf

と入力します。上のコマンドはgdbserverを起動して、ポート9999で待ち受けてtest.elfをアタッチします。

VSCodeでいざLaunch

いよいよVSCodeでF5を押してデバッグ開始です。

VSCode上でgdbが起動し、リモートのターゲットボードに接続されます。ステップ実行や変数の参照ができ、デバッグできるようになります。

image.png

対するLinux側ではプログラムがリモート操作されてステップ実行されています。
image.png

プログラムが終了するか、VSCodeで □ を押すと終了します。

もっと便利にしたい

ユーザ作成のライブラリを使う

ユーザが作成したライブラリを使うには、プロジェクトのフォルダにライブラリを入れ、tasks.jsonのargsに-Lと-lオプションを追加します。次の設定ではcszapiというライブラリが使われるようになります。

"args": [
  "-g",
  "${file}",
  "-L${workspaceFolder}",
  "-lcszapi",
  "-o",
  "${fileDirname}\\${fileBasenameNoExtension}.elf"
],

また、ヘッダファイルのIntelliSenseが動くようにするにはc_cpp_properties.jsonを編集して、インクルードパスを通すようにします。

image.png
これでユーザ作成のライブラリが使えるようになります。

ビルドが終わったら自動的にターゲットにコピーしたい

クロスコンパイルなので、出来上がったプログラムはターゲットボード上にコピーしなければなりません。毎回毎回scpや、エクスプローラでCTRL+C,CTRL+Vするのも面倒なので、tasks.jsonに自動化の処理を書いてあげましょう。
tasks.jsonは、"tasks": [で複数のタスクを登録できるようになっていますが、"group": { "kind": "build", "isDefault": true}が付いているタスクが CTRL*SHIFT+B で実行されるようになっています。
また、各タスクには "dependsOn": というパラメータが設定できて、これを使うとタスクの依存関係を設定できます。

つまり、ターゲットボード上にファイルを転送するというDeployというisDefaultなタスクを作り、DeployはBuildに依存するようにすれば、CTRL+SHIFT+Bでビルドとファイルコピーが可能になります。

(自動Deploy版)tasks.json
{
    // tasks.json 形式の詳細についての資料は、
    // https://go.microsoft.com/fwlink/?LinkId=733558 をご覧ください
    "version": "2.0.0",
    "tasks": [
		{
			"label": "Deploy",
			"type": "shell",
			"command": "cp",
			"args": [
				"${fileDirname}\\${fileBasenameNoExtension}.elf",
				"\\\\cszmini\\Share"
			],
			"problemMatcher": [],
			"dependsOn": "Build by ARM g++",
			"group": {
				"kind": "build",
				"isDefault": true
			}
		},
		{
			"type": "shell",
			"label": "Build by ARM g++",
			"command": "D:/Xilinx/SDK/2018.3/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-g++.exe",
			"args": [
				"-g",
				"${file}",
                "-L${workspaceFolder}",
                "-lcszapi",
				"-o",
				"${fileDirname}\\${fileBasenameNoExtension}.elf"
			],
			"options": {
				"cwd": "D:/Xilinx/SDK/2019.1/gnu/aarch32/nt/gcc-arm-linux-gnueabi/bin"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": "build"
		}
	]
}

dependsOnの参照はlabelを使って行われるようです。

F5でビルドとgdbの起動ができるようにしたい

launch.jsonのconfigurationsに登録されたタスクに、"preLaunchTask": というパラメータを設定しておけば、このタスクが実行される前に実行すべきタスクを指定できます。
したがって、"preLaunchTask": "Deploy"と書けば、GDB接続の前にDeployタスクが実行されて、ビルドとファイルの転送が行われます。

しかし、Linux上ではgdbserverプロセスを走らせなければならないのですが、このgdbserverを起動する前にtest.elfはターゲットボード上になければなりません。また、gdbserverを停止するにはリモートで接続してプログラムが終了するかkillするしかなく、ちょっと面倒です。

結論を言うと、preLaunchTaskを書いてビルドを自動実行するのではなく、リモートデバッグの場合は「ビルド&ファイル転送」と「デバッガ起動」は分けたほうがいいです。

少々面倒ですが、プログラムを書いてからそれを実行するまでに

  • CTRL+SHIFT+Bでビルド&実行ファイル転送
  • Linux上でgdbserver起動
  • F5でデバッグ開始

と、3ステップ必要です。gdbは巨大なプログラムだから、ちゃんと調べればファイル転送できるのかな?

GLIBCのバージョンが合わないとどうなる?

GLIBCのバージョンが合わない場合、つまりUbuntu 14のシステムをXSDK 2019.1に入っているarm-linux-gnueabihf-gdbでデバッグしようとすると、

readchar: Got EOF

というエラーが出てGDBが接続できません。

実際にやってみると
image.png
こうなります。

まとめ

VSCodeでZYNQのLinuxで動くARMのプログラムが書けて、デバッグまでできるようになりました。
これでXSDKを卒業できるかな!?

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?