Linux

【ZynqMP】3.認定UbuntuのDeviceTree変更

1.記事一覧

記事は複数回に分けて投稿する予定です。AMD/XilinxのARM64 SoC(ZynqMP Kria K26 SOM)で動作する、AMD/Xilinx公式認定Ubuntuやベアメタル開発を勉強していく覚書きです。

Zynq7000(armv7)版はこちら

2.【概要】標準のDevicetreeをカスタムする

XilinxのKria K26 SOMボードを搭載した公式評価ボード、KR260を用いたLinuxの勉強記事です。

第1回の【ZynqMP】1.認定UbuntuでPLのGPIOではDevicetree OverlayによるLinux動作中のDevicetree書換えを行いました。今回は元となる、ベースのDevicetreeを変更してみたいと思います。Linux起動中に変更する必要がない部分や、現在無効化されているツリーを有効化してLinux起動したい場合などに必要となります。

この内容は公式のXilinx-Wikiを参考にやっていきます。また、参考情報としてikwzmさんの記事を読んでいただくと良いと思います。

デバイスツリーにシンボル情報を埋め込む|@ikwzm様

また、u-bootのbootパラーメータ環境変数bootargsの設定変更もついでにやってみます。

今回やること

  • 実機KR260からデバイスツリーを読み出す
  • デバイスツリーを変更する(今回はやりません)
  • デバイスツリーをコンパイルして更新する
  • bootパラメータbootargsの変更

今回使用する環境

開発ツールDTC(Device Tree Compiler)
ターゲットボードXilinx社製 Kria KR260 ロボティクススターターキット(SK-KR260-G)
SOM : Xilinx社 Kria K26 SOM (Zynq UltraScale+ MPSoCベース)
   APU : Arm CA53x4 1333MHz arm64
   RPU : Arm CR5x2 533MHz armv7-R
SDRAM : DDR4 4GB
QSPI Firmware : Xilinx download – 2022.2_update1_BOOT.BIN
Linux Kernel : v5.15.0-1023-xilinx-zynqmp by 認定Ubuntu
OS : Xilinx認定Ubuntu22.04 LTS(arm64)

3.ベースデバイスツリーを変更する

3-1. 実機からDevicetreeを読み出す

SysFsからDTS(Device Tree Source)を読み出します。

ShellScript
ubuntu@kria:~/$ sudo dtc /sys/firmware/fdt >system.dts

3-2. デバイスツリーソースを見てみる

非常に長いので全ては載せませんが、最後にシンボル情報が出力されているのがわかります。

/dts-v1/;

