FC2カウンター FPGAの部屋
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Vitis アクセラレーション・プラットホームを使用して作ったハードウェアを KR260 の Ubuntu 22.04 で動作させる3

Vitis アクセラレーション・プラットホームを使用して作ったハードウェアを KR260 の Ubuntu 22.04 で動作させる2”の続き。

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる7”で動作させたハードウェアとソフトウェアを KR260 の Ubuntu 22.04 で動作させてみたいということで、前回は、ホスト・パソコンの ip_vadd2_file_transfer の内容を KR260 の Ubuntu 22.04 に転送した。ファイルを /lib/firmware/xilinx/kr260_ip_vadd2 ディレクトリにコピーして、kr260_ip_vadd2 をロードしたが、interrupt-controller が uio として実装されなかった。今回は、もう一度、pl.dtsi の interrupt-controller@80000000 の項目を減らして、コンパイルして、KR260 の Petalinux 2022.1 に転送して、kr260_ip_vadd2 をロードしたところ、interrupt-controller が uio に追加された。

KR260/kr260_custom_platform/kr260_custom_platform/dtg/dtg_kr260_ip_vadd/dtg/dtg_kr260_ip_vadd/kr260_custom/psu_cortexa53_0/device_tree_domain/bsp/pl.dtsi の axi_intc_0 セクションを #interrupt-cells と conpatible と reg だけ残して、後はコメントアウトした。なお、 #interrupt-cells を残さないとコンパイル時にエラーになった。
KR260_431_230330.png

pl.dtsi を貼っておく。

/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version: XSCT 2022.1
 * Today is: Sun Mar 19 19:55:06 2023
 */


