はじめに
nRF52840等のNordicのBluetoothモジュールをネイティブSDKで開発する場合、 SEGGER Embedded StudioやKeilなどのIDEを利用するケースが多いです。これらのIDEはモジュールのメモリレイアウトの変更やイメージのフラッシュなどがわかりやすく、便利な開発環境です。
しかし、世の中にはエディタ+ターミナルで開発したいという欲望に抗えない人たちも少なくありません。この記事はそんな人々への私からのクリスマスプレゼントです。どこかで誰かの役に立ちますように。
前提
以下の前提で解説します。また、説明が冗長になるのでVSCodeはインストール済みとして解説します。今回説明するOSはwindowsですが、Ubuntuやmacでも構築は可能です。
- OS:windows
- エディタ:VSCode
- ボード:Adafruit Feather nRF52840 Express、SparkFun Pro nRF52840 Mini
- デバッグプローブ:J-Link
- ケーブル:1.27mmピッチ・2×5のリボンケーブル
また、今回はSDKのサンプルのビルド、フラッシュまでの解説をターゲットにしています。nRF5 SDK for Meshに関しては少し構成が違うので、リンクを参照して下さい。本記事の構築ができれば読んで理解できると思います。
インストール
make
悲しいですがwindowsはmakeはデフォルトではインストールされていないので、インストールしましょう。
Nordic tools
Software Development Kit
いわゆるSDK。これがないと始まらない。開発ボードによっては使用できるSDKのバージョンに制限があります。(nRF52840はSDK15.0.0以降でないとサポートされていません)各SDKの説明を参照して下さい。(zip配布じゃなくてGithubとかで配布してほしいけど、makeファイルがsdkバージョンをディレクトリ名で使い分けているので厳しそう)
nRF Command Line Tools
nrfjprog、mergehex(後述)といった、バイナリのフラッシュやバイナリとSoftDeviceのマージに必要なNordic純正のコマンドラインツールです。IDEを使用しない場合、makeのターゲットを指定してこれらのコマンドを呼び出す形で開発を進めます。インストール後はコマンドにパスを通しておいて下さい。
ARM Toolchain
IDEを使用する場合、Nordicが提供する各IDE用のMDKをインストールする必要がありますが、今回は変わりにGNU gccコンパイラを使用します。
注意
windowsは8-2018-q4-major
バージョンではコンパイルでエラーが発生することが確認されています。ですので、windowsの方は7-2018-q2-update
、または8-2019-q3-update
以上のものを使用して下さい。ちなみに私がwindowsで動作確認したのは7-2018-q2-update
と8-2019-q3-update
のみです。
Toolchainは以下の三種の神器で構成されています。
-
GNU C/C++ Compiler
泣く子も黙るGNUコンパイラ。 -
Binary tools
コンパイルされたコードをリンクし、アセンブリコードをコンパイルし、さまざまなファイル変換操作を実行できるツール。 -
Debugging tools
GNUプロジェクトデバッガーであるGDBを使用して、コードをステップ実行し、メモリの内容をリアルタイムで表示できます。VSCodeにはCortex-Debugというプラグインがあり、J-LinkがあればVSCode上でデバッグできてしまいます。すごい。(というかターミナルとGDBだけでデバッグするのは流石に辛い)
ARM Toolchainの設定
SDKがToolchainのgccを使用するように設定する必要があります。[SDK ROOT]/components/toolchain/gcc
にある以下のファイルを修正します。(Windowsの設定例です)
- Windows:Makefile.windows
- Mac and Linux:Makefile.posix
GNU_VERSIONはarm-none-eabi-gcc --version
で確認できます。
GNU_INSTALL_ROOT := C:/Program Files (x86)/GNU Tools ARM Embedded/8 2019-q3-update/bin/
GNU_VERSION := 8.3.1
GNU_PREFIX := arm-none-eabi
ボード定義
Adafruit Feather nRF52840 Expressはピン配置がNordicの開発ボードと基本的には互換(利用可能なボタンやLED、GPIOはは少ない)のため、ここは省略して大丈夫です。
Nordicのボードはピンアサインをヘッダファイルで独自に定義できます。(Using the SDK with other boards)これは逆に、SDKで提供されているピンアサインと異なる各メーカーのブレイクアウト基盤などは、独自のヘッダファイルを用意する必要があります。
SparkFun Electronicsが提供しているSparkFun Pro nRF52840 Miniなどは技適の通っているMDBT50Qを使用しているため、国内で使用できるnRFモジュールの1つです。しかし、ピンアサインが異なるため以下の作業が必要です。
- ピンアサインヘッダファイルを追加
- ボード定義ヘッダファイルに1.で作成したピンアサインを含めるようマクロを追記
幸いSparkFun Pro nRF52840 MiniはSparkFun Electronicsがピンアサインヘッダファイルを用意しているため、それを[SDK ROOT]/components/boards
に追加します。
その後、ボード定義にピンアサインのファイルを追加できるよう[SDK ROOT]components/boards/boards.h
のマクロの#elif defined (BOARD_…
と記載してある箇所に以下を追記します。(マクロ名とそれに紐づくピンアサインヘッダファイルは揃えておいた方がわかりやすいです)
#elif defined (BOARD_SPARKFUN_NRF52840_MINI)
#include "sparkfun_nrf52840_mini.h"
#elif defined(BOARD_CUSTOM)
#include "custom_board.h"
#else
#error "Board is not defined"
VSCodeでIntelliSenseを有効にする
VSCodeを使用する一番の利点はやはりIntelliSenseです。当然有効にします。今回はSDKの中のexampleの各ディレクトリをルートディレクトリとする形式で有効にします。今回はスマートフォンからLEDを点灯、消灯させるサンプルの[SDK ROOT]/example/ble_peripheral/ble_app_blinky
をルートディレクトリにします。
VSCodeで上記ディレクトリを開いたら、ctl+sft+p
、c/cpp: edit configurations
でc_cpp_properties.json
を作成したら、以下のようにSDKのソースを参照するよう編集します。
[SDK ROOT]
、[ARM toolchain ROOT]
にはそれぞれSDKのルートディレクトリへの絶対パス、ARM ToolChainのルートディレクトリへの絶対パスを記載して下さい。
{
"env": {
"nrfSDK": "[SDK ROOT]"
},
"configurations": [
{
"name": "ARMGCC",
"includePath": [
"${workspaceFolder}/**",
"${nrfSDK}/components/**",
"${nrfSDK}/components",
"${nrfSDK}/components/libraries/experimental_memobj",
"${nrfSDK}/components/libraries/experimental_section_vars",
"${nrfSDK}/modules/nrfx/mdk",
"${nrfSDK}/modules/nrfx/hal",
"${nrfSDK}/components/libraries/balloc",
"${nrfSDK}/components/libraries/experimental_log",
"${nrfSDK}/components/libraries/experimental_log/src",
"${nrfSDK}/components/libraries/delay",
"${nrfSDK}/integration/nrfx",
"${nrfSDK}/components/libraries/bsp",
"${nrfSDK}/components/drivers_nrf/nrf_soc_nosd",
"${nrfSDK}/components/libraries/strerror",
"${nrfSDK}/components/boards",
"${nrfSDK}/components/toolchain/cmsis/include",
"${nrfSDK}/modules/nrfx",
"${nrfSDK}/components/libraries/util",
"${nrfSDK}/components/libraries/fifo",
"${nrfSDK}/components/libraries/uart",
"${nrfSDK}/integration/nrfx/legacy",
"${nrfSDK}/components/libraries/delay",
"${nrfSDK}/modules/nrfx/drivers/include",
"${workspaceFolder}/sparkfun/blank/config",
"${workspaceFolder}/sparkfun/blank"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"BSP_DEFINES_ONLY",
"CONFIG_GPIO_AS_PINRESET",
"FLOAT_ABI_HARD",
"NRF52840_XXAA",
"DCONFIG_NFCT_PINS_AS_GPIOS"
],
"compilerPath": "[ARM toolchain ROOT]\\7 2018-q2-update\\bin\\arm-none-eabi-gcc.exe",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}
この状態でF12などでコードジャンプできるようになっていれば正しく設定できています。
ボード毎のビルド設定
ボード毎のディレクトリを作成
NordicのSoCのバージョン毎に使用するSoftDeviceやメモリ容量が異なるため、pca10056
のように各ボード毎にビルド用ディレクトリがあります。ここで、SparkFun Pro nRF52840 Miniのような公式の開発ボードとピンアサインに互換性の無いカスタムボードを使用する場合、使用されているNordicのSoCに対応したディレクトリをコピーし、ボード定義のマクロを修正します。
SparkFun Pro nRF52840 MiniはSoCにnRF52840を使用しているため、pca10056
をコピーし、sparkfun_nrf52840_mini
という名前にします。
Makefileの修正
sparkfun_nrf52840_mini/s140/armgcc
のMakefileを開き、CFLAGS
とASMFLAGS
で使用されている-DBOARD_PCA10056
というオプションを以下のように修正します
CFLAGS += -DBOARD_SPARKFUN_NRF52840_MINI
ASMFLAGS += -DBOARD_SPARKFUN_NRF52840_MINI
コンパイラへの引数オプションを変えているだけなので、ファイル自体は修正せずmakeコマンドの引数に渡すことでも可能です。
ビルドとフラッシュ
ここまできたらターミナルでmake
を実行すればビルドできます。ビルドが成功したらあとはフラッシュするだけです。ボードとJ-Linkを接続し、make flash
を実行しましょう。
それぞれのボードのSWDは以下の箇所です。SparkFun Pro nRF52840 Miniは裏面にあるので注意して下さい。
最後に
もはやVSCodeはIDE…?一理ある。
余力があればデバッグについても書きます。もちろんデバッグもVSCodeでできます。