🙌

Kria KV260 環境構築メモ(Ubuntu22.04 版)

2022/12/14に公開

概要

Kria KV260 にて 認定Ubuntu の 22.04 LTS にて構築した際の個人的メモです(備忘録)。

なお前回 Ubuntu 20.04 で構築したときのメモはこちらにあります。

Ubuntu 22.04 から KR260 も対応しているようですが、恐らく同じような感じではないかと思います。

環境構築

ファームウェアのアップデート

どうやらファームウェアの古いKV260の場合は、そのままだと Ubuntu 22.04 はうまく起動しないようです。私の場合そうだったのでバージョンアップしました。

ファームウェアバージョンアップについてはこちらを参照ください。
既に Ubuntu 20.04 が入っている場合は、こちらの別記事で紹介しています。

Ubuntu の SDカード作成

イメージはこちらから取得して、SDカードに書き込むことになります。

私が使ったバージョンは iot-limerick-kria-classic-desktop-2204-x06-20220614-78.img.xz でした。

Linux なら dd コマンド、Windows や Mac なら Balena EtcherWin32 DiskImager などを用いて書き込めばよいようです。

SDが出来上がったら、ボードに差し込んで電源を入れれば起動します。

キーボードやモニタを繋いでも良いかと思いますが、私の場合は USB を接続して、とりあえず TeraTerm からシリアル(UART)接続することが多いです。

初期アカウント ubuntu の 初期パスワードは ubuntu のようです。ログインするとパスワードを変えるように促されるので設定します。

ネットワークに繋いで

ip address

などとすると IP アドレスがわかるので、以降を ssh で接続することも可能です。

CUI/GUI の切り替え(お好みで)

GUI使わないという人はさっさとCUIに切り替えてしまう手もあるかもしれません。お好みでどうぞ。

# CUIにする
sudo systemctl set-default multi-user.target

# GUIにする
sudo systemctl set-default graphical.target

日本時間にする

SDカードのイメージは UTC のようだったので JST にします。

sudo timedatectl set-timezone Asia/Tokyo

ホスト名の変更(お好みで)

デフォルトの kria のままでも良いのですが、複数ボードを持っていたり、どのSDカードで起動してるかわかりやすくしたい場合などホスト名を変えるのもありかと思います。

hostnamectl set-hostname ubuntu22-kv260

のように変更できるようです。

ユーザーを作る(お好みで)

デフォルトのユーザー(ubuntu)をそのまま使ってもよいのですが、新規に作る場合は。

sudo adduser <username>

でユーザーを作って

sudo gpasswd -a <username> sudo

で sudo 権限を付けておきましょう。

NFSなどでマウントする(お好みで)

以前こちらで書きましたが、NFSマウント等を使うと便利ですので、NASなどお持ちの方はお好みでどうぞ。

/etc/fstab でも良いのですが、ネットワーク環境次第でこちらの方が便利なので autofs を使っています。

sudo apt update
sudo apt -y install nfs-common
sudo apt -y install autofs

でインストールして

sudo nano /etc/auto.master

として末尾に

/-    /etc/auto.mount

を追加

sudo mkdir /mnt/nfs
sudo nano /etc/auto.mount

/mnt/nfs -fstype=nfs,rw,nfsvers=3 XX.XX.XX.XX:/nfsshare

みたいな感じで、共有ディレクトリを指定

sudo systemctl restart autofs

で完了。

なお、私は auto.mount にさらにもう一行追加して、自分のホームディレクトリを丸々NASにマウントしています。
(そうするとSDカード壊れてもダメージが小さいです)。

fclkcfg と u-dma-buf のインストール

ZynqMP開発の定番となっている ikwzm氏の fclkcfgu-dma-buf をインストールします。

git clone --recursive --depth=1 -b v1.7.2 https://github.com/ikwzm/fclkcfg-kmod-dpkg
cd fclkcfg-kmod-dpkg
sudo debian/rules binary
cd ..
sudo dpkg -i fclkcfg-5.15.0-1010-xilinx-zynqmp_1.7.2-1_arm64.deb

git clone --recursive --depth=1 -b v4.0.0 https://github.com/ikwzm/u-dma-buf-kmod-dpkg
cd u-dma-buf-kmod-dpkg
sudo debian/rules binary
cd ..
sudo dpkg -i u-dma-buf-5.15.0-1010-xilinx-zynqmp_4.0.0-0_arm64.deb
sudo dpkg -i u-dma-buf-mgr-5.15.0-1010-xilinx-zynqmp_4.0.0-0_arm64.deb 

Xilinx 標準ツールのインストール(お好みで)

こちらにある手順をやっておきます。

sudo apt update
sudo apt install net-tools
sudo snap install xlnx-config --classic --channel=2.x
sudo xlnx-config.sysinit

