Jetson NanoのSPIを有効にする

こんにちは、satoです。
いま、こんな感じでRaspberry Pi MouseにJetson Nanoを載せて新しいことができないかなーと試行錯誤中です。試行錯誤の過程でデフォルトでは無効になっているSPI(SPI1)を有効にする必要がありましたので、今回はJetson NanoをにインストールしているUbuntuのデバイスツリーを編集してSPIを有効にする方法をご紹介します。

注意点

今回ご紹介する方法は、2019年5月16日現在、公式のドキュメントには書かれていない内容です。手元のJetson Nanoでは動作確認をしていますが、このページ内で紹介する方法については責任を負いかねます。またJetson NanoにはL4T(Linux for Tegra) R32.1があらかじめインストールしてあり、起動できるようになっている前提で説明します。

作業手順

以下の手順に沿って作業を進めていきます。

  • SPIが有効になっているか確認
  • SPI用のカーネルモジュールであるspidevがロードできる状態か確認
  • デバイスツリーの再構築

必要なもの

SPIを有効にするには以下のものが必要です。

  • Jetson Nano
  • microSDカード
  • Ubuntuがインストールされた作業用PC
    • 仮想マシンではうまくいかない場合があるようです
    • 空き容量が最低でも5GB以上必要そうです
  • microUSBケーブル
    • PCとJetson Nanoを接続するために用います
  • 2.1mmプラグ出力のDC 5V電源
    • Jetson Nanoへの電源供給に用います
  • ジャンパピン x2
    • Jetson Nanoのピンをショートしてリカバリーモードに設定するのに用います
  • HDMI接続可能なディスプレイ
  • HDMIケーブル
  • キーボード

SPIが有効になっているかの確認

まずはじめに、SPIが有効になっているか(デフォルトでは無効になっているようです)を確認します。Jetson Nano上で作業します。

