ZephyrでRTTコンソール

はじめに

久々のZephyrです。

JLinkには、JTAG/SWD経由でシリアル入出力をする機能があります。 UARTを使ったコンソールも良いのですが、物理配線が増えたり、簡単にUARTを引き出せない場合、RTTが便利です。

Zephyrコンフィグ

NordicのZephyrフォークを参考に、必要そうなコンフィグを有効化していきます。

  • CONFIG_USE_SEGGER_RTT=y
  • CONFIG_SHELL_BACKEND_RTT=y

上の2つあたりが必須そうです。 次の内容で設定ファイルを作成します。

|> zephyr/samples/subsys/shell/shell_module/prj_minimal_rtt.conf

CONFIG_SHELL=y
CONFIG_KERNEL_SHELL=n
CONFIG_SHELL_BACKEND_SERIAL=n
CONFIG_OBJECT_TRACING=y
CONFIG_THREAD_MONITOR=y
CONFIG_INIT_STACKS=y
CONFIG_BOOT_BANNER=n
CONFIG_THREAD_NAME=y
CONFIG_LOG=n
CONFIG_SHELL_HISTORY=n
CONFIG_SHELL_STACK_SIZE=1024
CONFIG_SHELL_CMD_BUFF_SIZE=128
CONFIG_SHELL_WILDCARD=n
CONFIG_SHELL_HELP_ON_WRONG_ARGUMENT_COUNT=n
CONFIG_SHELL_STATS=n
CONFIG_SHELL_CMDS=n
CONFIG_CONSOLE=y

#enable RTT shell
CONFIG_USE_SEGGER_RTT=y
CONFIG_SHELL_BACKEND_RTT=y

ビルドしてターゲットボードに書き込みます。

mkdir build && cd $_
cmake -GNinja -DBOARD=nrf52840_pca10056 -DCONF_FILE="prj.conf prj_minimal_rtt.conf" ..
ninja flash

RTTクライアントを立ち上げます。 まず、JLinkの接続から。

JLinkExe -device nrf52840_xxaa -speed 4000 -if SWD
J-Link>connect

RTTクライアントを起動します。

$ JLinkRTTClient
###RTT Client: ************************************************************ 
###RTT Client: *               SEGGER Microcontroller GmbH                * 
###RTT Client: *   Solutions for real time microcontroller applications   * 
###RTT Client: ************************************************************ 
###RTT Client: *                                                          * 
###RTT Client: *       (c) 2012 - 2016  SEGGER Microcontroller GmbH       * 
###RTT Client: *                                                          * 
###RTT Client: *     www.segger.com     Support: support@segger.com       * 
###RTT Client: *                                                          * 
###RTT Client: ************************************************************ 
###RTT Client: *                                                          * 
###RTT Client: * SEGGER J-Link RTT Client   Compiled Mar 27 2019 17:12:05 * 
###RTT Client: *                                                          * 
###RTT Client: ************************************************************ 

###RTT Client: -----------------------------------------------
###RTT Client: Connecting to J-Link RTT Server via localhost:19021  Connected.


llss^?^?###RTT Client: Connection lost. Going to reconnect.
###RTT Client: Connecting to J-Link RTT Server via localhost:19021 .. Connected.
SEGGER J-Link V6.44d - Real time terminal output
J-Link OB-SAM3U128-V2-NordicSemi compiled Jan  7 2019 14:07:15 V1.0, SN=683516743
Process: JLinkExe



rtt:~$

Zephyrのshell rtt:~$が立ち上がっています。 Tabでの補完も効きます。

rtt:~$
  demo      device    dynamic   gpio      log_test  version

version情報を見てみましょう。

rtt:~$ vvveeerrrsssiiiooonnn


Zephyr version 1.13.99

あん?何故かキー入力に対して、3回文字が出力されます。 Zephyr側はコマンドを受け付けているので、RTTClientの問題っぽいですね…。

どうもどこかのバージョンからバグったみたいですね…。

forum.segger.com

Zephyrのブートログが出力されていません。 上記設定では、printkが出力されていません。

UARTコンソールが有効になっているせいかと思いきや、そうでもないようです。

github.com

LOG_PRINTKを設定しないとダメ? お試して、LOG機能を有効化して、バックエンドをRTTにします。

ダメですね…。

194.19.86.155

1.14のリリースノートで解決済みになっているようですが、1.14でもprintkでの出力は出ていないような…?

下のサンプルだと、printkが出力されることがわかりました。

|> zephyr/samples/subsys/logging/logger

Process: JLinkExe
***** Booting Zephyr OS zephyr-v1.14.0-1039-gc3ccbbbdc3ca *****
Module logging showcase.
[00:00:00.125,030] <inf> sample_module: log in test_module 11
[00:00:00.125,061] <inf> sample_module: Inline function.
Disabling logging in the sample_module module
Function called again but with logging disabled.
Instance level logging showcase.
[00:00:00.125,213] <inf> sample_instance.inst1: Inline call.
[00:00:00.125,213] <inf> sample_instance.inst1: counter_value: 0
[00:00:00.125,213] <wrn> sample_instance.inst1: Example of hexdump:
01 02 03 04             |....    
[00:00:00.125,213] <inf> sample_instance.inst2: Inline call.
[00:00:00.125,213] <inf> sample_instance.inst2: counter_value: 0
[00:00:00.125,244] <wrn> sample_instance.inst2: Example of hexdump:
01 02 03 04             |....    
Changing filter to warning on sample_instance.inst1 instance.
[00:00:00.125,305] <wrn> sample_instance.inst1: Example of hexdump:
01 0m

設定ファイルを見てみます。

$ cat prj_rtt.conf
CONFIG_LOG=y
CONFIG_LOG_RUNTIME_FILTERING=y
CONFIG_LOG_BUFFER_SIZE=2048
CONFIG_LOG_PRINTK=y
CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD=0
CONFIG_LOG_BACKEND_RTT=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_COVERAGE=n

ふむふむ。LOG_BACKEND_RTTを有効にするようですね。

では、これをshellの方の設定に継ぎ足して…

$ ninja
zephyr/subsys/shell/shell_rtt.c:7:
../../../../../include/toolchain/gcc.h:28:37: error: static assertion failed: "Conflicting log RTT backend enabled on the same channel"
 #define BUILD_ASSERT_MSG(EXPR, MSG) _Static_assert(EXPR, MSG)
                                     ^~~~~~~~~~~~~~
zephyr/subsys/shell/shell_rtt.c:12:1: note: in expansion of macro 'BUILD_ASSERT_MSG'
 BUILD_ASSERT_MSG(!(IS_ENABLED(CONFIG_LOG_BACKEND_RTT) &&
 ^~~~~~~~~~~~~~~~
[64/130] Building C object zephyr/CMak...phyr.dir/subsys/logging/log_core.c.obj
ninja: build stopped: subcommand failed.

ああん? まさか、shellとログ、どちらかしか使えないってこと…?