/dts-v1/;
/plugin/;
/ {
    fragment@0 {
        target = <&fpga_full>;
        overlay0: __overlay__ {
            #address-cells = <2>;
            #size-cells = <2>;
            firmware-name = "kr260_custom.bit.bin";
            resets = <&zynqmp_reset 116>, <&zynqmp_reset 117>, <&zynqmp_reset 118>, <&zynqmp_reset 119>;
        };
    };
    fragment@1 {
        target = <&amba>;
        overlay1: __overlay__ {
            afi0: afi0 {
                compatible = "xlnx,afi-fpga";
                config-afi = < 0 0>, <1 0>, <2 0>, <3 0>, <4 0>, <5 0>, <6 0>, <7 0>, <8 0>, <9 0>, <10 0>, <11 0>, <12 0>, <13 0>, <14 0xa00>, <15 0x000>;
            };
            clocking0: clocking0 {
                #clock-cells = <0>;
                assigned-clock-rates = <99999001>;
                assigned-clocks = <&zynqmp_clk 71>;
                clock-output-names = "fabric_clk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,fclk";
            };
            clocking1: clocking1 {
                #clock-cells = <0>;
                assigned-clock-rates = <99999001>;
                assigned-clocks = <&zynqmp_clk 72>;
                clock-output-names = "fabric_clk";
                clocks = <&zynqmp_clk 72>;
                compatible = "xlnx,fclk";
            };
        };
    };
    fragment@2 {
        target = <&amba>;
        overlay2: __overlay__ {
            #address-cells = <2>;
            #size-cells = <2>;
            DMA_pow2_0: DMA_pow2@80070000 {
                /* This is a place holder node for a custom IP, user may need to update the entries */
                clock-names = "ap_clk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80070000 0x0 0x10000>;
                xlnx,s-axi-control-addr-width = <0x6>;
                xlnx,s-axi-control-data-width = <0x20>;
            };
            PMOD_0: gpio@80010000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80010000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            PMOD_1: gpio@80020000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80020000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            PMOD_2: gpio@80030000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80030000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            PMOD_3: gpio@80040000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80040000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            axi_dma_0: dma@80050000 {
                #dma-cells = <1>;
                clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
                clocks = <&zynqmp_clk 71>, <&zynqmp_clk 71>, <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80050000 0x0 0x10000>;
                xlnx,addrwidth = <0x20>;
                xlnx,sg-length-width = <0xe>;
                dma-channel@80050000 {
                    compatible = "xlnx,axi-dma-mm2s-channel";
                    dma-channels = <0x1>;
                    xlnx,datawidth = <0x20>;
                    xlnx,device-id = <0x0>;
                };
                dma-channel@80050030 {
                    compatible = "xlnx,axi-dma-s2mm-channel";
                    dma-channels = <0x1>;
                    xlnx,datawidth = <0x20>;
                    xlnx,device-id = <0x0>;
                };
            };
            axi_intc_0: interrupt-controller@80000000 {
                #interrupt-cells = <2>;
                /*clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>; */
                compatible = "generic-uio";
                /*interrupt-controller ;
                interrupt-names = "irq";
                interrupt-parent = <&gic>;
                interrupts = <0 89 4>; */
                reg = <0x0 0x80000000 0x0 0x10000>;
                /*xlnx,kind-of-intr = <0xfffffffd>;
                xlnx,num-intr-inputs = <0x20>; */
            };
            axi_timer_0: timer@80060000 {
                clock-frequency = <99999001>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80060000 0x0 0x10000>;
                xlnx,count-width = <0x20>;
                xlnx,gen0-assert = <0x1>;
                xlnx,gen1-assert = <0x1>;
                xlnx,one-timer-only = <0x0>;
                xlnx,trig0-assert = <0x1>;
                xlnx,trig1-assert = <0x1>;
            };
            krnl_vadd_1: krnl_vadd@b0000000 {
                /* This is a place holder node for a custom IP, user may need to update the entries */
                /*clock-names = "ap_clk";
                clocks = <&misc_clk_0>; */
                compatible = "generic-uio";
                /*interrupt-names = "interrupt";
                interrupt-parent = <&axi_intc_0>;
                interrupts = <1 2>;*/
                reg = <0x0 0xb0000000 0x0 0x10000>;
                /*xlnx,s-axi-control-addr-width = <0x6>;
                xlnx,s-axi-control-data-width = <0x20>;*/
            };
            misc_clk_0: misc_clk_0 {
                #clock-cells = <0>;
                clock-frequency = <199998000>;
                compatible = "fixed-clock";
            };
            multi_axi4ls_0: multi_axi4ls@80080000 {
                /* This is a place holder node for a custom IP, user may need to update the entries */
                clock-names = "ap_clk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80080000 0x0 0x10000>;
                xlnx,s-axi-control-addr-width = <0x6>;
                xlnx,s-axi-control-data-width = <0x20>;
            };
            zyxclmm_drm {
                compatible = "xlnx,zocl";
                interrupts-extended = <&axi_intc_0 0 4>, <&axi_intc_0 1 4>, <&axi_intc_0 2 4>, <&axi_intc_0 3 4>, <&axi_intc_0 4 4>, <&axi_intc_0 5 4>, <&axi_intc_0 6 4>, <&axi_intc_0 7 4>, <&axi_intc_0 8 4>, <&axi_intc_0 9 4>,
<&axi_intc_0 10 4>, <&axi_intc_0 11 4>, <&axi_intc_0 12 4>, <&axi_intc_0 13 4>, <&axi_intc_0 14 4>,
<&axi_intc_0 15 4>, <&axi_intc_0 16 4>, <&axi_intc_0 17 4>, <&axi_intc_0 18 4>, <&axi_intc_0 19 4>,
<&axi_intc_0 20 4>, <&axi_intc_0 21 4>, <&axi_intc_0 22 4>, <&axi_intc_0 23 4>, <&axi_intc_0 24 4>,
<&axi_intc_0 25 4>, <&axi_intc_0 26 4>, <&axi_intc_0 27 4>, <&axi_intc_0 28 4>, <&axi_intc_0 29 4>,
<&axi_intc_0 30 4>, <&axi_intc_0 31 4 >;
            };
        };
    };
};


変更した pl.dtsi をコンパイルして pl.dtbo を生成した。
dtc -@ -O dtb -o ./dtg/dtg_kr260_ip_vadd/dtg/dtg_kr260_ip_vadd/kr260_custom/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo ./dtg/dtg_kr260_ip_vadd/dtg/dtg_kr260_ip_vadd/kr260_custom/psu_cortexa53_0/device_tree_domain/bsp/pl.dtsi
KR260_432_230330.png

KR260_433_230330.png

pl.dtbo を ip_vadd2_file_transfer ディレクトリにコピーした。
ip_vadd2_file_transfer ディレクトリの pl.dtbo を FileZilla で KR260 の Petalinux の ~/kr260_ip_vadd2 に転送した。
KR260_434_230330.png

pl.dtbo を /lib/firmware/xilinx/kr260_ip_vadd2 ディレクトリにコピーした。(binary_container_1.bin shell.json はすでにコピー済み)
sudo cp pl.dtbo /lib/firmware/xilinx//kr260_ip_vadd2

現在、ロードされているアクセラレーション・アプリケーションをアンロードして、kr260_ip_vadd2 をロードした。
sudo xmutil unloadapp
sudo xmutil loadapp kr260_ip_vadd2