端末を開き、sudo cat /sys/kernel/debug/tegra_gpioを実行することでJetson Nanoのalternate special functionの状態を確認できます。以下のようにCの列が1fになっているとSPIは有効になっていないことがわかります(https://elinux.org/Jetson/TX1_SPI)。

$ sudo cat /sys/kernel/debug/tegra_gpio
Name:Bank:Port CNF OE OUT IN INT_STA INT_ENB INT_LVL
 A: 0:0 64 40 40 04 00 00 000000
 B: 0:1 f0 00 00 00 00 00 000000
 C: 0:2 1f 00 00 00 00 00 000000
 D: 0:3 00 00 00 00 00 00 000000
 E: 1:0 40 00 00 00 00 00 000000
 F: 1:1 00 00 00 00 00 00 000000
 G: 1:2 0c 00 00 04 00 00 000000
 H: 1:3 fd 99 00 60 00 00 000000
 I: 2:0 07 05 00 02 00 00 000000
 J: 2:1 f0 00 00 00 00 00 000000
 K: 2:2 00 00 00 00 00 00 000000
 L: 2:3 00 00 00 00 00 00 000000
 M: 3:0 00 00 00 00 00 00 000000
 N: 3:1 00 00 00 00 00 00 000000
 O: 3:2 00 00 00 00 00 00 000000
 P: 3:3 00 00 00 00 00 00 000000
 Q: 4:0 00 00 00 00 00 00 000000
 R: 4:1 00 00 00 00 00 00 000000
 S: 4:2 a0 80 00 00 00 00 000000
 T: 4:3 01 01 00 00 00 00 000000
 U: 5:0 00 00 00 00 00 00 000000
 V: 5:1 03 00 00 02 00 00 000000
 W: 5:2 00 00 00 00 00 00 000000
 X: 5:3 78 08 08 70 00 60 606000
 Y: 6:0 06 00 00 02 00 00 000000
 Z: 6:1 0f 08 08 04 00 06 020600
AA: 6:2 00 00 00 00 00 00 000000
BB: 6:3 01 00 00 00 00 00 000000
CC: 7:0 12 00 00 10 00 12 121200
DD: 7:1 01 00 00 00 00 00 000000
EE: 7:2 00 00 00 00 00 00 000000
FF: 7:3 00 00 00 00 00 00 000000

SPIが有効になっていると以下ようにCの列が00の結果を取得できます。

$ sudo cat /sys/kernel/debug/tegra_gpio
Name:Bank:Port CNF OE OUT IN INT_STA INT_ENB INT_LVL
 A: 0:0 64 40 40 04 00 00 000000
 B: 0:1 f0 00 00 00 00 00 000000
 C: 0:2 00 00 00 00 00 00 000000
 D: 0:3 00 00 00 00 00 00 000000
 E: 1:0 40 00 00 00 00 00 000000
 F: 1:1 00 00 00 00 00 00 000000
 G: 1:2 0c 00 00 04 00 00 000000
 H: 1:3 fd 99 00 60 00 00 000000
 I: 2:0 07 05 00 02 00 00 000000
 J: 2:1 f0 00 00 00 00 00 000000
 K: 2:2 00 00 00 00 00 00 000000
 L: 2:3 00 00 00 00 00 00 000000
 M: 3:0 00 00 00 00 00 00 000000
 N: 3:1 00 00 00 00 00 00 000000
 O: 3:2 00 00 00 00 00 00 000000
 P: 3:3 00 00 00 00 00 00 000000
 Q: 4:0 00 00 00 00 00 00 000000
 R: 4:1 00 00 00 00 00 00 000000
 S: 4:2 a0 80 00 00 00 00 000000
 T: 4:3 01 01 00 00 00 00 000000
 U: 5:0 00 00 00 00 00 00 000000
 V: 5:1 03 00 00 02 00 00 000000
 W: 5:2 00 00 00 00 00 00 000000
 X: 5:3 78 08 08 70 00 60 606000
 Y: 6:0 06 00 00 02 00 00 000000
 Z: 6:1 0f 08 08 04 00 06 020600
AA: 6:2 00 00 00 00 00 00 000000
BB: 6:3 01 00 00 00 00 00 000000
CC: 7:0 12 00 00 10 00 12 121200
DD: 7:1 01 00 00 00 00 00 000000
EE: 7:2 00 00 00 00 00 00 000000
FF: 7:3 00 00 00 00 00 00 000000

SPI用のカーネルモジュールの確認

SPI用のカーネルモジュールであるspidevがビルドされているかを確認します。Jetson TX1やTX2のドキュメントを確認すると、以前はこのカーネルモジュールも手動でビルドする必要があったようです。Jetson Nanoの端末上でmodinfo spidevを実行し、SPI用のカーネルモジュールが存在するかを確認します。すでにビルドされていれば以下のようにspidev.koまでのファイルパスが取得できます。

$ modinfo spidev
filename:       /lib/modules/4.9.140-tegra/kernel/drivers/spi/spidev.ko
alias:          spi:spidev
license:        GPL
description:    User mode SPI device interface
author:         Andrea Paterniani, <a.paterniani@swapp-eng.it>
alias:          of:N*T*Clineartechnology,ltc2488C*
alias:          of:N*T*Clineartechnology,ltc2488
alias:          of:N*T*Crohm,dh2228fvC*
alias:          of:N*T*Crohm,dh2228fv
alias:          of:N*T*CspidevC*
alias:          of:N*T*Cspidev
depends:
intree:         Y
vermagic:       4.9.140-tegra SMP preempt mod_unload modversions aarch64
parm:           bufsiz:data bytes in biggest supported SPI message (uint)

デバイスツリーの再構築

Jetson Nanoの準備

デバイスツリーの再構築にあたり、まずはJetson Nanoをリカバリーモードで起動する必要があります。電源を切った状態のJetson NanoのJ48とJ40の3, 4番ピンをジャンパピンを用いてショートします(https://developer.nvidia.com/embedded/dlc/jetson-nano-dev-kit-user-guide)。

リカバリーモードに入るためにショートするピン

この状態でJ25にDC 5Vを供給します。電源を接続したあとはJ40のピンは外しても付けたままでもどちらでも問題ありません。J48は電源供給状態切り替えのためのピンなので外すことはできません。リカバリーモードで起動できているとHDMIで接続したディスプレイには何も出力されません。最初にリカバリーモードで起動したときは不安になるかもしれませんが、そういう仕様のようです。

電源を接続したJetson Nano

デバイスツリーの再構築とJetson Nanoへの書き込み

ここから先はUbuntuがインストールされた作業用PCを用いて作業をしていきます。作業用PCにはUbuntu 16.04.5のマシンを使用してテストしました。作業に必要なコードはGitHub(https://github.com/rt-net/JetsonNano_DT_SPI)に公開しています。公開したコードを用いてデバイスツリーの再構築をします。

gitコマンドでGitHubからリポジトリをダウンロードします。

$ git clone https://github.com/rt-net/JetsonNano_DT_SPI.git

ダウンロードしたリポジトリの中は以下のような構成になっています。

$ cd JetsonNano_DT_SPI && tree
.
├── LICENSE
├── README.md
├── run.sh
└── tegra210-p3448-0000-p3449-0000-a02.dts

LICENSEREADME.mdはGitHubに公開する際に追加したドキュメントです。今回は使用しません。run.shがNVIDIAのサイトからJetson Nanoへのファイル書き込みに必要なファイルをダウンロードしてJetson Nanoへファイルを書き込むためのツール、tegra210-p3448-0000-p3449-0000-a02.dtsがSPI1を有効にするためのデバイスツリーのソースです。

SPI1を有効にしたtegra210-p3448-0000-p3449-0000-a02.dtsをコンパイルして書き込むためには、リカバリーモードで起動したJetson Nanoと作業用PCをUSBケーブルで接続し、作業用PC上の端末で

$ ./run.sh

と実行すれば完了なのですが、今回はrun.shについて少し説明します。

以下に7〜15行目を抜粋します。ここではQuick Start Guide(https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Fquick_start.html%23)に沿ってファイルをダウンロードし、ファイルを配置しています。

以下に16〜20行目を抜粋します。ここでは先ほどの13行目でダウンロードしたL4Tのソースファイルのうち、デバイスツリーのバイナリの一部についてバックアップをとり、JetsonNano_DT_SPIに公開されているデバイスツリーのソース(tegra210-p3448-0000-p3449-0000-a02.dts)をコンパイルしたものと置き換えています。

以下に21行目を抜粋します。ここではこのあとで実行するスクリプトのためにファイルの所有権をrootに書き換えています。

以下に24〜27行目を抜粋します。ここではNVIDIA user space librariesを書き込むディレクトリにコピーし(https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Frootfs_custom.html%23wwpID0E0NB0HA)、デバイスツリーのみをUSBケーブル経由でJetson Nanoに書き込んでいます(https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Fflashing.html%23wwpID0E0LB0HA)。

以下に6行目を抜粋します。ここではJetson Nanoに書き込むファイルがすでに用意されているかを確認しています。このおかげで2回目にrun.shを実行する際は7〜21行目までのスクリプトは実行されず24〜27行目のみ実行されます。

ruh.shからflash.shを実行して無事に書き込みができると、Jetson Nanoが再起動します。ここでJetson Nanoで端末を開いて以下のように「SPIが有効になっているかの確認」で紹介したコマンドを実行することでデバイスツリーの再構築ができていることを確認できます。

$ sudo cat /sys/kernel/debug/tegra_gpio | grep " C:"
 C: 0:2 00 00 00 00 00 00 000000
$ ls /dev/spi*
/dev/spi1.0

以上でJetson Nanoのデバイスツリーの再構築は完了です。

今回取り扱うデバイスツリーのバイナリ(*.dtb)についてはkernelディレクトリに入っており、デバイスツリーのソース(*.dts)は ダウンロードしたJetson-Nano-Tegra210_Linux_R32.1.0_aarch64.tbz2を展開すると得られるLinux_for_Tegra/source_sync.shを実行することでLinux_for_Tegra/sources以下にダウンロードすることができます(https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Fmanifest_jetson_nano.html%23wwpID0E0KB0HA)。具体的には今回編集するtegra210-p3448-0002-p3449-0000-a02.dtbのソースはLinux_for_Tegra/sources/hardware/nvidia/platform/t210/porg/kernel-dts/tegra210-p3448-0002-p3449-0000-a02.dtsにダウンロードできます。このファイルはGPL v2ライセンスで公開されています。

SPI2を有効にする方法については参考サイトで紹介しているNVIDIA Developer Forums(https://devtalk.nvidia.com/default/topic/1050427/jetson-nano/enabling-spidev-on-the-jetson-nano-is-hanging-when-flashing/post/5338398/#5338398)でjas-mxさんが公開しています。今回のSPI1を有効にするスクリプトとデバイスツリーのソースはjas-mxさんが公開している情報を元に作成されました。

SPI1とSPI2が割り当てられているピンは以下のサイトから確認できます。

まとめ

Jetson NanoのSPI(SPI1)を有効にするためのスクリプトをGitHub(https://github.com/rt-net/JetsonNano_DT_SPI)に公開したので、スクリプトの内容とその使い方を紹介しました。使用するデバイスツリーのソースはGPL v2ライセンスで公開されており、ダウンロード用のスクリプトを実行することで、ダウンロードすることができます。

参考サイト

NVIDIA Developer Forums

Enabling spidev on the jetson nano is hanging when flashing – NVIDIA Developer Forums(2019年5月16日閲覧):

https://devtalk.nvidia.com/default/topic/1050427/jetson-nano/enabling-spidev-on-the-jetson-nano-is-hanging-when-flashing/post/5338398/#5338398

NVIDIA Tegra Linux Driver Package Development Guide

Flashing a Specific Partition – L4T Development Guide(2019年5月16日閲覧):

https://docs.nvidia.com/jetson/l4t/index.html#page/Tegra%2520Linux%2520Driver%2520Package%2520Development%2520Guide%2Fflashing.html%23wwpID0E0LB0HA