Nordic nRF5340 と nRF Connect SDK にハマる

投稿者: | 2020/07/07

Struggled to run Bluetooth Throughput demo on Nordic nRF5340.

久々の投稿です。

今回は、Nordic Semiconductor 社(以下 Nordic)の比較的新しいチップを搭載した、nRF5340 PDK(Preview Development Kit)を動かしてみたレポートです。

今まで、Nordic の評価ボードを、同社の(旧来の) SDK で動かしてきた方には、何かしら御参考になるのではないかと思います。旧来の SDK とあまりに違うことが多く、また nRF5340 はマルチコアデバイスでもあり、今までの常識が通用しません。

じゃあ、今までの SDK を nRF5340 でも使えばいいのかというと、なんと nRF5340 からは nRF Connect SDK という新しい SDK を使わないといけなくなっているのです。

何が違うのか?

まず最初に、旧来と違う点をまとめます。

  • 開発環境が Zephyr RTOS ベースになった
  • Application MCU と Network MCU という 2コア構成になった(それぞれのコアで、できることが異なる)

なんだ、それだけか。と気楽に構えてデモコードを動かそうとしたら、丸一日、四苦八苦するハメになってしまいました。皆さんが同じ苦労をなさってもしようがないので、また、Nordic のウェブサイトはたくさんの情報を提供しようと努力している節は見受けられるのですが、初めて利用する人がハマるのは間違いなし、と確信しましたので、以下にまとめさせて頂きました。

なお、今回は Connect SDK v1.3.0 を使用しています。

なお、nRF5340 が 2コア構成となった背景としては、リアルタイム制約の強い通信プロトコルスタックを、アプリケーション実行用のコアから外すことで、アプリケーション設計の柔軟性を向上させる目的があるものと考えられます。

デモアプリの選択

今回の目的の一つは、Bluetooth 5 の 2Mbps(物理レイヤ)通信速度を評価してみたかった、というものです。私は今まで nRF51 DK と nRF52 DK を一つずつ持っていたのですが、前者は 2Mbps 通信に対応しておらず、もう一台評価ボードを用意する必要がありました。しかし、改めて nRF52 DK を 1台導入するのは癪なので、nRF5340 PDK を導入しました。

上述の新しい SDK(nRF Connect SDK)の中を見ると、samples/bluetooth/throughput というディレクトリがあり、サンプルコードを動かすだけでベンチマークを取れるようになっています。このデモアプリは、もちろん nRF5340 にも対応しています。(こちらが参考になります。)

なーんだ、簡単じゃないか。

いえ、簡単ではなかったのです。。。

開発環境のインストール

こちらの Docs » Getting started を見ると、新しい SDK のセットアップ方法が説明されています。Windows でも大丈夫のようですが、なんとなく、Linux のほうが安心のようです。また、今回は勉強を兼ねて Installing the nRF Connect SDK manually の手順を選びました。

私は当初、Ubuntu 16.04 (LTS) に入れようと思ったのですがダメでした。apt install libsdl2-dev がどうしてもうまくいかないのです。しようがないので、新しく Ubuntu 18.04 の仮想マシン(VMware)を用意するはめになりました。

なお、上述の Getting started にもありますが、Zephyr SDK をインストールする必要はないようです。Zephyr の勉強は後回しにして、とりあえず nRF Connect SDK を動かせれば良いや、という方は、指示通りに従ったほうが良さそうです。(ただし、LED チカチカ等のサンプルコードなどは、Zephyr SDK をインストールしないと面倒かも知れません。)

あと余談ですが、ツールチェインはドキュメント通り ~/gnuarmemb にインストールするのが良さそうです。私は違う名前にしてハマり、1時間程度を無駄にしました。

Bluetooth Throughput をビルドする

さて。先ほど説明したデモアプリをビルドしてみましょう。~/ncs/nrf/samples/bluetooth/throughput に cd し、west build します。ここで、ビルド時にはボード名を指定することになっているのですが、この辺も、ある程度の試行錯誤が必要のように思います。まずは、以下のようにしてみました。(実は、これでは動かない)

$ cd ~/ncs/nrf/samples/bluetooth/throughput
$ west build -b nrf5340pdk_nrf5340_cpuapp
$ west -v flash

ターミナルソフトを開いて、/dev/ttyACM2 に 115200 で接続します。これもソースコードを読んだりドキュメントを注意深く読めば分かるのでしょうが、ここまでできるのに、さらに 30分を要しました。まとめると、

  • nRF5340 PDK には USB の仮想 tty が 3つあり、ビルドするサンプルコードの UART 出力は uart0 なのだが、その uart0 が 3つ目の仮想 tty(Linux だと /dev/ttyACM2)に繋がっている

という点と、

  • 通信レートは 115.2kbps である

という点です。

さて通信ソフトを立ち上げ PDK をリセットしますが、最初の 2行だけのメッセージだけ表示され、デモの README に書かれている通りのプロンプトが出ません。んー。

*** Booting Zephyr OS build v2.3.0-rc1-ncs1 ***
Starting Bluetooth Throughput example

またここで 2〜3時間ほどハマりました。

Bluetooth Throughput デモは、Network MCU 上でしか動かない

何がいけなかったというと、上記デモアプリは Application MCU 上では動かない、ということでした。実は、ここをよく読むと推察できるのですが。

もっとちゃんとした説明は、こちらです。

つまり、Application MCU では先ほどのデモアプリは動かない、ということになります。

empty_app_core ってなに?