KR260_435_230330.png

KR260 Petalinux の /sys/class/uio を見ると uio0 〜 uio10 までが見える。これは interrupt-controller もマップできたようだ。
KR260_436_230330.png

ロードされた uio を示す。

uio5 - DMA_pow2
uio6 - dma
uio7 - interrupt-controller
uio8 - timer
uio9 - krnl_vadd
uio10 - multi_axi4ls

  1. 2023年03月31日 04:43 |
  2. KR260
  3. | トラックバック:0
  4. | コメント:0

Vitis アクセラレーション・プラットホームを使用して作ったハードウェアを KR260 の Ubuntu 22.04 で動作させる2

Vitis アクセラレーション・プラットホームを使用して作ったハードウェアを KR260 の Ubuntu 22.04 で動作させる1”の続き。

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる7”で動作させたハードウェアとソフトウェアを KR260 の Ubuntu 22.04 で動作させてみたいということで、前回は、xmutil コマンドの動作を確認し、u-dma-buf.ko を生成した。今回は、ホスト・パソコンの ip_vadd2_file_transfer の内容を KR260 の Ubuntu 22.04 に転送した。ファイルを /lib/firmware/xilinx/kr260_ip_vadd2 ディレクトリにコピーして、kr260_ip_vadd2 をロードしたが、interrupt-controller が uio として実装されなかった。

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる3”で作成した KR260/kr260_custom_platform/kr260_custom_platform/ip_vadd2_file_transfer ディレクトリの内容を KR260 の Ubuntu 22.04 に作成した ~/examples/kr260_ip_vadd2 ディレクトリに転送する。
まずは、KR260 の Ubuntu 22.04 に ~/examples/kr260_ip_vadd2 ディレクトリを作成する。
mkdir examples
cd examples/
mkdir kr260_ip_vadd2
cd kr260_ip_vadd2/


ホストパソコンの KR260/kr260_custom_platform/kr260_custom_platform/ip_vadd2_file_transfer ディレクトリの pl.dtbo, binary_container_1.xclbin, shell.json を KR260 の Ubuntu 22.04 に作成した ~/examples/kr260_ip_vadd2 ディレクトリに FileZilla で転送した。
KR260_427_230330.png

ここからは、KR260 の Ubuntu 22.04 の ~/examples/kr260_ip_vadd2 ディレクトリでの作業となる。
/lib/firmware/xilinx/kr260_ip_vadd2 ディレクトリを作成した。
sudo mkdir /lib/firmware/xilinx/kr260_ip_vadd2

binary_container_1.xclbin の名前を binary_container_1.bin に変更する。こうしないと、XRT は FPGA ビットストリームを抽出して Kria のプログラマブル ロジックをコンフィグレーションすることができないそうだ。
mv binary_container_1.xclbin binary_container_1.bin

pl.dtbo binary_container_1.bin shell.json ファイルを /lib/firmware/xilinx/kr260_ip_vadd2 ディレクトリにコピーした。
sudo cp pl.dtbo binary_container_1.bin shell.json /lib/firmware/xilinx//kr260_ip_vadd2

現在、ロードされているアクセラレーション・アプリケーションをアンロードして、kr260_ip_vadd2 をロードする。
sudo xmutil unloadapp
sudo xmutil loadapp kr260_ip_vadd2

KR260_428_230330.png

kr260_ip_vadd2 をロードした時のターミナルの様子を示す。
KR260_429_230330.png

ターミナル表示のログを示す。

[  567.076186] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /fpga-full/firmware-name
[  567.086337] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /fpga-full/resets
[  567.096574] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/overlay0
[  567.106445] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/overlay1
[  567.116297] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/afi0
[  567.125799] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/clocking0
[  567.135734] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/clocking1
[  567.145698] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/overlay2
[  567.155578] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/DMA_pow2_0
[  567.165601] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/PMOD_0
[  567.175276] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/PMOD_1
[  567.184990] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/PMOD_2
[  567.194666] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/PMOD_3
[  567.204338] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/axi_dma_0
[  567.214267] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/axi_intc_0
[  567.224283] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/axi_timer_0
[  567.234387] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/krnl_vadd_1
[  567.244518] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/misc_clk_0
[  567.254540] OF: overlay: WARNING: memory leak will occur if overlay removed, property: /__symbols__/multi_axi4ls_0
[  567.345548] genirq: Flags mismatch irq 64. 00000004 (interrupt-controller) vs. 00000004 (fabric)
[  567.357125] uio_pdrv_genirq 80000000.interrupt-controller: unable to register uio device