/memreserve/	0x00000000755e4000 0x0000000003a1bc01;
/ {
	compatible = "xlnx,zynqmp-sk-kr260-revB\0xlnx,zynqmp-sk-kr260\0xlnx,zynqmp";
	#address-cells = <0x02>;
	#size-cells = <0x02>;
	model = "ZynqMP SMK-K26 Rev1/B/A";

	clock5 {
		clock-frequency = <0x17d7840>;
		#clock-cells = <0x00>;
		compatible = "fixed-clock";
	};

	clock4 {
		clock-frequency = <0x17d7840>;
		#clock-cells = <0x00>;
		compatible = "fixed-clock";
	};

	clock3 {
		clock-frequency = <0x9502f90>;
		#clock-cells = <0x00>;
		compatible = "fixed-clock";
	};
[...略]
	__symbols__ {
		cpu0 = "/cpus/cpu@0";
		cpu1 = "/cpus/cpu@1";
		cpu2 = "/cpus/cpu@2";
		cpu3 = "/cpus/cpu@3";
		CPU_SLEEP_0 = "/cpus/idle-states/cpu-sleep-0";
		cpu_opp_table = "/cpu-opp-table";
		zynqmp_ipi = "/zynqmp_ipi";
		ipi_mailbox_pmu1 = "/zynqmp_ipi/mailbox@ff990400";
		dcc = "/dcc";
[...略]

3-3. デバイスツリーのコンパイル

今回は特に改変しませんが、改変したと仮定して新しいデバイスツリーソースをLinuxに組み込んでいきます。まずはデバイスツリーをコンパイルするためのコンパイラを導入します。

認定UbuntuでDTCがプリインストールされていたか、自分で入れたか私は忘れてしまったため、下記コマンドで入っているか確認します。

ShellScript
ubuntu@kria:~$ dtc -v
Version: DTC 1.6.1

入っていなかった場合、第1回の1.認定UbuntuでPLのGPIOを使う>6-1. DTC(Device Tree Compiler)の準備を参考にDTCを導入します。

Devicetree Overlayを使うためにはベースDevicetreeでシンボル情報を出力してコンパイルする必要があります。シンボルを出力できるコンパイラはVer1.4.2以降です。

デバイスツリーソース(DTS)をシンボル出力(-@)でコンパイルします。

DTBのファイル名は”user-override.dtb”にします。

ShellScript
ubuntu@kria:~$ dtc -@ -O dtb -o user-override.dtb system.dts

warningが出力されますが、dtbは生成されます。VivadoのXSCTで生成したデバイスツリーのコンパイルでも同じ様なwarningが出力されます。ちょっと不安になりますが、このまま進めることにします。

3-4. カスタムデバイスツリーの配置

公式Wikiによると、FATパーティションに配置すればu-bootがこちらを優先して読み込む仕様のようです。FATパーティションを探してみます。

ShellScript
ubuntu@kria:~$ df -T
Filesystem     Type  1K-blocks     Used Available Use% Mounted on
tmpfs          tmpfs    400060     3656    396404   1% /run
/dev/sda2      ext4   60281772 11971140  45761764  21% /
tmpfs          tmpfs   2000292        0   2000292   0% /dev/shm
tmpfs          tmpfs      5120        4      5116   1% /run/lock
/dev/sda1      vfat    1032428   152149    880279  15% /boot/firmware
tmpfs          tmpfs    400056       64    399992   1% /run/user/1000

/boot/firmware以下のようです。こちらにuser-override.dtbを配置します。

ShellScript
ubuntu@kria:~$ sudo cp user-override.dtb /boot/firmware/

再起動をすれば、カスタムデバイスツリーが読み込まれます。

3-5. カスタムデバイスツリーがロードされたか確認

user-override.dtbがロードされているか、u-bootのログを見てみます。u-bootのログを取る場合、私の環境ではjtag用のmicro-USBケーブルをPCと接続します。PCはUbuntu20.04で、/dev/ttyUSB1がシリアルコンソールになっていました。以下のコマンドでコンソールのログを取ります。

ShellScript
# Ctrl + cで終了
$ cat /dev/ttyUSB1 |tee ./tty001.log

上記のログ記録を実行しつつ、別端末でSSHにログインし、再起動を実施します。

U-Boot 2022.01 (Jan 25 2023 - 08:10:44 +0000)

CPU:   ZynqMP
Silicon: v3
Detected name: zynqmp-smk-k26-xcl2g-rev1-sck-kr-g-rev1
Model: ZynqMP SMK-K26 Rev1/B/A
Board: Xilinx ZynqMP
DRAM:  4 GiB
PMUFW:	v1.1


[...略]


Found U-Boot script /boot.scr.uimg
6918 bytes read in 3 ms (2.2 MiB/s)
## Executing script at 20000000
Selecting DT for Kria boards
Kria DT: #conf-smk-k26-revA-sck-kr-g-revB
Configuring the cma value based on the board type
cma=1000M
Loading user-override.dtb
43626 bytes read in 5 ms (8.3 MiB/s)
Loading image.fit
80231820 bytes read in 5440 ms (14.1 MiB/s)
## Loading kernel from FIT Image at 10000000 ...
   Using 'conf-smk-k26-revA-sck-kr-g-revB' configuration
[...略]

カスタムデバイスツリーがロードされていました。

ログ記録がバグる場合、一度screenなどで/dev/ttyUSB1に入ってから出るをやってからcatするとうまく行きました。理由はよくわかりません。

ShellScript
#一度シリアルコンソールに入る
$ screen /dev/ttyUSB1 115200
# Ctrl + aを押してからkを押して抜ける

4.bootパラメータbootargsを変更する

開発をする上でbootパラメータを変更したいことがあるかと思います(“debug”など)。デバイスツリーを変更するついでにbootパラメータの変更もやってみます。

Kria K26 SOM公式ページによると、u-boot本体はSDカード側ではなく、QSPIにファームウェアとして書き込まれています。u-bootにはbootargs環境変数があり、bootパラメータの値が格納されています。実際にはSDカードのboot.scrスクリプトを読み出す様になっているため、bootargsはこの中に実装されているものと思われます。

今回は公式手順に従い、bootargsを変更してみます。

4-1. 現在適用されているbootパラメータを確認

KR260にSSHでログインし、以下のコマンドで確認します。

ShellScript
ubuntu@kria:~$ cat /proc/cmdline 
 root=LABEL=writable rootwait earlycon console=ttyPS1,115200 console=tty1 clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio xilinx_tsn_ep.st_pcp=4 cma=1000M

デフォルトのCMAサイズを変更してみます。CMA(Contiguous Memory Allocator)とはDMAバッファを確保する際、物理アドレスが連続した大きな領域を確保できるメモリアロケータです。

4-2. bootargs専用設定ファイルを更新する

公式によると、/etc/default/flash-kernelのファイルの変数を書き換えれば良いようです。

ShellScript
ubuntu@kria:~$ cat /etc/default/flash-kernel
LINUX_KERNEL_CMDLINE=""
LINUX_KERNEL_CMDLINE_DEFAULTS=""

LINUX_KERNEL_CMDLINE
デフォルトのbootargsの内容の後、つまり右側に追記する内容をここに書きます。(おそらくですが、bootargsは右側に書かれているほど優先度が高いです)

LINUX_KERNEL_CMDLINE_DEFAULTS
デフォルトのbootargsの内容の前、つまり左側に追記する内容をここに書きます。

それではCMAを512MBに変更してみます。

ShellScript
# viでもなんでも良いです
ubuntu@kria:~$ sudo nano /etc/default/flash-kernel
# 確認
ubuntu@kria:~$ cat /etc/default/flash-kernel
LINUX_KERNEL_CMDLINE="cma=512M"
LINUX_KERNEL_CMDLINE_DEFAULTS=""

4-3. カスタムbootargsを適用する

次のコマンドで更新します。

ShellScript
ubuntu@kria:~$ sudo flash-kernel
flash-kernel: installing version 5.15.0-1023-xilinx-zynqmp
Couldn't find DTB  on the following paths: /etc/flash-kernel/dtbs /usr/lib/linux-image-5.15.0-1023-xilinx-zynqmp /lib/firmware/5.15.0-1023-xilinx-zynqmp/device-tree/
Generating u-boot image... done.
Taking backup of image.fit.
Installing new image.fit.
Generating boot script u-boot image... done.
Taking backup of boot.scr.uimg.
Installing new boot.scr.uimg.
$ sudo reboot

再起動してbootパラメータを確認します。後ろに追記されていました。

ShellScript
ubuntu@kria:~$ cat /proc/cmdline 
 root=LABEL=writable rootwait earlycon console=ttyPS1,115200 console=tty1 clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio xilinx_tsn_ep.st_pcp=4 cma=1000M cma=512M

/proc/meminfo:Linux上で確認できます。

ShellScript
ubuntu@kria:~$ cat /proc/meminfo |grep  Cma
CmaTotal:         524288 kB
CmaFree:          520668 kB

ちなみにu-bootログではcma=1000Mの方が出ていました。これは確認に使えないですね。

U-Boot 2022.01 (Jan 25 2023 - 08:10:44 +0000)

CPU:   ZynqMP
Silicon: v3
Detected name: zynqmp-smk-k26-xcl2g-rev1-sck-kr-g-rev1
Model: ZynqMP SMK-K26 Rev1/B/A
Board: Xilinx ZynqMP
DRAM:  4 GiB
PMUFW:	v1.1

[...略]

Kria DT: #conf-smk-k26-revA-sck-kr-g-revB
Configuring the cma value based on the board type
cma=1000M
Loading user-override.dtb
43626 bytes read in 6 ms (6.9 MiB/s)
Loading image.fit
80231820 bytes read in 5408 ms (14.1 MiB/s)

[...略]

Starting kernel ...

[...略]

[    0.000000] CPU features: detected: ARM erratum 845719
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 1032192
[    0.000000] Policy zone: Normal
[    0.000000] Kernel command line:  root=LABEL=writable rootwait earlycon console=ttyPS1,115200 console=tty1 clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio xilinx_tsn_ep.st_pcp=4 cma=1000M cma=512M
[    0.000000] Dentry cache hash table entries: 524288 (order: 10, 4194304 bytes, linear)
[    0.000000] Inode-cache hash table entries: 262144 (order: 9, 2097152 bytes, linear)
[...略]

4-4. bootargsの内容を間違ってしまった時

Ubuntuが起動する場合

/etc/default/flash-kernelを修正して再度flash-kernelを実行します。flash-kernelは過去に追記した引数を削除してから追記し直します。

ShellScript
#ミスって512Mではなく、512にしてしまった
ubuntu@kria:~$ cat /proc/cmdline 
 root=LABEL=writable rootwait earlycon console=ttyPS1,115200 console=tty1 clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio xilinx_tsn_ep.st_pcp=4 cma=1000M cma=512

# 間違えた場合はそのまま修正すれば良い
ubuntu@kria:~$ sudo nano /etc/default/flash-kernel
# 確認
ubuntu@kria:~$ cat /etc/default/flash-kernel
LINUX_KERNEL_CMDLINE="512M"
LINUX_KERNEL_CMDLINE_DEFAULTS=""

# 再度flash-kernel
ubuntu@kria:~$ sudo flash-kernel
ubuntu@kria:~$ sudo reboot

#過去に追記したものは消える
ubuntu@kria:~$ cat /proc/cmdline 
 root=LABEL=writable rootwait earlycon console=ttyPS1,115200 console=tty1 clk_ignore_unused uio_pdrv_genirq.of_id=generic-uio xilinx_tsn_ep.st_pcp=4 cma=1000M cma=512M

Ubuntuが起動しない時

私はこのケースに遭遇したことがないので、確実なことは言えませんが、SDカードのFATパーティションにboot.scr.uimgの中にbootargsがいる(と思われる)ので、boot.scr.uimg.bakが存在すれば差し替えを行うと行けるかもしれません。なければ公式Ubuntuのイメージから取り出したりします。

ABOUT ME
sh-goto
組込エンジニア. 最近の遊びはLinuxの低レイヤいじりとXilinxのZynqとFPGAを使った電子工作
関連記事