JTAG の為の設定 と CMA 領域の変更(RPU利用時)

ここでは bootargs に関連する 2点を変更します。

まず一点目は CMA サイズです。デフォルトで CMA 領域は 1000M 確保されているようです。

ただし、この後の RPU の認識を行うときに vitis などが OpenAMP を利用時にデフォルトで使うアドレスをリザーブすると、連続領域で確保できなくなりエラーとなるので、変更しておきます(ここはそのままにして、RPU 側の利用するメモリを移動させる手もあると思います)。

もう一点は、JTAG接続時にハングしてしまう問題で、これは cpuidle.off=1 を指定すると回避できます(アイドル時にCPUが寝ないので、消費電力は増えるかもしれません)。

sudo nano /etc/default/flash-kernel

のように開いて、私の場合下記のようにしました。

LINUX_KERNEL_CMDLINE="quiet splash cma=512M cpuidle.off=1"
LINUX_KERNEL_CMDLINE_DEFAULTS=""

続けて

sudo flash-kernel

とすれば設定できるようです。

なお、現在の設定を見るには

cat /proc/cmdline

とすればよいようです。

RPU (Cortex-R5) を認識させる

詳しい記事はこちらに書いております。

下記の方法で現状のデバイスツリーを取得します。

sudo dtc /sys/firmware/fdt 2> /dev/null > system.dts