/sys/class/uio を示す。
KR260_430_230330.png

uio0 〜 uio9 まで実装されていが、uio4 の下の name ファイルを読むと fabric と買いてあった。これは、こちらで実装した uio ではない。
その後の uio5 〜 uio9 までの name ファイルを読んだ。

uio5 - DMA_pow2
uio6 - dma
uio7 - timer
uio8 - krnl_vadd
uio9 - multi_axi4ls


という訳で、interrupt-controller が uio として実装されなかった。
  1. 2023年03月30日 04:28 |
  2. KR260
  3. | トラックバック:0
  4. | コメント:0

ZYBO Z7-20 の Debian Linux で MicroBlaze プロセッサを使用する際に MicroBlaze が動作しない時がある

ZYBO Z7-20 の Debian Linux で MicroBlaze プロセッサを使用する”で、ハードコアの ARM Cortex-A9 と MicroBlaze プロセッサが連携で動作するハードウェアで ikwzm さんの Debian Linux 上で、dtbocfg.rb でハードウェアをロードしたときに MicroBlaze プロセッサが動作するのを確認できた。その際には、MicroBlaze プロセッサのアプリケーション・ソフトウェアは Vivado の Tools メニューから Associate ELF Files... を選択して elf ファイルを Block RAM の初期化データとして埋め込んである。

だが、条件は確定できていないが、MicroBlaze プロセッサが起動していない場合がある。それは、他のブロック・デザインから IP や階層モジュールをコピー & ペーストしたときに多い気がする。
ブロック・デザインを 1 から構築したときは、大丈夫だったし、そこで、そのブロック・デザインで階層モジュールをコピー & ペーストしたときは、大丈夫だった。
いずれにせよ。MicroBlaze プロセッサが動作するかどうか?を検証できる回路を埋め込んでおいた方が良いと思う。
なお、使用してるボードは ZYBO Z7-20 だ。使用している Vivado のバージョンは 2022.2 だ。
  1. 2023年03月29日 20:13 |
  2. FPGAを使用したシステム
  3. | トラックバック:0
  4. | コメント:0

Vitis アクセラレーション・プラットホームを使用して作ったハードウェアを KR260 の Ubuntu 22.04 で動作させる1

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる7”で動作させたハードウェアとソフトウェアを KR260 の Ubuntu 22.04 で動作させて見ようと思う。つまり、今までは、KR260 の Petalinux 2022.1 で動作させていたハードウェアとソフトウェアを Ubuntu 22.04 で動作させてみたい。

KR260 の Ubuntu 22.04 は”再度 KR260 で Ubuntu 22.04 LTS を起動した”で使用した MicroSD カードを使用して、KR260 をブートした。

KR260 で Ubuntu 22.04 LTS を起動した。
KR260_425_230328.png
KR260_426_230328.png

xmutil コマンドの動作を確認してみよう。
/lib/firmware/xilinx ディレクトリには、k26-starter-kits ディレクトリがあって、その中に、k26_starter_kits.bit.bin と k26_starter_kits.dtbo, shell.json ファイルが入っている。
KR260_421_230328.png

これを xmutil コマンドロードできるはず。
sudo xmutil unloadapp
sudo xmutil loadapp k26-starter-kits

k26-starter-kits をロードすることができた。
KR260_422_230328.png

次は、u-dma-buf.ko を用意する必要がある。
KR260 の Ubuntu 22.04 上で ikwzm/udmabuf から git clone する。
git clone https://github.com/ikwzm/udmabuf.git

udmabuf ディレクトリに入って、make all した。
cd udmabuf/
make all

KR260_423_230328.png

u-dma-buf.ko が生成された。
ls -l
KR260_424_230328.png
  1. 2023年03月29日 04:21 |
  2. KR260
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新(2023年3月28日)

FPGAの部屋のまとめサイトを更新しました。
2023 年 3 月 27 日までの記事をまとめました。
  1. 2023年03月28日 04:29 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる7

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる6”の続き。

Vitis アクセラレーション・プラットホームを使用してハードウェアを完成させ、それを自作アプリケーション・ソフトウェアで動作させてみたいということで、前回は、pl.dtsi の krnl_vadd セクションを最小限にして、コンパイルし、Petalinux に転送して、ロードしたところ、krnl_vadd が uio8 として実装できた。今回は、uio ドライバを使用して、multi_axi4ls IP と DMA_pow2 IP、krnl_vadd IP を使用するアプリケーション・ソフトウェアを作成し、動作を確認した。