さて。それでは先ほどの west build で -b nrf5340pdk_nrf5340_cpunet を指定すれば良さそうなことが分かりましたが、それだけでは動きません。実は、Network MCU でコードを動かすには、Application MCU から Network MCU をブートしてやらないといけないのです。そのためのサンプルコードが、samples/nrf5340/empty_app_core です。これを west build -b nrf5340pdk_nrf5340_cpuapp でビルドし、west flash(-v オプションを付けたほうが分かりやすいでしょう)すると、Network MCU を起こすプログラムを Application MCU に書き込むことができます。

でも、相変わらず /dev/ttyACM2 には何も出てきません。。。

シリアルコンソールに何も出てこない…

なにしろシリアルコンソールに何も出てこないので、さらに、ドキュメントを探したり、頭の中で想像しながら作業し続けないといけないので、ここいらでかなり疲れてきました。

そんな折、先ほど引用した Docs » User guides » Working with nRF5340 を読んでいたところ、末尾に「In the default configuration, you cannot access the logging output of the network core sample.」と書かれてました。そんなことをさらっと書かれても、初めてのユーザーは途方にくれることでしょう。おまけにその下の説明が分かりづらい。結論から言うと、Zephyr の開発環境から見た場合、Network MCU の TxD は P0.25 から出ていて(P0.26 ではありません)、P0.26 から RxD を取り込むことができる、という意味のようです。ちょっと分かりづらいですよね。

それでもシリアルに出てこない

さて。私は(ここらでかなり疲弊していたのですが)気合いを入れて、オシロに電源を入れました。Network MCU のほうに west build -b nrf5340pdk_nrf5340_cpunet した Bluetooth Throughput を書き込んで動かしてみたのですが、P0.25 も P0.26 もピクリとも動きません。なんでやねん。

いろいろ調べたところ、原因が分かりました。先ほどの empty_app_core では、P0.25 も P0.26 も Network MCU 側に割り当ててくれていない、ということです。README には、main.c の関数 network_gpio_allow() を変更しろ、とあるのですが、具体的な方法が説明されていません。しかしさすがは Google、とある中国人の先達の投稿を見つけてくれました。

つまり、main.c の network_gpio_allow() の return の前に、次を加筆します。

	NRF_P0_S->PIN_CNF[25] = (GPIO_PIN_CNF_MCUSEL_NetworkMCU <<
				GPIO_PIN_CNF_MCUSEL_Pos);
	NRF_P0_S->PIN_CNF[26] = (GPIO_PIN_CNF_MCUSEL_NetworkMCU <<
				GPIO_PIN_CNF_MCUSEL_Pos);

大抵の人(私を含む)は、NRF_P0_S->PIN_CN という定義を探し回って途方にくれることでしょう。なーんだ、GPIO のピン番号を配列要素で指定すればいいだけじゃん。それくらい、README に書いておいて欲しいです…。(涙)

これで、empty_app_core をビルドし直し、Application MCU に書き直すと、無事に Network MCU と通信できるようになりました。あ、P0.25 が MCU の TxD(出力)で、P0.26 が RxD(入力)ですよ。

*** Booting Zephyr OS build v2.3.0-rc1-ncs1  ***
Starting Bluetooth Throughput example
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF53x (0x0003)
I: Firmware: Standard Bluetooth controller (0x00) Version 2.3 Build 0
I: Identity: xx:xx:xx:xx:xx:xx (random)
I: HCI: version 5.2 (0x0b) revision 0x0000, manufacturer 0x05f1
I: LMP: version 5.2 (0x0b) subver 0xffff
Bluetooth initialized
Choose device role - type s (slave role) or m (master role): 

折角の仮想 TTY を使いたい…

まあ、ここまでやれば FTDI のケーブルなどを使ってシリアル通信できる訳ですが、折角ボード上に USB - UART ブリッジを載せているのですから、それを使いたいですよね。

ここからは、細かく書く元気を失っているので(後日、加筆するかも)、簡単にまとめておきます。

  1. まず、empty_app_core の network_gpio_allow() では、25 と26 ではなくて、20 と 22 を Network MCU に割り当てておきます。
  2. 次のようなファイルを nrf5340pdk_nrf5340_cpunet.overlay として作成します。(実は、こちらを参考にしました。)
&uart0 {
	current-speed = <115200>;
	status = "okay";
	tx-pin = <20>;
	rx-pin = <22>;
	rts-pin = <19>;
	cts-pin = <21>;
};

3.  west build -b nrf5340pdk_nrf5340_cpunet --
-DDTC_OVERLAY_FILE=nrf5340pdk_nrf5340_cpunet.overlay
として、Bluetooth Throughput デモをビルドします。

これで、Network MCU のコンソールが、USB の仮想 tty(/dev/ttyACM2)に繋がりました。めでたし、めでたし。

通信速度の結果

2台の nRF5340 PDK を、ステンレス板で作成した簡易電波暗室に納め、実効通信速度を測定してみました。6回実行した結果を示します。

[local] received 612684 bytes (598 KB) in 2511 GATT writes at 1111628 bps
[local] received 612684 bytes (598 KB) in 2511 GATT writes at 960985 bps
[local] received 612684 bytes (598 KB) in 2511 GATT writes at 1005184 bps
[local] received 612684 bytes (598 KB) in 2511 GATT writes at 1232013 bps
[local] received 612684 bytes (598 KB) in 2511 GATT writes at 1254453 bps
[local] received 612684 bytes (598 KB) in 2511 GATT writes at 1255286 bps

平均で、1.1Mbps 程度というところでしょうか。

今日はここまで。

お問い合わせはお気軽に!

御返答は 24時間以内(営業時間中)とさせて頂いております。もし返答が届かない場合、何らかの事情でメールが不達となっている可能性がございます。大変お手数ですが、別のメールアドレス等で督促頂けますと幸いです。なお、Facebook ページ(https://www.facebook.com/flogics/)でも御連絡頂けます。