JetPack6.0 DP(L4T36.2.0)の味見 + IMX708カメラドライバ移植トライ

# はじめに

JetPack6.0 DPが2023年末に公開されていたので、今更ながら動作確認をしました。
JetPackのインストールから躓きポイントがあり、ビルド関係も大きく変化していたのでIMX708の移植を通して確認した結果を共有します。


**あくまでDeveloppers Previewということで致命的なものは[forum](https://forums.developer.nvidia.com/)で、そうでないものGA対応を期待して待ちましょう。**

## 3行で

1. flash、ビルドするスクリプトは[GitHubで公開してます](https://github.com/uzuna/jetson-imx708/tree/l4t-36.2.0)
1. [公式のDeveloperGuide](https://docs.nvidia.com/jetson/archives/r36.2/DeveloperGuide/IN/QuickStart.html#to-flash-the-jetson-developer-kit-operating-software)の方法ではUSBの認識周りで失敗することがあり、USBケーブルの抜き差しで回避できます
1. [商用Linuxを使えるように](https://docs.nvidia.com/jetson/archives/r36.2/DeveloperGuide/SD/Kernel/BringYourOwnKernel.html)L4Tのソースの構造は大きく変わって、ビルド周りも5.xから大きく変わりました。ただしカメラドライバなどの記述には大きな変化はありません。


## BSPのflash環境

SDKManagerは使わず[公式のDeveloperGuideにある方法](https://docs.nvidia.com/jetson/archives/r36.2/DeveloperGuide/IN/QuickStart.html#to-flash-the-jetson-developer-kit-operating-software)でflashをします。

前のバージョンである`L4T 35.4.1`と殆ど差はなく`BSP`と`SampleRootfs`をダウンロード、展開してflashするだけになります。
ただし今回、私の環境ではflash成功するまでいくらか工夫が必要でした。

### bootup待ちでタイムアウトする件への対応

筆者の環境では以下のようにboot-up待ちでタイムアウトしていました。

```console
***************************************
*                                     *
*  Step 3: Start the flashing process *
*                                     *
***************************************
Waiting for target to boot-up...
Waiting for target to boot-up...
Waiting for target to boot-up...
Waiting for target to boot-up...
Waiting for target to boot-up...
Waiting for target to boot-up...
Waiting for target to boot-up...
Waiting for target to boot-up...
...
Waiting for target to boot-up...
Timeout
Cleaning up...
```

ここで重要なのは、**リカバリーモード中ではUSB Gadgetで通信経路を作りホストからの指示を受けるので、USB Gadgetが動作してホスト側から見えなければならない**ことです。
ホスト側で`dmesg`や`tail -f /var/log/kern.log`でログを見ると`Step 3: Start the flashing process`の後に以下のようなログが出ていました。

```
$ sudo dmesg
...
usb usb4-port2: Cannot enable. Maybe the USB cable is bad?
...
```

Jetson側は`L4T 35.4.1`から大きな変化はなく正しく設定は出来ているようだったので、このエラーが出た場合は電源をそのままにUSBケーブルをそのままで再接続をして、ホスト側にUSBを認識させれば良いです。
waiting中はUSBでの通信はしておらず、USBGadgetがEtherとMassStorageとして認識するまで待っているだけなのでUSBを外しても特に問題はありません。

他、リカバリーモード中はファンが動かなかったり期待通りに動作しなかったりします。flash中はかなり暑くなるので卓上ファンを用意するのが良さそうです。

また、以前はUSBのポートを見て何らかの判別をするためループを回していたようですが、Orinのみの対応になったので意味のないループで60秒待つ動作になっています。
[ここは修正して](https://github.com/uzuna/jetson-imx708/blob/l4t-36.2.0/bsp-flash/patches/nv_flash.patch#L9-L14)から使うことをおすすめします。

### flashサンプル

[サンプルスクリプト](https://github.com/uzuna/jetson-imx708/tree/l4t-36.2.0)に上の修正を含むビルドのスクリプトを用意しています。

```sh
export HOSTNAME=<your jetson hostname>

make -C bsp-flash pre-flash
# Connect Jetson orin nano with RecoveryMode
make -C bsp-flash flash
```

## BSPのビルド

今回LinuxのメインのカーネルとNVIDIAのドライバが分離されており、NVIDIA依存のモジュールがカーネルイメージ同梱からカーネルモジュールに切り出されています。
またツールチェインもGCC11.3に更新されており、基本的に以前までのカーネルとは別物として扱うのが良さそうです。

[公式の手順](https://docs.nvidia.com/jetson/archives/r36.2/DeveloperGuide/SD/Kernel/KernelCustomization.html#to-manually-download-and-expand-the-kernel-sources)にある通り、ビルドのために解答するファイルは3つに増えていました。

```console
$ cd <install-path>/Linux_for_Tegra/source
$ tar xf kernel_src.tbz2
$ tar xf kernel_oot_modules_src.tbz2
$ tar xf nvidia_kernel_display_driver_source.tbz2
```

中身としては以下の通りで、これまでkernel_srcに全て入っていたものが分離されています
1. `kernel_src.tbz2` -> Ubuntu JammyのLinux Kernel
1. `kernel_oot_modules_src.tbz2` -> NVIDIA out-of-tree modules
1. `nvidia_kernel_display_driver_source` -> Linux Kernel似合わせてコンパイルが必要なディスプレイドライバ

カメラドライバはout-of-treeの中に配置されています。

### ビルド時の順序

Makefileを見たところ以下のような順序になっています。

1. LinuxKernelをビルド
1. NVIDIA OOTのビルド
1. LinuxKernelとNVIDIA OOTの両方を参照してDisplayDriverのビルド

DisplayDriverでは前ステップのヘッダーとビルド成果物を元にconftestでヘッダを生成してビルドを行うため、期待するものと不一致が出るとビルドに失敗するので注意が必要です。

### ビルドサンプル

[サンプルスクリプト](https://github.com/uzuna/jetson-imx708/tree/l4t-36.2.0)にIMX708を含めてビルドするサンプルを用意しています。

```sh
make setup
make build_kernel
make apply_patch # IMX708 patch
make build_dtb
make build_modules
```


## IMX708のビルドと動作確認

ソースコードは`L4T 35.4.1`から変更することなく動作しました。デバイスツリーは記述が少し変わっています。
前回はメインのツリーに使う可能性のあるツリーを全て記述して、有効or無効を上書きして切り替えるものでしたが、今回からはベーツのツリーはそのままで、追加情報を持つツリーを起動時に読み込む仕様に変化しています。

```diff
LABEL JetsonIO
	MENU LABEL Custom Header Config: <CSI Camera IMX708 Dual>
	LINUX /boot/Image
	FDT /boot/dtb/kernel_tegra234-p3768-0000+p3767-0005-nv.dtb
	INITRD /boot/initrd
	APPEND ${cbootargs} root=PARTUUID=df4a1557-5d25-4704-9de6-6ae47f54bb65 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 firmware_class.path=/etc/firmware fbcon=map:0 net.ifnames=0 nospectre_bhb video=efifb:off console=tty0
+	OVERLAYS /boot/tegra234-p3767-camera-p3768-imx708-dual.dtbo
```

他、tegra-camera-platformの記述が少し変わっています。が、後述の通り関連にIssueがあり正常動作の確認がまだ出来ないのでここでは省略します。

### 動作確認結果

IMX708の**ドライバは**CAM0, CAM1どちらでも動作しました。
CAM1での動作確認は以下のとおりです。

```console
jetson@orin-nano:~/imx708$ make insmod 
sudo insmod nv_imx708.ko
[sudo] password for jetson: 
[   34.202978] imx708 10-001a: imx708_board_setup: error during i2c read probe (-121)
[   34.203009] imx708 10-001a: board setup failed
[   34.203075] imx708: probe of 10-001a failed with error -121
v4l2-ctl --list-devices
NVIDIA Tegra Video Input Device (platform:tegra-camrtc-ca):
        /dev/media0

vi-output, imx708 9-001a (platform:tegra-capture-vi:2):
        /dev/video0

sudo media-ctl -p -d /dev/media0
Media controller API version 5.15.122

Media device information
------------------------
driver          tegra-camrtc-ca
model           NVIDIA Tegra Video Input Device
serial          
bus info        
hw revision     0x3
driver version  5.15.122

Device topology
- entity 1: 13e00000.host1x:nvcsi@15a00000- (2 pads, 0 link)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev0
        pad0: Sink
        pad1: Source

- entity 4: 13e00000.host1x:nvcsi@15a00000- (2 pads, 2 links)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev1
        pad0: Sink
                <- "imx708 9-001a":0 [ENABLED]
        pad1: Source
                -> "vi-output, imx708 9-001a":0 [ENABLED]

- entity 7: imx708 9-001a (1 pad, 1 link)
            type V4L2 subdev subtype Sensor flags 0
            device node name /dev/v4l-subdev2
        pad0: Source
                [fmt:SRGGB10_1X10/4608x2592 field:none colorspace:srgb]
                -> "13e00000.host1x:nvcsi@15a00000-":0 [ENABLED]

- entity 9: vi-output, imx708 9-001a (1 pad, 1 link)
            type Node subtype V4L flags 0
            device node name /dev/video0
        pad0: Sink
                <- "13e00000.host1x:nvcsi@15a00000-":1 [ENABLED]

sudo systemctl restart nvargus-daemon
jetson@orin-nano:~/imx708$ make check.0
v4l2-ctl -d /dev/video0 --set-ctrl bypass_mode=0 --stream-mmap --stream-count=1 --stream-to=test.raw
<
jetson@orin-nano:~/imx708$ make check-fps.0
v4l2-ctl -d /dev/video0 --set-ctrl bypass_mode=0 --stream-mmap --stream-count=60
<<<<<<<<<<<<<<<< 14.36 fps
<<<<<<<<<<<<<< 14.36 fps
<<<<<<<<<<<<<<< 14.36 fps
<<<<<<<<<<<<<< 14.36 fps
<
```

GStreamer nvarguscamerasrcで映像取得はまだ動作していません。
IMX219では(シルク上の)CAM0接続、sensor-id=1で動作することが公式で確認されていますが、それ以外では動作しないようです。[issue:4327644 in release_note pdf](https://docs.nvidia.com/jetson/archives/r36.2/ReleaseNotes/Jetson_Linux_Release_Notes_r36.2.pdf)
V4L2からはデータが取得できているので、今は深追いしません。

```console
gst-launch-1.0 nvarguscamerasrc num-buffers=1 ! nvvidconv ! jpegenc ! filesink location=test.jpeg
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
GST_ARGUS: Creating output stream
CONSUMER: Waiting until producer is connected...
GST_ARGUS: Available Sensor modes :
GST_ARGUS: 4608 x 2592 FR = 14.350001 fps Duration = 69686408 ; Analog Gain range min 112.000000, max 960.000000; Exposure Range min 210000, max 68406000;

GST_ARGUS: 2304 x 1296 FR = 30.010000 fps Duration = 33322226 ; Analog Gain range min 112.000000, max 960.000000; Exposure Range min 52000, max 32680000;

GST_ARGUS: 1536 x 864 FR = 120.120005 fps Duration = 8325008 ; Analog Gain range min 112.000000, max 960.000000; Exposure Range min 36000, max 7970000;

GST_ARGUS: Running with following settings:
   Camera index = 0 
   Camera mode  = 1 
   Output Stream W = 2304 H = 1296 
   seconds to Run    = 0 
   Frame Rate = 30.010000 
GST_ARGUS: Setup Complete, Starting captures for 0 seconds
GST_ARGUS: Starting repeat capture requests.
CONSUMER: Producer has connected; continuing.
ERROR: from element /GstPipeline:pipeline0/GstNvArgusCameraSrc:nvarguscamerasrc0: TIMEOUT
Additional debug info:
Argus Error Status
nvbuf_utils: dmabuf_fd -1 mapped entry NOT found
Error generated. /dvs/git/dirty/git-master_linux/multimedia/nvgstreamer/gst-nvarguscamera/gstnvarguscamerasrc.cpp, threadExecute:694 NvBufSurfaceFromFd Failed.
Execution ended after 0:00:02.823941856
Error generated. /dvs/git/dirty/git-master_linux/multimedia/nvgstreamer/gst-nvarguscamera/gstnvarguscamerasrc.cpp, threadFunction:247 (propagating)
Setting pipeline to NULL ...
GST_ARGUS: Cleaning up
Freeing pipeline ...
```