KR260 の Petalinux 2022.1 の ~/kr260_ip_vadd2 ディレクトリに アプリケーション・ソフトウェアの kr260_ip_vadd2.c を作成した。
KR260_419_230326.png

KR260_420_230326.png

kr260_ip_vadd2.c のコードを示す。

// kr260_ip_vadd2.c
// 2023/03/26 by marsee

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>

int32_t multi_calc(int32_t *multi_axi4ls, int32_t a, int32_t b){
    while((multi_axi4ls[0] &4) == 0) ; // wait ap_idle
    multi_axi4ls[6] = a; // reg a, 0x18
    multi_axi4ls[8] = b; // reg b, 0x20
    multi_axi4ls[0] = 1; // ap_start = 1
    while((multi_axi4ls[11] & 1) == 0) ; // wait c_ap_vld
    return(multi_axi4ls[10]);
}

void main(){
    int uio9_fd;
    int32_t *multi_axi4ls;
    int32_t a, b, c;
    int uio4_fd;
    volatile int32_t *dma_pow2;
    volatile int32_t *data;
    int fd_udmabuf0;
    u_int32_t fd_paddr;
    unsigned long  phys_addr;
    int uio8_fd;
    int32_t *krnl_vadd;
    unsigned char  attr[1024];

    // uio9, multi_axi4ls IP
    if((uio9_fd = open("/dev/uio9", O_RDWR)) == -1) {
        printf("Can not open /dev/uio9\n");
        exit(1);
    }
    multi_axi4ls = (uint32_t*)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, uio9_fd, 0);
    
    printf("multi_axi4ls\n");
    for(a = 0, b = 1; a < 10; a++, b++){
        c = multi_calc(multi_axi4ls, a, b);
        printf("a = %d, b = %d, c = %d\n", a, b, c);
    }

    // uio4, DMP_pow2 IP
    if((uio4_fd = open("/dev/uio4", O_RDWR)) == -1) {
        printf("Can not open /dev/uio4\n");
        exit(1);
    }
    dma_pow2 = (volatile int32_t*)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, uio4_fd, 0);
    
    // udmabuf0
    fd_udmabuf0 = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The chache is disabled. 
    if (fd_udmabuf0 == -1){
        fprintf(stderr, "/dev/udmabuf0 open errorn");
        exit(-1);
    }

    // phys_addr of udmabuf0
    fd_paddr = open("/sys/class/u-dma-buf/udmabuf0/phys_addr", O_RDONLY);
    if (fd_paddr == -1){
        fprintf(stderr, "/sys/class/u-dma-buf/udmabuf0/phys_addr open errorn");
        exit(-1);
    }
    read(fd_paddr, (void *)attr, 1024);
    sscanf((const char *)attr, "%lx", &phys_addr);  
    close(fd_paddr);
    printf("phys_addr = %x\n", (unsigned int)phys_addr);
  
    data = (volatile int32_t *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd_udmabuf0, 0);
    if (data == MAP_FAILED){
        fprintf(stderr, "data mmap error\n");
        exit(-1);
    }

    // data Initialization
    for(int i=0; i<10; i++){
        data[i] = i;
    }
    
    // DMA_pow2 start
    while((dma_pow2[0] & 4) == 0) ; // wait ap_idle
    dma_pow2[6] = phys_addr; // in_r
    dma_pow2[8] = phys_addr + 10 * sizeof(int32_t);
    dma_pow2[0] = 1; // ap_start
    while((dma_pow2[0] & 2) == 0) ; // wait ap_done
    
    printf("\n DMA_pow2\n");
    for(int i=0; i<10; i++){
        printf("in = %d, out = %d\n", data[i], data[i+10]);
    }

    // uio8, krnl_vadd IP
    if((uio8_fd = open("/dev/uio8", O_RDWR)) == -1) {
        printf("Can not open /dev/uio8\n");
        exit(1);
    }
    krnl_vadd = (uint32_t*)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, uio8_fd, 0);

    for(int i=0; i<10; i++){
        data[i+20] = i;
        data[i+30] = i+1;
    }

    // krnl_vadd start
    while((krnl_vadd[0] & 4) == 0) ; // wait ap_idle
    krnl_vadd[4] = (uint32_t)((phys_addr + 20 * sizeof(int32_t))&0xffffffff); // in1
    krnl_vadd[5] = (uint32_t)(((phys_addr + 20 * sizeof(int32_t))&0xffffffff00000000)>>32); // in1
    krnl_vadd[7] = (uint32_t)((phys_addr + 30 * sizeof(int32_t))&0xffffffff); // in2
    krnl_vadd[8] = (uint32_t)(((phys_addr + 30 * sizeof(int32_t))&0xffffffff00000000)>>32); // in2
    krnl_vadd[10] = (uint32_t)((phys_addr + 40 * sizeof(int32_t))&0xffffffff); // out_r
    krnl_vadd[11] = (uint32_t)(((phys_addr + 30 * sizeof(int32_t))&0xffffffff00000000)>>32); // out_r
    krnl_vadd[13] = 10; // size
    krnl_vadd[0] = 1; // ap_start
    while((krnl_vadd[0] & 2) == 0) ; // wait ap_done
   
    printf("\nkrnl_vadd\n");
    for(int i=0; i<10; i++){
       printf("in1 = %d, in2 = %d, out_r = %d\n", data[i+20], data[i+30], data[i+40]);
    }
}


