Ryuz's tech blog

FPGAなどの技術ブログ

Kria KV260 の 認定Ubuntu で RPU (Cortex-R5) を認識させる

はじめに

タイトルそのままの内容です。

以前、Ultra96V2のDebianイメージで Cortex-R5 を認識させる - Qiita という記事を書きましたが、その Kria K260 版です。

今回は 認定Ubuntu の iot-kria-classic-desktop-2004-x03-20211110-98.img を使っております。

  • Description: Ubuntu 20.04.4 LTS
  • kernel: 5.4.0-1017-xilinx-zynqmp

DeviceTree を取得する

Twitter で教えていただいた方法ですが、

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

とすると現在のシステムの dts が取得できるようです。

調べてみると このKernel、どんなKernel? - Qiita が詳しいようなので参考にさせていただきました。

DeviceTree を編集する

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

        gic: interrupt-controller@f9010000 {

次に symbols の直前に下記を追記しました。

    reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;
        rproc_0_dma: rproc@0x7ed40000 {
            no-map;
            compatible = "shared-dma-pool";
            reg = <0x0 0x7ed40000 0x0 0x100000>;
        };
        rproc_0_reserved: rproc@0x7ed00000 {
            no-map;
            reg = <0x0 0x7ed00000 0x0 0x40000>;
        };

        rproc_1_dma: rproc@0x7ef00000 {
            no-map;
            compatible = "shared-dma-pool";
            reg = <0x0 0x7ef00000 0x0 0x40000>;
        };
        rproc_1_reserved: rproc@0x7ef40000 {
            no-map;
            reg = <0x0 0x7ef40000 0x0 0x100000>;
        };
    };

    zynqmp-rpu {
        compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;
        core_conf = "split";
        r5_0: r5@0 {
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
            memory-region = <&rproc_0_reserved>, <&rproc_0_dma>;
            pnode-id = <0x7>;
            mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
            mbox-names = "tx", "rx";
            tcm_0_a: tcm_0@0 {
                reg = <0x0 0xFFE00000 0x0 0x10000>;
                pnode-id = <0xf>;
            };
            tcm_0_b: tcm_0@1 {
                reg = <0x0 0xFFE20000 0x0 0x10000>;
                pnode-id = <0x10>;
            };
        };
        r5_1: r5@1 {
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
            memory-region = <&rproc_1_reserved>, <&rproc_1_dma>;
            pnode-id = <0x8>;
            mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
            mbox-names = "tx", "rx";
            tcm_1_a: tcm_1@0 {
                reg = <0x0 0xFFE90000 0x0 0x10000>;
                pnode-id = <0x11>;
            };
            tcm_1_b: tcm_1@1 {
                reg = <0x0 0xFFEB0000 0x0 0x10000>;
                pnode-id = <0x12>;
            };
        };
    };
    
    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;

        // APU<->RPU0 IPI mailbox controller
        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;

        // APU<->RPU0 IPI mailbox controller
        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>;
        };
    };

DeviceTree をコンパイルしてコピーする

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

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

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

ちなみに、これも Twitter で教えていただいたもので

cat /boot/firmware/boot.scr.uimg

とすると、スクリプトが出てきます。

(前略)
                if test -e ${devtype} ${devnum}:${distro_bootpart} /Image; then
                        echo "Loading Image"
                        img_addr=0x00200000
                        load ${devtype} ${devnum}:${distro_bootpart} ${img_addr} Image;
                fi
                if test -e ${devtype} ${devnum}:${distro_bootpart} /system.dtb; then
                        echo "Loading system.dtb"
                        dtb_addr=0x70000000
                        load ${devtype} ${devnum}:${distro_bootpart} ${dtb_addr} system.dtb;
                fi
                if test -e ${devtype} ${devnum}:${distro_bootpart} /rootfs.cpio.gz.u-boot; then
                        echo "Loading rootfs.cpio.gz.u-boot"
                        initrd_addr=0x04000000
                        load ${devtype} ${devnum}:${distro_bootpart} ${initrd_addr} rootfs.cpio.gz.u-boot
                fi
(後略)

のように、ファイルがあれば読み込む記述があり、system.dtb という名前でファイルを置いておけば読み込んでくれることがわかります。

おわりに

今回、GW前に急に KV260 が届いたので、Ultra96 の資産をいろいろと移植中ですが、Twitter 上で多くの方に助けられてなんとか動かせる環境ができてきました。

従来の流れであれば下記を試させて頂くところなのですが、今回、認定Ubuntu もあるということなので可能な限りどちらでも使えるように先に勝手のわからない方から取り組んで、案の定、勝手がわからず苦しんだというお話です。

qiita.com