JLink経由で、nRF52をNRF_LOGでデバッグ


nRF52シリーズで組込みの開発を行っていると、デバッグを行いたくなることってありますよね。
ねっねっ。

簡単にデバッグを行う方法としてプリントデバッグがあり、ArduinoIDEのシリアルモニターを用いると手軽に開発できます。

nRF52系のArduino Core, LibraryはAdafruitさんが公開してくださっています。

センサーをつないで測定値を表示してみるといったものなら、このデバッグ方法でも十分でしょう。

しかし、Bootloader起動時の処理内容が知りたい電源投入後にひたすらリセットがかかる原因を究明したいArduinoのCoreにはない機能を実装してデバッグしたい1といった要望には応えられないでしょう。

なんかいい方法ないかな。。。

そんな時に大活躍するのが、NRF_LOG()です。

今回は、nRF5_SDK15.3.0を前提に、NRF_LOG()の使い方を紹介します。

nRF5_SDK_15.3.0のダウンロード

こちらから、nRF5_SDK_15.3.0やs140_nrf52_6.1.1などを選択してダウンロードします。

サンプルプログラムの準備

適当なサンプルプログラムを使用します。

[YOUR_DOWNLOAD_PATH]/nRF5_SDK_15.3.0_59ac345/examples/peripheral/pwm_driver/main.c

を用いて、Lチカしてみます。

pca10040とpca10056のどちらを選択するかは、お手元の環境に合わせてください。

他のボードを使用する場合は、ピン配置を適切に変更すれば、とりあえず動作はすると思います。

ピン配置を変更するには、

[YOUR_DOWNLOAD_PATH]/nRF5_SDK_15.3.0_59ac345/components/boards/pca10056.h

あたりに手を加えれば、ひとまずなんとかなります。

サンプルプログラムの書き込み

JLink本体を用意します。

/examples/peripheral/pwm_driver/pca10056/blank/armgcc

に移動して、

$ make
$ make erase
$ make flash

と実行していけば、ビルドされたソースコードがnRF52840に書き込まれます。

書き込みに成功すれば、User Button(DFU Switch)を押すたびに、ビルトインのLEDの光り方が変わるはずです。

NRF_LOG() の有効化

/examples/peripheral/pwm_driver/pca10056/blank/config/sdk_config.h

の設定ファイルを編集していきます。

// <e> NRF_LOG_ENABLED - nrf_log - Logger
//==========================================================
#ifndef NRF_LOG_ENABLED
#define NRF_LOG_ENABLED 1
#endif

という#defineがあるはずなので(なければ適当なsdk_config.hからnRF_Logに関係している部分をコピーしてください)、 #define NRF_LOG_ENABLED 1 と有効にされていることを確認してください。

NRF_LOG() の出力先の設定

JLink経由での出力とUART出力の2種類から選べます。

JLink経由でのデバッグ

JLink経由でデバッグする場合は、

//==========================================================
// <e> NRF_LOG_BACKEND_RTT_ENABLED - nrf_log_backend_rtt - Log RTT backend
//==========================================================
#ifndef NRF_LOG_BACKEND_RTT_ENABLED
#define NRF_LOG_BACKEND_RTT_ENABLED 1
#endif

という箇所を探し出し、 #define NRF_LOG_BACKEND_RTT_ENABLED 1 として有効にしてください。

SEGGER_RTT()を用いたデバッグ

JLink経由でのデバッグには、JLinkが必須となります。

となると、SEGGER_RTT()を用いたリアルタイムでのデバッグも可能となります。

SEGGER_RTT()に関する定義と実装は

/nRF5_SDK_15.3.0_59ac345/external/segger_rtt/SEGGER_RTT.h

などを見れば、わかります。

SEGGER_RTT()を使うためには、2ステップ必要です。

Makefileの編集

/examples/peripheral/pwm_driver/pca10056/blank/armgcc/Makefile

を編集します。

# Source files common to all targets
SRC_FILES += \
~~~中略~~~
  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_Syscalls_GCC.c \
  $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \

INC_FOLDERS += \
~~~中略~~~
  $(SDK_ROOT)/external/segger_rtt \

というように、SEGGER_RTT関連のソースファイルもコンパイル、リンクするように追記します。

SEGGER_RTT.hのインクルード

SEGGER_RTT_WriteString(0, "Hello World!");
SEGGER_RTT_printf(0, "LED_NEOPIXEL pin: %lu\n", LED_NEOPIXEL);

のような関数を呼び出しているファイル(main.cなど)に

#include "SEGGER_RTT.h"

を追加します。

UART経由でのデバッグ

UART経由でデバッグする場合は、

// <e> NRF_LOG_BACKEND_UART_ENABLED - nrf_log_backend_uart - Log UART backend
//==========================================================
#ifndef NRF_LOG_BACKEND_UART_ENABLED
#define NRF_LOG_BACKEND_UART_ENABLED 0
#endif

という箇所を探し出し、 #define NRF_LOG_BACKEND_UART_ENABLED 1 と有効にしてください。

JLink経由でのデバッグ (SEGGER_RTTを使ってみる)

JLink経由でデバッグを行うためには、JLink本体が欠かせません。

必要なソフトウェア一式を、こちらで、J-Link Software and Documentation Packを選択してダウンロードします。

ダウンロードしたソフトウェアの中に、JLinkRTTViewer というものがあると思います。

nRF52840を使用しているならば、このままOKを押下します。

ファームウェアの書き込みに成功していれば、以下のような画面になるはずです。

NRF_LOG_INFO("Hello World!);
SEGGER_RTT_WriteString(0, "Hello World!);

などで、出力した文字列が表示されているかと思います。

以上が、SEGGER_RTTを使用した、JLink経由でのデバッグの紹介です。

UART経由でのデバッグ

#define NRF_LOG_BACKEND_UART_TX_PIN 6 で指定されたピンに出力されているので、いい感じにUARTの出力を受け取ればデバッグできるでしょう。

まとめ

ログを出力するために編集するファイルが多いので、慣れるまでは設定漏れが発生するかもしれません。

JLinkを用意すれば、NRF_LOG_INFO()だけでなく、SEGGER_RTT_WriteString()も使用できるので、リアルタイムでのデバッグも可能となるでしょう。


  1. AdafruitさんのArduino CoreはnRF5_SDK11系をもとに作成されています。最新のSDKはnRF5_SDK16系であり、nRF5_SDK11から大きく仕様が変わっているので、最新の機能を使うためにはArduinoのCore, Libraryに各バージョンの機能を移植・実装する必要があります。