kr260_ip_vadd2.c をコンパイルした。
kr260_ip_vadd 実行ファイルが生成された。
gcc -o kr260_ip_vadd2 kr260_ip_vadd2.c
ログを示す。

xilinx-kr260-starterkit-20221:~/kr260_ip_vadd2$ gcc -o kr260_ip_vadd2 kr260_ip_vadd2.c
kr260_ip_vadd2.c: In function 'main':
kr260_ip_vadd2.c:66:5: warning: implicit declaration of function 'read'; did you mean 'fread'? [-Wimplicit-function-declaration]
   66 |     read(fd_paddr, (void *)attr, 1024);
      |     ^~~~
      |     fread
kr260_ip_vadd2.c:68:5: warning: implicit declaration of function 'close'; did you mean 'pclose'? [-Wimplicit-function-declaration]
   68 |     close(fd_paddr);
      |     ^~~~~
      |     pclose


u-dma-buf.ko をロードし、kr260_ip_vadd2 ディレクトリに移動する。
現在、ロードされているアクセラレーション・アプリケーションをアンロードして、kr260_ip_vadd をロードする。
/dev/uio* と /dev/udmabuf0 をユーザー書き込み可能モードにした。
kr260_ip_vadd を動作させたところ成功した。
cd
sudo insmod u-dma-buf.ko udmabuf0=0x10000
cd kr260_ip_vadd2
sudo xmutil unloadapp
sudo xmutil loadapp kr260_ip_vadd2
sudo chmod 666 /dev/uio*
sudo chmod 666 /dev/udmabuf0
./kr260_ip_vadd2

KR260_417_230326.png

KR260_418_230326.png

これで、Vitis アクセラレーション・プラットホームを使用してハードウェアを完成させ、それを自作アプリケーション・ソフトウェアで動作させることができた。
空のホスト・アプリケーション・ソフトウェアとアクセラレーション・カーネルの krnl_vadd を使って、ハードウェアを完成させて、ハードウェア・プラットホーム上の multi_axi4ls IP と DMA_pow2 IP を動作させながら krnl_vadd も自作アプリケーション・ソフトウェアで動作させることができた。
  1. 2023年03月27日 04:11 |
  2. KR260
  3. | トラックバック:0
  4. | コメント:0

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる6

Vitis アクセラレーション・プラットホームを使用してハードウェアを作り、それを自作アプリケーション・ソフトウェアで動作させる5”の続き。

Vitis アクセラレーション・プラットホームを使用してハードウェアを完成させ、それを自作アプリケーション・ソフトウェアで動作させてみたいということで、前回は、ロードされているアクセラレーション・アプリケーションをアンロードして、kr260_ip_vadd2 をロードしたが、やはり、Vitis で生成された krnl_vadd IP は uio として生成されなかった。今回は、pl.dtsi の krnl_vadd セクションを最小限にして、コンパイルし、Petalinux に転送して、ロードしたところ、krnl_vadd が uio8 として実装できた。

前回、UIO ドライバを増やしたが、これでダメだとすると、pl.dtsi の記述を最小限にしてみたらどうだろうか?ということで、conpatible と reg だけにして試してみよう。

KR260/kr260_custom_platform/kr260_custom_platform/dtg/dtg_kr260_ip_vadd/dtg/dtg_kr260_ip_vadd/kr260_custom/psu_cortexa53_0/device_tree_domain/bsp/pl.dtsi の krnl_vadd セクションを conpatible と reg だけ残して、後はコメントアウトした。
(注)krnl_vadd セクションをいろいろとコメントアウトして、試したが、compatible と reg だけ残した時のみ uio にマップされるようだった。
KR260_412_230325.png

現在の pl.dtsi を示す。

/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version: XSCT 2022.1
 * Today is: Sun Mar 19 19:55:06 2023
 */