取得した system.dts に対して、まず interrupt-controller@f9010000 のセクションを探して "gic:" を追記しました。

    gic: interrupt-controller@f9010000 {

次に zynqmp-firmware のセクションを探して "zynqmp_firmware:" を追記しました。

    zynqmp_firmware: zynqmp-firmware {

最後に __symbols__ の直前に下記を追記しました。

    reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        rpu0vdev0vring0: rpu0vdev0vring0@7ed40000 {
            no-map;
            reg = <0x0 0x7ed40000 0x0 0x4000>;
        };
        rpu0vdev0vring1: rpu0vdev0vring1@7ed44000 {
            no-map;
            reg = <0x0 0x7ed44000 0x0 0x4000>;
        };
        rpu0vdev0buffer: rpu0vdev0buffer@7ed48000 {
            no-map;
            reg = <0x0 0x7ed48000 0x0 0x100000>;
        };
        rproc_0_reserved: rproc_0_reserved@7ed00000 {
            no-map;
            reg = <0x0 0x7ed00000 0x0 0x40000>;
        };
        
        rpu1vdev0vring0: rpu1vdev0vring0@7ef40000 {
            no-map;
            reg = <0x0 0x7ef40000 0x0 0x4000>;
        };
        rpu1vdev0vring1: rpu1vdev0vring1@7ef44000 {
            no-map;
            reg = <0x0 0x7ef44000 0x0 0x4000>;
        };
        rpu1vdev0buffer: rpu1vdev0buffer@7ef48000 {
            no-map;
            reg = <0x0 0x7ef48000 0x0 0x100000>;
        };
        rproc_1_reserved: rproc_1_reserved@7ef00000 {
            no-map;
            reg = <0x0 0x7ef00000 0x0 0x40000>;
        };
    };


    tcm_0a: tcm_0a@ffe00000 {
        no-map;
        reg = <0x0 0xffe00000 0x0 0x10000>;
        status = "okay";
        compatible = "mmio-sram";
        power-domain = <&zynqmp_firmware 15>;
    };

    tcm_0b: tcm_0b@ffe20000 {
        no-map;
        reg = <0x0 0xffe20000 0x0 0x10000>;
        status = "okay";
        compatible = "mmio-sram";
        power-domain = <&zynqmp_firmware 16>;
    };

    tcm_1a: tcm_1a@ffe90000 {
        no-map;
        reg = <0x0 0xffe90000 0x0 0x10000>;
        status = "okay";
        compatible = "mmio-sram";
        power-domain = <&zynqmp_firmware 17>;
    };
 
    tcm_1b: tcm_1b@ffeb0000 {
        no-map;
        reg = <0x0 0xffeb0000 0x0 0x10000>;
        status = "okay";
        compatible = "mmio-sram";
        power-domain = <&zynqmp_firmware 18>;
    };

    zynqmp-rpu@ff9a0000 {
        compatible = "xlnx,zynqmp-r5-remoteproc";
        xlnx,cluster-mode = <1>;
        ranges;
        reg = <0x0 0xff9a0000 0x0 0x10000>;
        #address-cells = <0x2>;
        #size-cells = <0x2>;
        
        r5_0 {
            compatible = "xilinx,r5f";
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
            sram = <&tcm_0a &tcm_0b>;
            memory-region = <&rproc_0_reserved>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
            power-domain = <&zynqmp_firmware 7>;
        };
        r5_1 {
            compatible = "xilinx,r5f";
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
            sram = <&tcm_1a &tcm_1b>;
            memory-region = <&rproc_1_reserved>, <&rpu1vdev0buffer>, <&rpu1vdev0vring0>, <&rpu1vdev0vring1>;
            power-domain = <&zynqmp_firmware 8>;
        };
    };
    
    zynqmp_ipi1 {
        compatible = "xlnx,zynqmp-ipi-mailbox";
        interrupt-parent = <&gic>;
        interrupts = <0 29 4>;
        xlnx,ipi-id = <7>;
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        ipi_mailbox_rpu0: mailbox@0xff990000 {
            reg = <0x00 0xff990600 0x00 0x20>,
                  <0x00 0xff990620 0x00 0x20>,
                  <0x00 0xff9900c0 0x00 0x20>,
                  <0x00 0xff9900e0 0x00 0x20>;
            reg-names = "local_request_region",
                "local_response_region",
                "remote_request_region",
                "remote_response_region";
            #mbox-cells = <1>;
            xlnx,ipi-id = <1>;
        };
    };

    zynqmp_ipi2 {
        compatible = "xlnx,zynqmp-ipi-mailbox";
        interrupt-parent = <&gic>;
        interrupts = <0 30 4>;
        xlnx,ipi-id = <8>;
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        ipi_mailbox_rpu1: mailbox@ff3f0b00 {
            reg = <0x00 0xff3f0b00 0x00 0x20>,
                  <0x00 0xff3f0b20 0x00 0x20>,
                  <0x00 0xff3f0940 0x00 0x20>,
                  <0x00 0xff3f0960 0x00 0x20>;
            reg-names = "local_request_region",
                    "local_response_region",
                    "remote_request_region",
                    "remote_response_region";
            #mbox-cells = <1>;
            xlnx,ipi-id = <2>;
        };
    };

なお、reserved-memory については既に元の dts に存在する場合があり、その時は既にある中に追記するなどマージしてください。

上記を構築するにあたって、OpenaAMPのWiki や、 UG1186 を参考にさせていただきましたが、これでいいのかどうか正直あまり自信はないです。

また、power-domain の番号についてはこちらのソースコードを参考にしました。

下記のように dtc でコンパイルして、FAT領域にコピーすれば完了です。

dtc -I dts -O dtb system.dts -o user-override.dtb
sudo cp user-override.dtb /boot/firmware/

リブートして /sys/class/remoteproc/ の下にプロセッサが2つ見えていれば成功です。

bootgenを入れる

PLを使うアプリで必要となるので bootgenも入れておきます。

最近のカーネルでは bit ファイルの bootgen での処理は必須でないようなのですが、bootgen 処理しておいた方が、コンフィギュレーション時間が短いなどの事例もあるようです。

git clone https://github.com/Xilinx/bootgen
cd bootgen/
make
sudo cp bootgen /usr/local/bin/

なお openssl/ssl.h が無いと怒られるときは

sudo apt-get install libssl-dev

としてください。

Docker を入れる(お好みで)

公式のUbuntu イメージは比較的簡単にDockerを入れることができるので、今回は環境構築に活用します。

sudo apt install docker.io
sudo apt install docker-compose

下記のように特手ユーザーに権限を付けると sudo が不要になります。

sudo usermod -aG docker <username>

動くかどうか hello-world を試すなどすると良いでしょう。

sudo docker run hello-world

Samba を入れる(お好みで)

必須ではありませんが、Windowsユーザーの場合は入れておくと何かと便利かと思います。

特に Windows から利用する場合は NetBIOS で名前解決ができるようになるので、DHCP で KV260 の IPアドレスが変化するような環境では便利なケースもあります。

sudo apt update
sudo apt install -y samba
sudo nano /etc/samba/smb.conf

として、/etc/samba/smb.conf を編集します。

[home]セクションのコメントアウトをすべて外して、

read only = no

とします。また [global] のセクションに

unix extensions = no
wide links = yes

を足すと、シンボリックリンクの先もアクセスできるようです。

ユーザーを追加は下記のコマンドで行うことができ

sudo pdbedit -a <username>

次のようにして再起動して反映可能です。

sudo systemctl restart smbd nmbd

ROS を入れる(お好みで)

Ubuntu 22.04 には ROS2 humble が入ります。

手順はこちらの通りやれば良いかと思います。

使ってみる

起動時の overlay を解除する(必要な時に実施)

こちらに少し記載していますが、Ubuntu 22.04 では起動時に fpga-region が overlay されて、ファンを制御できる bitstream がダウンロードされるようです。

自分の回路を overlay するときにこのせいでうまく行かない場合は

sudo rmdir /configfs/device-tree/overlays/k26-starter-kits_image_1

とすれば、一時的に overlay が解除できます(ファンは全力で回ってしまい煩くなりますが)。

GitHubで編集を提案

Discussion