くにゅくにゅの雑記帳

実験ノート的なやつ

Visual Studio Code で ARM Cortex の開発環境を作る

f:id:kunukunu:20180506154139p:plain

Visual Studio Code で ARM Cortex の開発環境を構築してみたので,備忘録代わりに構築手順を書いておきます。

Visual Studio Code そのものは統合開発環境ではなく,あくまで高機能なコードエディタという位置づけの製品ですが,アドオンを入れることにより,コーディングだけでなく,プロジェクトのビルドや,ターゲットMCUへのダウンロード,ターゲット上で実行しながらのデバッグを,エディタ上で行うことができるようになります。IntelliSense によるコード補完もきちんと動作し,なかなか快適です。一方,大きな欠点として,2018年5月時点では C/C++リファクタリング機能が完全に欠落しています。このため,変数名の一括変更といった,ほかのコードエディタならば当たり前にできるようなことができなかったりもします。それを差し置いても,Eclipseベースの環境で作業するよりは(ry

環境

わたしの使用環境は Windows 10 64 bit なので,それを前提に書きます。ただし,Visual Studio Code を含め基本的にすべてクロスプラットフォームなので,ほかの環境でも概ね同様の手順で構築できるはずです。

必要なソフトウェア

必要なソフトウェアは,以下のとおりです。最初にインストールします。

Visual Studio Code

ダウンロードは以下から。

Visual Studio Code - Visual Studio

インストール後,最低限以下の2つの拡張機能をインストールする必要があります。まずは,C/C++拡張。

marketplace.visualstudio.com

 そして Cortex-Debug。これが要であり,かつ大変優秀で,デバッグを開始すると,なにも考えなくても OpenOCD の起動から gdb へのアタッチまでを自動的にやってくれます。

marketplace.visualstudio.com

Cortex-Debug と同類の拡張機能に Native Debug というものもあります。こちらも利用可能ですが,もう少し汎用的に作られており,たとえば Cortex-Debug にある OpenOCD の自動起動といった機能がありません。したがって,Cortex-Debug の方をお勧めします。 

GNU ARM Embedded Toolchain

ロスコンパイラやデバッガなどのツールチェインです。ARM社のサイトにあるものを使ってください。同種のプロジェクトは過去にいくつかあり,古い記事では異なるものを案内している場合もありますが,すべて過去のものと思ってよいです。執筆時点の最新版は Version 7-2017-q4-major です。

Windows用には,インストーラ版と,ZIPパッケージ版があります。どちらも内容は同じですが,インストーラを普通に実行すると "C:\Program Files (x86)" にインストールされてしまいます。パスネームに空白が含まれるとのちのちヘンな不具合に悩まされることがあるので,インストール先を変えるか,ZIP版を強くお勧めします。わたしは,ZIP版を "C:\tools" に入れています。 

OpenOCD

オンチップデバッガの OpenOCD です。Windows版のビルドはいくつかありますが,gnu-mcu-eclipse 版がお勧めです。執筆時点での最新版は,gnu-mcu-eclipse-openocd-0.10.0-7-20180123-1217-win64.zip です。インストーラはありません。わたしは,ZIP版を "C:\tools" に入れています。

github.com

Git for Windows

Git は必須ではありませんが,使った方がいいし,Visual Studio Code も git ありきで作られています。付属の Git BASH だけでも,POSIXライクなシェルがちょっとほしいときに使い道があります。執筆時点での最新版は Git-2.17.0-64-bit.exe です。

Git - Downloading Package  

make

ツールチェインには make が含まれていません。このため,別途インストールする必要があります。お勧めは,以下のいずれかです。

Make for Windows

Windows で動く単体の make.exe です。最低限の make がほしいだけなら,こいつをインストールするのがもっともシンプルです。make.exe とともに arm-none-eabi-gcc.exe などが cmd.exe 内で走ります。cmd.exe はちょっと…… という場合や,MakefilePOSIX なコマンドの存在を前提としていてうまく走らない場合には,前述した Git BASH 内で実行することも可能です。

gnuwin32.sourceforge.net
MSYS2

MSYS2 自体は,Windows内で動く POSIX 互換シェルみたいなものです。Git BASH も MSYS2 をベースに作られていますが,単体でいじれる環境がほしい場合には,こちらのインストールをお勧めします。MSYS2 インストール後,pacman で make だけをインストールすれば足ります。"C:\msys64\usr\bin\make.exe" ができたらOKです。

MSYS2 homepage

MSYS2 は MinGW と一緒くたに語られがちですが,MinGWWindows ネイティブプログラムをビルドするためのGNUツールチェインのことであり,ARM Cortex のクロスビルドを行うという今回の目的の上ではまったく関係がありません。

環境変数の設定

Windows環境変数設定で,ツールチェイン,OpenOCD,および make のインストール先を PATH に通しておく必要があります。わたしの場合は,以下を PATH に追加しました。

C:\msys64\usr\bin

C:\Tools\gcc-arm-none-eabi-7-2017-q4-major-win32\bin

C:\Tools\OpenOCD\0.10.0-7-20180123-1217\bin

MSYS2 ではなく,単体の make.exe を使う場合には,C:\msys64\usr\bin ではなく,そちらへのPATHを通してください。

MSYS2は,デフォルトでは Windows の PATH を継承しません。してくれないとやや不便なので,MSYS2_PATH_TYPE という環境変数を新規に作り,inherit と設定すると,継承するようになります。

 

Visual Studio Code の設定

Visual Studio Code の挙動は,すべて JSON で設定します。ワークスペースの挙動を定義した JSON は,プロジェクトフォルダの .vscode というフォルダに保存されています。それぞれテンプレートみたいなものが作られますが,その説明は割愛するので,ほかのサイトを参考にしてください。ここでは,どういう JSON を書けばどうなるかだけを記述します。

tasks.json

tasks.json は,プログラムのビルドなど,開発中に実行したい「タスク」の動作を定義します。ここでは,すでに Makefile があるという前提で,make all と make clean の2つのタスクを実行できるように定義しました。意味は見ればだいたいわかると思います。make.exe に all または clean の引数をつけて実行しろ,と言っているだけです。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "type": "shell",
    "echoCommand": true,
    "tasks": [
        {
            "label": "build all",
            "command": "make.exe",
            "args": [
                "all",
            ],
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        },{
            "label":"clean",
            "command": "make.exe",
            "args": [
                "clean",
            ],
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}

タスクとして定義した項目は,タスク→実行に label として設定した名前が表示されるようになり,これで手元から make all や make clean が実行できるようになります。
f:id:kunukunu:20180506181925p:plain


launch.json

launch.json では,デバッガを起動したときの動作を定義します。このプロジェクトでは,以下のように記述しました。executable としてデバッグ対象のバイナリを,servertype として openocd を,configFiles として OpenOCD の設定ファイルを定義します。このあたりは,実際に利用するデバイスに合わせてください。

"version": "0.2.0",
    "configurations": [

        {
            "cwd": "${workspaceRoot}",
            "executable": "./build/n042-test.elf",
            "name": "Debug Microcontroller",
            "device": "STM32F047",
            "runToMain": true,
            "request": "launch",
            "type": "cortex-debug",
            "servertype": "openocd",
            "configFiles": [
                "board/st_nucleo_f0.cfg"
            ],
        },
    ]
}

デバッグの設定は,以下あたりから可能で,"name" にて設定した項目が現れます。F5 キーを押すと,OpenOCD と gdb が起動し,ターゲットのMCUに接続します。run / halt / step in / step over / breakpoint など,基本的なデバッグ操作が可能です。

f:id:kunukunu:20180506184153p:plain

 

なお,プログラムをダウンロードするためのUIは特に用意されていないようです。ターゲットに接続した状態で,デバッグコンソールで load コマンドを実行すると,ダウンロードされます。

f:id:kunukunu:20180506185752p:plain


c_cpp_properties.json

c_cpp_properties.json では,IntelliSense の動作を設定します。設定しなくてもビルドやデバッグの動作に支障はありませんが,ここを適切に設定することで開発が飛躍的に楽になります。"Linux" "Mac" "Win32" など,いくつかの設定があらかじめ定義されていますが,まったく新たに "STM32" という定義を追加することにしました。
ここでは,NUCLEO-F042K6 ボード用に STM32CubeMX が吐いたコードに対する設定例を示します。基本的には,IntelliSense エンジンがすべてのヘッダファイルを見つけられるように,コンパイラのインクルードディレクトリ(-I で設定するもの)と,プリプロセッサ定義(-D で設定するもの)を場当たり的に定義していくだけです。

        {
            "name": "STM32",
            "includePath": [
                "${workspaceFolder}",
                "${workspaceFolder}/Inc",
                "${workspaceFolder}/Drivers/STM32F0xx_HAL_Driver/Inc",
                "${workspaceFolder}/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy",
                "${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32F0xx/Include",
                "${workspaceFolder}/Drivers/CMSIS/Include",
                "C:/Tools/gcc-arm-none-eabi-7-2017-q4-major-win32/arm-none-eabi/include",
                "C:/Tools/gcc-arm-none-eabi-7-2017-q4-major-win32/lib/gcc/arm-none-eabi/7.2.1/include",
                "${workspaceFolder}"
            ],
            "defines": [
                "USE_HAL_DRIVER",
                "STM32F042x6"
            ],
            "intelliSenseMode": "clang-x64",
            "browse": {
                "path": [
                    "${workspaceFolder}",
                    "${workspaceFolder}/Inc",
                    "${workspaceFolder}/Drivers/STM32F0xx_HAL_Driver/Inc",
                    "${workspaceFolder}/Drivers/STM32F0xx_HAL_Driver/Inc/Legacy",
                    "${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32F0xx/Include",
                    "${workspaceFolder}/Drivers/CMSIS/Include",
                    "C:/Tools/gcc-arm-none-eabi-7-2017-q4-major-win32/arm-none-eabi/include",
                    "C:/Tools/gcc-arm-none-eabi-7-2017-q4-major-win32/lib/gcc/arm-none-eabi/7.2.1/include",
                    "${workspaceFolder}"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": ""
            },
            "cStandard": "c11",
            "cppStandard": "c++17"
        },
 

追加した定義は,画面右下の当該部分をクリックすると選択可能となります。

 f:id:kunukunu:20180506183431p:plain

 

はまりポイント

ワークスペースのフォルダのパスに日本語などの非ASCII文字が含まれていると,うまく動作しません。必ずASCII文字だけで構成されたフォルダ名を使ってください。

まとめ

必要なツールをインストールし,Visual Studio Code 上で Makefile にしたがったビルドと,OpenOCD および gdb によるデバッグを行えるようにするところまでを説明しました。make.exe や openocd.exe など必要なプログラムプログラムへのパスが通っていれば,あとは Cortex-Debug などが良い感じにやってくれますが,ビルドやデバッグ時に行うべき最低限の挙動は,各種 JSON として定義し,Visual Studio Code に伝えてあげないといけません。このあたりが,多少とっつきづらいように思いました。