/dts-v1/;
/plugin/;
/ {
    fragment@0 {
        target = <&fpga_full>;
        overlay0: __overlay__ {
            #address-cells = <2>;
            #size-cells = <2>;
            firmware-name = "kr260_custom.bit.bin";
            resets = <&zynqmp_reset 116>, <&zynqmp_reset 117>, <&zynqmp_reset 118>, <&zynqmp_reset 119>;
        };
    };
    fragment@1 {
        target = <&amba>;
        overlay1: __overlay__ {
            afi0: afi0 {
                compatible = "xlnx,afi-fpga";
                config-afi = < 0 0>, <1 0>, <2 0>, <3 0>, <4 0>, <5 0>, <6 0>, <7 0>, <8 0>, <9 0>, <10 0>, <11 0>, <12 0>, <13 0>, <14 0xa00>, <15 0x000>;
            };
            clocking0: clocking0 {
                #clock-cells = <0>;
                assigned-clock-rates = <99999001>;
                assigned-clocks = <&zynqmp_clk 71>;
                clock-output-names = "fabric_clk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,fclk";
            };
            clocking1: clocking1 {
                #clock-cells = <0>;
                assigned-clock-rates = <99999001>;
                assigned-clocks = <&zynqmp_clk 72>;
                clock-output-names = "fabric_clk";
                clocks = <&zynqmp_clk 72>;
                compatible = "xlnx,fclk";
            };
        };
    };
    fragment@2 {
        target = <&amba>;
        overlay2: __overlay__ {
            #address-cells = <2>;
            #size-cells = <2>;
            DMA_pow2_0: DMA_pow2@80070000 {
                /* This is a place holder node for a custom IP, user may need to update the entries */
                clock-names = "ap_clk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80070000 0x0 0x10000>;
                xlnx,s-axi-control-addr-width = <0x6>;
                xlnx,s-axi-control-data-width = <0x20>;
            };
            PMOD_0: gpio@80010000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80010000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            PMOD_1: gpio@80020000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80020000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            PMOD_2: gpio@80030000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80030000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            PMOD_3: gpio@80040000 {
                #gpio-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a";
                gpio-controller ;
                reg = <0x0 0x80040000 0x0 0x10000>;
                xlnx,all-inputs = <0x0>;
                xlnx,all-inputs-2 = <0x0>;
                xlnx,all-outputs = <0x0>;
                xlnx,all-outputs-2 = <0x0>;
                xlnx,dout-default = <0x00000000>;
                xlnx,dout-default-2 = <0x00000000>;
                xlnx,gpio-width = <0x8>;
                xlnx,gpio2-width = <0x20>;
                xlnx,interrupt-present = <0x0>;
                xlnx,is-dual = <0x0>;
                xlnx,tri-default = <0xFFFFFFFF>;
                xlnx,tri-default-2 = <0xFFFFFFFF>;
            };
            axi_dma_0: dma@80050000 {
                #dma-cells = <1>;
                clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk", "m_axi_s2mm_aclk";
                clocks = <&zynqmp_clk 71>, <&zynqmp_clk 71>, <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80050000 0x0 0x10000>;
                xlnx,addrwidth = <0x20>;
                xlnx,sg-length-width = <0xe>;
                dma-channel@80050000 {
                    compatible = "xlnx,axi-dma-mm2s-channel";
                    dma-channels = <0x1>;
                    xlnx,datawidth = <0x20>;
                    xlnx,device-id = <0x0>;
                };
                dma-channel@80050030 {
                    compatible = "xlnx,axi-dma-s2mm-channel";
                    dma-channels = <0x1>;
                    xlnx,datawidth = <0x20>;
                    xlnx,device-id = <0x0>;
                };
            };
            axi_intc_0: interrupt-controller@80000000 {
                #interrupt-cells = <2>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                interrupt-controller ;
                interrupt-names = "irq";
                interrupt-parent = <&gic>;
                interrupts = <0 89 4>;
                reg = <0x0 0x80000000 0x0 0x10000>;
                xlnx,kind-of-intr = <0xfffffffd>;
                xlnx,num-intr-inputs = <0x20>;
            };
            axi_timer_0: timer@80060000 {
                clock-frequency = <99999001>;
                clock-names = "s_axi_aclk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80060000 0x0 0x10000>;
                xlnx,count-width = <0x20>;
                xlnx,gen0-assert = <0x1>;
                xlnx,gen1-assert = <0x1>;
                xlnx,one-timer-only = <0x0>;
                xlnx,trig0-assert = <0x1>;
                xlnx,trig1-assert = <0x1>;
            };
            krnl_vadd_1: krnl_vadd@b0000000 {
                /* This is a place holder node for a custom IP, user may need to update the entries */
                /*clock-names = "ap_clk";
                clocks = <&misc_clk_0>; */
                compatible = "generic-uio";
                /*interrupt-names = "interrupt";
                interrupt-parent = <&axi_intc_0>;
                interrupts = <1 2>;*/
                reg = <0x0 0xb0000000 0x0 0x10000>;
                /*xlnx,s-axi-control-addr-width = <0x6>;
                xlnx,s-axi-control-data-width = <0x20>;*/
            };
            misc_clk_0: misc_clk_0 {
                #clock-cells = <0>;
                clock-frequency = <199998000>;
                compatible = "fixed-clock";
            };
            multi_axi4ls_0: multi_axi4ls@80080000 {
                /* This is a place holder node for a custom IP, user may need to update the entries */
                clock-names = "ap_clk";
                clocks = <&zynqmp_clk 71>;
                compatible = "generic-uio";
                reg = <0x0 0x80080000 0x0 0x10000>;
                xlnx,s-axi-control-addr-width = <0x6>;
                xlnx,s-axi-control-data-width = <0x20>;
            };
            zyxclmm_drm {
                compatible = "xlnx,zocl";
                interrupts-extended = <&axi_intc_0 0 4>, <&axi_intc_0 1 4>, <&axi_intc_0 2 4>, <&axi_intc_0 3 4>, <&axi_intc_0 4 4>, <&axi_intc_0 5 4>, <&axi_intc_0 6 4>, <&axi_intc_0 7 4>, <&axi_intc_0 8 4>, <&axi_intc_0 9 4>,
<&axi_intc_0 10 4>, <&axi_intc_0 11 4>, <&axi_intc_0 12 4>, <&axi_intc_0 13 4>, <&axi_intc_0 14 4>,
<&axi_intc_0 15 4>, <&axi_intc_0 16 4>, <&axi_intc_0 17 4>, <&axi_intc_0 18 4>, <&axi_intc_0 19 4>,
<&axi_intc_0 20 4>, <&axi_intc_0 21 4>, <&axi_intc_0 22 4>, <&axi_intc_0 23 4>, <&axi_intc_0 24 4>,
<&axi_intc_0 25 4>, <&axi_intc_0 26 4>, <&axi_intc_0 27 4>, <&axi_intc_0 28 4>, <&axi_intc_0 29 4>,
<&axi_intc_0 30 4>, <&axi_intc_0 31 4 >;
            };
        };
    };
};


