Zedboard-PetaLinux2020.2 UARTLITE使用手順

# 概要

[前回](https://qiita.com/junejune/items/6e79365968b2b233d203)はZedboard上でPetaLinuxで生成したOSが立ち上がることまで確認した。

今回はZedBoardで初期状態では使える状態になっていないUARTLITEが使えるようになるまでの一連の手順について確認した。なお、PetaLinuxリファレンスガイドや下記リンクの１つ目の手順通りにやっても全く上手くいかず、試行錯誤しているがあえてそのまま記述する。

なお、本作業は前回行ったZedBoardのセットアップから継続した状態で行っている。

[1] [Zedboard-PetaLinux2020.2 セットアップ](https://qiita.com/junejune/items/6e79365968b2b233d203)

[参考URL]

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842249/Uartlite+Driver

http://embdlog.blogspot.com/2015/07/zynquart2-linux.html

https://forums.xilinx.com/t5/Xilinx-Evaluation-Boards/ZCU102-and-AXI-Uartlite-not-found-under-dev-ttyUL0/td-p/807487

## 1. VIVADOでハードウェア定義ファイルを出力

### 1.1. Verilogソースコードを⽣成

UARTLITEを利用するためのBlock Designはこのように作成した。

![1.1.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/63faf855-35e1-8ae2-9407-a1777137ccd7.png)

UARTLITEのIP2つと割り込み用のxlconcatのIPを用意。
割り込みは`processing_system7`の`IRQ_F2P`につなぐ。

xlconcatはポート２つ

![1.1.3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/81dfa131-65fc-7653-91ad-14dcfa06dd5c.png)

IRQ_F2Pは立ち上がりエッジの設定にしておく。

![1.1.4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/69a95085-99f5-2c3e-4adf-50de52dddd39.png)

Verilogソースコードを⽣成
[BLOCK DESIGN] -> [Sources] -> [Design Sources]
 -> [<project_name>.bd]を右クリック -> Generate Output Products...

+ 初期設定のまま -> [Generate]

### 1.2. HDLファイルを⽣成

[BLOCK DESIGN] -> [Sources] -> [Design Sources]
 -> [<project_name>.bd]を右クリック -> Create HDL Wrapper

+ Let Vivado manage wrapper and auto-update -> [OK]

### 1.3. Bitstreamファイルを⽣成

[Flow Navigator] -> [PROGRAM AND DEBUG] -> [Generate Bitstream]

+ 初期設定のまま -> [OK]

これを実行したところ、下記エラーが出てBitstreamの生成が完了しなかった。

``` log
[Chipscope 16-213] The debug port 'u_ila_0/clk' has 1 unconnected channels (bits). This will cause errors during implementation.
```

どうやらSYNTHESISで上記エラーが発生している様子。

[Flow Navigator] -> [SYNTHESIS] -> [Open Synthesized Design]して開く。
[Flow Navigator] -> [SYNTHESIS] -> [Open Synthesized Design] -> [Schematic]
すると、`u_ila_0`にほとんどつながれていない状態になっていた。

[Tools] -> [Set Up Debug] -> 全部[Next]して[Finish]
これで`u_ila_0`の使われていなかったポートが整理された。

再度、[Flow Navigator] -> [PROGRAM AND DEBUG] -> [Generate Bitstream]

+ 初期設定のまま -> [OK]

今度は無事にBitstreamの生成が完了した。

### 1.4. ハードウェア定義ファイルを⽣成

[File] -> [Export] -> [Export Hardware...] -> [Next]で進める。

+ Output
  + [Include bitstream]を選択 -> [Next]

+ 以降は特にいじらず[Next] -> [Finish]

これで下記パスにハードウェア定義ファイルが生成される
`<vivado_project_folder>/<project_name>_wrapper.xsa`

## 2. Petalinuxのビルド

### 2.1. ハードウェア定義ファイルをインポート

下記PetaLinuxコマンドをPetaLinuxプロジェクト上で実行

``` bash
$ petalinux-config --get-hw-description=<XSAファイルを置いたディレクトリへのパス>
```

Configuration画面でシリアルの設定を確認

[Subsystem AUTO Hardware Settings]

![2.1.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/209a7129-954c-5ebf-8928-14f1761e7f2f.png)

[Serial Settings]

![2.1.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/a3414b79-b666-134a-9c8b-6c79080eac3f.png)

今回追加した`axi_uartlite_0`,`axi_uartlite_1`が確かに追加されている。
しかし、なぜか`ps7_uart_1`のボーレートが`9600`になっているではないか。
（実際は`115200`
に設定している。）
てきとうにUARTLITEのボーレートを`9600`にしたことで引きずられた？

![2.1.3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/1685c4d8-2113-c0dd-9d8b-2d7e7a9e3b53.png)

変更しようと\<Select\>したが、`9600`しか選択肢がない。。。

![2.1.4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/b5c13f0d-a273-ed6f-c3a2-c44aeda88c4d.png)

試しにVIVADOに戻ってUARTLITE 0,1のボーレートを変更してみた。
[BLODK DESIGN] -> [Diagram]の`axi_uartlite_0`をダブルクリック

![2.1.9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/310d73e7-52f2-cdf2-c903-22e273c558a6.png)

[Baud Rate]を`9600` -> `115200`に変更。
`axi_uartlite_1`も同様に。

![2.1.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/3b0479bf-10a1-c457-cdd1-d1a4661bd4d0.png)

ハードウェア定義ファイルの生成までやり直し。

再度、下記PetaLinuxコマンドをPetaLinuxプロジェクト上で実行

``` bash
$ petalinux-config --get-hw-description=<XSAファイルを置いたディレクトリへのパス>
```

`ps7_uart_1`が`115200`に戻った。
UARTLITEのボーレートを変更したのも反映されている。

![2.1.5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/dddf02e3-8f0a-8042-97fc-cc6f09192a4d.png)

また、`Kernel Bootargs`を確認したところ、自動で生成されるシリアルのボーレート設定が`115200`にされていた。

![2.1.8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546326/6cb487ae-eb51-a94a-8f1c-012b0efaf91c.png)

\<Save\>して\<Exit\>で抜ける。

``` bash
INFO: Sourcing build tools
INFO: Getting hardware description...
INFO: Rename UART_IO_wrapper.xsa to system.xsa
[INFO] Generating Kconfig for project
[INFO] Menuconfig project

*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.

[INFO] Sourcing build environment
[INFO] Generating kconfig for Rootfs
[INFO] Silentconfig rootfs
[INFO] Generating plnxtool conf
[INFO] Generating workspace directory
```

正常に終了した。

### 2.2. Kernel Configuration の変更

カーネル設定を変更する。が、エラーが出た。

``` bash
$ petalinux-config -c kernel

(ERROR箇所抜粋)
ERROR: linux-xlnx-5.4+git999-r0 do_menuconfig: No valid terminal found, unable to open devshell.
Tried the following commands:
        tmux split-window -c "{cwd}" "do_terminal"
        tmux new-window -c "{cwd}" -n "linux-xlnx Configuration" "do_terminal"
        xfce4-terminal -T "linux-xlnx Configuration" -e "do_terminal"
        terminology -T="linux-xlnx Configuration" -e do_terminal
        mate-terminal --disable-factory -t "linux-xlnx Configuration" -x do_terminal
        konsole --separate --workdir . -p tabtitle="linux-xlnx Configuration" -e do_terminal
        gnome-terminal -t "linux-xlnx Configuration" -- do_terminal
        xterm -T "linux-xlnx Configuration" -e do_terminal
        rxvt -T "linux-xlnx Configuration" -e do_terminal
        tmux new -c "{cwd}" -d -s devshell -n devshell "do_terminal"
        screen -D -m -t "linux-xlnx Configuration" -S devshell do_terminal
ERROR: Logfile of failure stored in: /workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/build/tmp/work/zynq_generic-xilinx-linux-gnueabi/linux-xlnx/5.4+git999-r0/temp/log.do_menuconfig.28010
ERROR: Task (/workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/components/yocto/layers/meta-xilinx/meta-xilinx-bsp/recipes-kernel/linux/linux-xlnx_2020.2.bb:do_menuconfig) failed with exit code '1'
```

ターミナルがないと怒られる。
同様の前例がないか調べて出てきた下記パッケージをインストール。

``` bash
$ sudo apt-get install screen
```

再度カーネルコンフィグ設定を試すと、今度は開けた。
下記順に進み、`Xilinx uartlite serial port support`をインクルードする。

``` config
Device Drivers ---> Character devices ---> Serial drivers --->
 [*] Xilinx uartlite serial port support
```

### 2.3. ビルド

``` bash
$ petalinux-build
INFO: Sourcing build tools
[INFO] Building project
[INFO] Sourcing build environment
[INFO] Generating workspace directory
INFO: bitbake petalinux-image-minimal
Loading cache: 100% |#################################################################################| Time: 0:00:00
Loaded 4262 entries from dependency cache.
Parsing recipes: 100% |###############################################################################| Time: 0:00:04
Parsing of 2995 .bb files complete (2992 cached, 3 parsed). 4265 targets, 245 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
WARNING: /workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/components/yocto/layers/meta-xilinx/meta-xilinx-bsp/recipes-kernel/linux/linux-xlnx_2020.2.bb:do_compile is tainted from a forced run
Initialising tasks: 100% |############################################################################| Time: 0:00:03
Checking sstate mirror object availability: 100% |####################################################| Time: 0:00:08
Sstate summary: Wanted 135 Found 9 Missed 126 Current 841 (6% match, 87% complete)
NOTE: Executing Tasks
NOTE: Setscene tasks completed
NOTE: u-boot-xlnx: compiling from external source tree /workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/components/yocto/workspace/sources/u-boot-xlnx
NOTE: Tasks Summary: Attempted 3554 tasks of which 3359 didn't need to be rerun and all succeeded.

Summary: There was 1 WARNING message shown.
INFO: copy to TFTP-boot directory is not enabled !!
[INFO] Successfully built project
```

### 2.4. ブートイメージの生成

``` bash
$ petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --u-boot --force
WARNING: Fpga Manager enabled, skipping bitstream to pack into BOOT.BIN
INFO: Sourcing build tools
INFO: File in BOOT BIN: "/workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/images/linux/zynq_fsbl.elf"
INFO: File in BOOT BIN: "/workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/images/linux/u-boot.elf"
INFO: File in BOOT BIN: "/workspace/share/petalinux/project/workspace/avnet-digilent-zedboard-2020.2/images/linux/system.dtb"
INFO: Generating Zynq binary package BOOT.BIN...


****** Xilinx Bootgen v2020.2
  **** Build date : Nov 15 2020-06:11:24
    ** Copyright 1986-2020 Xilinx, Inc. All Rights Reserved.


[INFO]   : Bootimage generated successfully

INFO: Binary is ready.
```

### 2.5. 起動確認

SDカードに下記構成で書き込み。

| パーティション | フォーマット | ファイル |
| -------------- | ------------ | -------- |
| 1              | fat32        | BOOT.BIN |
| 1              | fat32        | image.ub |
| 1              | fat32        | zImage |
| 1              | fat32        | system.dtb |
| 2              | ext4         | rootfs.tar.gzを展開 |

SDをZedBoardに挿入し、電源をON。
Linuxが立ち上がり、ログインしたら下記パスを確認。

``` bash
$ ls /proc/device-tree/amba_pl/
#address-cells   compatible       phandle          serial@42c00000
#size-cells      name             ranges           serial@42c10000
```

２つのUARTLITEに紐付けたserialが確かに追加されている。

またデバイスファイルも確認。

``` bash
$ ls /dev/tty*
/dev/tty        /dev/tty24      /dev/tty40      /dev/tty57
/dev/tty0       /dev/tty25      /dev/tty41      /dev/tty58
/dev/tty1       /dev/tty26      /dev/tty42      /dev/tty59
/dev/tty10      /dev/tty27      /dev/tty43      /dev/tty6
/dev/tty11      /dev/tty28      /dev/tty44      /dev/tty60
/dev/tty12      /dev/tty29      /dev/tty45      /dev/tty61
/dev/tty13      /dev/tty3       /dev/tty46      /dev/tty62
/dev/tty14      /dev/tty30      /dev/tty47      /dev/tty63
/dev/tty15      /dev/tty31      /dev/tty48      /dev/tty7
/dev/tty16      /dev/tty32      /dev/tty49      /dev/tty8
/dev/tty17      /dev/tty33      /dev/tty5       /dev/tty9
/dev/tty18      /dev/tty34      /dev/tty50      /dev/ttyPS0
/dev/tty19      /dev/tty35      /dev/tty51      /dev/ttyUL1
/dev/tty2       /dev/tty36      /dev/tty52      /dev/ttyUL2
/dev/tty20      /dev/tty37      /dev/tty53      /dev/ttyprintk
/dev/tty21      /dev/tty38      /dev/tty54
/dev/tty22      /dev/tty39      /dev/tty55
/dev/tty23      /dev/tty4       /dev/tty56
```

ttyULxが追加されている。
これをシリアルとして使用するにはさらに設定が必要となる。
ここでビルド時に自動生成されるデバイスツリーを確認してみる。
VIVADOで生成したハードウェア定義を反映して下記デバイスツリーが生成される。

`<project_directory>\components\plnx_workspace\device-tree\device-tree\pl.dtsi`

``` dtsi
/*
 * CAUTION: This file is automatically generated by Xilinx.
 * Version:
 * Today is: Wed Mar 10 07:30:17 2021
 */


/dts-v1/;
/plugin/;
/ {
    fragment@0 {
        target = <&fpga_full>;
        overlay0: __overlay__ {
            #address-cells = <2>;
            #size-cells = <2>;
            firmware-name = "UART_IO_wrapper.bit.bin";
        };
    };
    fragment@1 {
        target = <&amba>;
        overlay1: __overlay__ {
            clocking0: clocking0 {
                #clock-cells = <0>;
                assigned-clock-rates = <100000000>;
                assigned-clocks = <&clkc 15>;
                clock-output-names = "fabric_clk";
                clocks = <&clkc 15>;
                compatible = "xlnx,fclk";
            };
        };
    };
    fragment@2 {
        target = <&amba>;
        overlay2: __overlay__ {
            #address-cells = <1>;
            #size-cells = <1>;
            axi_uartlite_0: serial@42c00000 {
                clock-names = "s_axi_aclk";
                clocks = <&clkc 15>;
                compatible = "xlnx,axi-uartlite-2.0", "xlnx,xps-uartlite-1.00.a";
                current-speed = <115200>;
                device_type = "serial";
                interrupt-names = "interrupt";
                interrupt-parent = <&intc>;
                interrupts = <0 29 1>;
                port-number = <1>;
                reg = <0x42c00000 0x10000>;
                xlnx,baudrate = <0x1c200>;
                xlnx,data-bits = <0x8>;
                xlnx,odd-parity = <0x0>;
                xlnx,s-axi-aclk-freq-hz-d = "100.0";
                xlnx,use-parity = <0x0>;
            };
            axi_uartlite_1: serial@42c10000 {
                clock-names = "s_axi_aclk";
                clocks = <&clkc 15>;
                compatible = "xlnx,axi-uartlite-2.0", "xlnx,xps-uartlite-1.00.a";
                current-speed = <115200>;
                device_type = "serial";
                interrupt-names = "interrupt";
                interrupt-parent = <&intc>;
                interrupts = <0 30 1>;
                port-number = <2>;
                reg = <0x42c10000 0x10000>;
                xlnx,baudrate = <0x1c200>;
                xlnx,data-bits = <0x8>;
                xlnx,odd-parity = <0x0>;
                xlnx,s-axi-aclk-freq-hz-d = "100.0";
                xlnx,use-parity = <0x0>;
            };
        };
    };
};

```

上記の`firmware-name`からVIVADOのプロジェクトで生成したビットストリームを元に
このファイルが作られていることが分かる。

UARTLITEの設定は`axi_uartlite_0`と`axi_uartlite_1`に記載されている。
普通にビルドすればこの`pl.dtsi`も反映して最終的なデバイスツリーである
`system.dtb`が生成されるため、逆コンパイルしてみると、

``` bash
$ dtc -I dtb -O dts -o system.dts system.dtb
```

``` dts
(抜粋)
    amba_pl {
        #address-cells = <0x1>;
        #size-cells = <0x1>;
        compatible = "simple-bus";
        ranges;
        phandle = <0x38>;

        serial@42c00000 {
            clock-names = "s_axi_aclk";
            clocks = <0x1 0xf>;
            compatible = "xlnx,axi-uartlite-2.0", "xlnx,xps-uartlite-1.00.a";
            current-speed = <0x1c200>;
            device_type = "serial";
            interrupt-names = "interrupt";
            interrupt-parent = <0x4>;
            interrupts = <0x0 0x1d 0x1>;
            port-number = <0x1>;
            reg = <0x42c00000 0x10000>;
            xlnx,baudrate = <0x1c200>;
            xlnx,data-bits = <0x8>;
            xlnx,odd-parity = <0x0>;
            xlnx,s-axi-aclk-freq-hz-d = "100.0";
            xlnx,use-parity = <0x0>;
            phandle = <0x39>;
        };

        serial@42c10000 {
            clock-names = "s_axi_aclk";
            clocks = <0x1 0xf>;
            compatible = "xlnx,axi-uartlite-2.0", "xlnx,xps-uartlite-1.00.a";
            current-speed = <0x1c200>;
            device_type = "serial";
            interrupt-names = "interrupt";
            interrupt-parent = <0x4>;
            interrupts = <0x0 0x1e 0x1>;
            port-number = <0x2>;
            reg = <0x42c10000 0x10000>;
            xlnx,baudrate = <0x1c200>;
            xlnx,data-bits = <0x8>;
            xlnx,odd-parity = <0x0>;
            xlnx,s-axi-aclk-freq-hz-d = "100.0";
            xlnx,use-parity = <0x0>;
            phandle = <0x3a>;
        };
    };

(抜粋)
    aliases {
        ethernet0 = "/amba/ethernet@e000b000";
        serial0 = "/amba/serial@e0001000";
        serial1 = "/amba_pl/serial@42c00000";
        serial2 = "/amba_pl/serial@42c10000";
        spi0 = "/amba/spi@e000d000";
    };

(抜粋)
    __symbols__ {
        (抜粋)
        axi_uartlite_0 = "/amba_pl/serial@42c00000";
        axi_uartlite_1 = "/amba_pl/serial@42c10000";
    };

```

これを見ると、`status = "okay";`がないため有効となっていないことが分かる。

### 2.6. デバイスツリー変更

デバイスツリーを変更する。ユーザーのカスタム設定は下記ファイルをいじるらしい。

`<project-directory>\project-spec\meta-user\recipes-bsp\device-tree\files\system-user.dtsi`

2つのUARTLITE定義に下記を追加した。

``` dtsi
/include/ "system-conf.dtsi"
/ {
};

&axi_uartlite_0 {
	status = "okay";
};

&axi_uartlite_1 {
	status = "okay";
};
```

ビルドとイメージファイルの生成を再度行う。

``` bash
$ petalinux-build
$ petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/system.bit --u-boot --force
```

### 2.7. 動作確認

SDカードに下記構成で書き込み。

| パーティション | フォーマット | ファイル |
| -------------- | ------------ | -------- |
| 1              | fat32        | BOOT.BIN |
| 1              | fat32        | image.ub |
| 1              | fat32        | zImage |
| 1              | fat32        | system.dtb |
| 2              | ext4         | rootfs.tar.gzを展開 |

SDをZedBoardに挿入し、電源をON。
Linuxが立ち上がり、ログインしたら起動時のログを確認。

``` bash
$ dmesg | grep tty
Kernel command line: console=ttyPS0,115200 root=/dev/mmcblk0p2 rw rootwait uio_pdrv_genirq.of_id=generic-uio
e0001000.serial: ttyPS0 at MMIO 0xe0001000 (irq = 24, base_baud = 3125000) is a xuartps
printk: console [ttyPS0] enabled
42c00000.serial: ttyUL1 at MMIO 0x42c00000 (irq = 46, base_baud = 0) is a uartlite
42c10000.serial: ttyUL2 at MMIO 0x42c10000 (irq = 47, base_baud = 0) is a uartlite
```

UARTLITEの0、1がそれぞれttyUL1、ttyUL2に割り当てられたことが分かる。

今回UARTLITEは0をJA1に、1をJB1を使うようにVIVADOで設定したプロジェクトを使用している。
UARTLITEの動作確認のためUSBシリアルへの変換ケーブルを用意した。
https://www.amazon.co.jp/dp/B00K7YYFNM/

このケーブルのチップセットはPL2303HXとなっており、ドライバをインストールする必要がある。
ドライバのインストール方法はググった。（ここでは省略)

上記ケーブルとオス - オスケーブルでPmodから接続した。
今回PmodはJA1,JB1を受信、JA2,JB2を送信に割り当てているため下記のように接続した。

| ケーブル | 機能 | ZedBoard Pmod接続先 |
| --- | --- | --- |
| 黒 | GND | GND |
| 緑 | TxD | JA1,JA1 |
| 白 | RxD | JA2,JB2 |
| 赤 | USB5V | 接続しない |

結果の確認のためTeraTermを起動、下記のようにシリアルポート設定した。

| 項目 | 設定 |
| --- | --- |
| スピード | 115200 |
| データ | 8 bit |
| パリティ | none |
| ストップビット | 1 bit |
|フロー制御 | none |

ZedBoard側から文字列を送ってみる。

``` bash
$ echo "test" > /dev/ttyUL1
$ echo "test" > /dev/ttyUL2
```

TeraTerm側で`test`という文字列が表示されることが確認できた。
ただし、TeraTermからの入力はできなかった。設定が足りないのかもしれない。

# まとめ

とりあえずVIVADOで生成したハードウェア定義をPetaLinuxで取り込んでZedBoard上で使えることが確認できた。ググるといろいろと情報は出てくるが、2020.2で実施すると手順がそのままではいかず苦労した。