変更した pl.dtsi をコンパイルして pl.dtbo を生成する。
dtc -@ -O dtb -o ./dtg/dtg_kr260_ip_vadd/dtg/dtg_kr260_ip_vadd/kr260_custom/psu_cortexa53_0/device_tree_domain/bsp/pl.dtbo ./dtg/dtg_kr260_ip_vadd/dtg/dtg_kr260_ip_vadd/kr260_custom/psu_cortexa53_0/device_tree_domain/bsp/pl.dtsi
KR260_413_230325.png

pl.dtbo を ip_vadd2_file_transfer ディレクトリにコピーした。
ip_vadd2_file_transfer ディレクトリの pl.dtbo を FileZilla で KR260 の Petalinux の ~/kr260_ip_vadd2 に転送した。

pl.dtbo を /lib/firmware/xilinx/kr260_ip_vadd2 ディレクトリにコピーした。(binary_container_1.bin shell.json はすでにコピー済み)
sudo cp pl.dtbo /lib/firmware/xilinx//kr260_ip_vadd2

現在、ロードされているアクセラレーション・アプリケーションをアンロードして、kr260_ip_vadd2 をロードする。
sudo xmutil unloadapp
sudo xmutil loadapp kr260_ip_vadd2

KR260_414_230325.png

KR260 Petalinux の /sys/class/uio を見ると uio0 〜 uio9 までが見える。これは krnl_vadd もマップできたようだ。
KR260_415_230325.png

krnl_vadd は uio8 にマップされていた。
KR260_416_230325.png

ロードされた uio を示す。

uio4 - DMA_pow2
uio5 - dma
uio6 - interrupt-controller
uio7 - timer
uio8 - krnl_vadd
uio9 - multi_axi4ls


これで、アクセラレーション・カーネルの krnl_vadd も uio にマップできたので、先に進める。
  1. 2023年03月26日 05:27 |
  2. KR260
  3. | トラックバック:0
  4. | コメント:0
»