KR260のPetaLinuxでLチカ

# はじめに

最近KR260用PetaLinuxのビルドと起動を初めて行ったのですが、**「思ってたのとなんか違う」** 状況になりました。今まで`petalinux-config`で組み込んでいた自前のロジックがうまく組み込めません。

そんな経験からPetaLinuxへの正しい組み込み方を模索した結果を記述します。

# 目的
本記事では自分で作成したBitstreamを適用した環境で、sysfsを利用したLED制御を実現します。

# 開発環境
**Board**
&emsp;Kria KR260 Robotics Starter Kit
**Tools**
&emsp;Vitis 2024.2
&emsp;Vivado 2024.2
&emsp;PetaLinux 2024.2
**PetaLinux BSP**
&emsp;xilinx-kr260-starterkit-v2024.2-12072024.bsp
**Host OS**
&emsp;Ubuntu 24.04 Desktop

:::note info
今回の作業でVitisは使いませんが、System Device Treeを生成する際にVitisに含まれるデータを参照する為、Vitisのインストールが必要です。
:::

:::note info
巷に存在するKria関連のHowToでは、Vitisで機能拡張する為にPlatform用のBlock Designを追加する記述があります。本記事では拡張性は無視しており、Platform関連の実装は行わず、GPIOのみを実装しています。
:::

## 環境設定
作業はVivadoとPetaLinuxで行います。


# Vivado作業手順
## Project作成
Vivadoを起動して適当な所にプロジェクトを作成して下さい。Kria SOMsはプロジェクト作成時に一手間あります。Boardの選択画面で**Vendor**と**Name**を選択して、KR260が表示されたら赤丸で囲ってある**Connections**をクリックします。

![Board選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/b816f854-c190-4e39-9ca2-66b7028b4ba8.png)

ウィンドウが開いたら、各Connectorを下記の様に選択して **[OK]** をクリックします。

![Connector選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/df846117-fa2b-414b-bdee-f6378cd7ebc9.png)

Board選択画面に戻ったら **[Next]** , **[Finish]** の順にクリックしてプロジェクトを作成します。

プロジェクトが作成されたら、メニューバーから **[Tools]** -> **[Settings...]** を選択します。ウィンドウが開いたら **Project Settings** 内の **Bitstream** をクリックして、各種オプションが表示されたら **-bin_file** をチェックして **[OK]** をクリックして下さい。

![BIN_FILE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/6769172b-d47c-45fc-93b7-c641ea470872.png)

これでプロジェクトの作成は完了です。

## Block Design作成

Project Managerの画面が表示されたら**Create Block Design**をクリックして、ウィンドウが開いたら名前は変更せずに **[OK]** をクリックします。これで**design_1**の名前でBlock Designが作成されます。

Diagramウィンドウが開いたら、**'＋'** をクリックしてZynq UltraScale+ MPSoCを追加します。IPが追加されたらウィンドウ上部に表示される**Run Block Automation**をクリックして、ウィンドウが開いたら **[OK]** をクリックします。この操作によりBoard PresetがPS部に反映されます。

![IP追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/c986a6d1-1d41-4af7-80cb-2f4830bf1edb.png)

次にZynqのPS-PL間のI/Fを変更します。ZynqのIPブロックをダブル・クリックしてウィンドウを開いたら、**PS-PL Configuration** を選択して、FPDを無効化・LPDを有効化します。変更したら **[OK]** をクリックして下さい。

![Zynq.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/a3ac0443-a4fb-4409-90ce-1bf006aa7f13.png)

次にGPIOを追加します。BoardタブをクリックしてUSER_LED上で右クリックして **Connect Board Component...** を選択します。ウィンドウが開いたら、そのまま **[OK]** をクリックして下さい。

![USER_LED選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/8a8ecb68-7a21-4aa8-b94f-792d9ca06379.png)

GPIOを追加するとDiagram上部に **Run Connection Automation** と表示されますので、これをクリックします。ウィンドウが開いたら、そのまま **[OK]** をクリックして下さい。

右クリックでポップアップを表示して **Regenerate Layout** を選択すると以下の様になるはずです。

![BD完成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/85811aa7-c340-4b24-a2c3-e7242a004e05.png)

これでBlock Designは完成です。

## Bitstream生成

先ずBlock Designに対してHDL Wrapperを作成します。

Sourceタブ上の**design_1**を右クリックして、**Create HDL Wrapper...** を選択します。ウィンドウが開いたら **[OK]** をクリックします。

![HDL_Wrapper.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/fd96c747-13e1-491b-992b-20c4b4581e18.png)

HDL Wrapperの生成には少し時間が掛かります。生成後、図の様にTop Moduleに設定されるまで待ちます。

![TOP_Module.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/bc0ce053-9930-4dab-9bd7-96870047db72.png)

Flow Navigatorの **Generate Bitstream** をクリックして下さい。この後、ウィンドウが２回開きますので、**[Yes]** , **[OK]** の順でクリックします。

Bitsreamが生成されると **'Bitstream Generation Completed'** というタイトルでウィンドウが開きますので、**[Cancel]** をクリックして終了して下さい。

これで作業完了です。

## XSAファイル生成

次に生成したBitstreamを元にXSAファイルの生成を行います。このファイルはSystem Device Treeの元になります。

最初にメニューバーから **[File]** -> **[Export]** -> **[Export Hardware...]** を選択します。

ウィンドウが開いたら **[Next]** をクリックして次の画面で**Include Bitstream**を選択してから **[Next]** をクリックします。

次にファイル名の指定画面になりますが、本記事ではkr260-gpio-userに設定します。

![XSA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/3845bb57-987e-46e5-87ae-b358bef6182c.png)

この後は **[Next]** , **[Finish]** の順にクリックしてXSAファイルを生成します。

## System Device Tree作成

作成したXSAファイルからSystem Device Treeを生成します。

xsctコマンドはVivadoを起動したシェルから実行して下さい。`SDT_DIR`, `XSA_FILE`は作業環境に合わせて定義して下さい。

```bash:
SDT_DIR=$HOME/sdt
XSA_FILE=$HOME/kr260-gpio-user/kr260-gpio-user.xsa
xsct -eval "sdtgen set_dt_param -xsa $XSA_FILE -dir $SDT_DIR -board_dts zynqmp-smk-k26-reva;sdtgen generate_sdt"
```
System Device Treeは`SDT_DIR`で定義されたフォルダ配下に生成されます。

これでVivadoでの作業は終了です。

# PetaLinux作業手順
## 環境変数定義

作業時に利用する環境変数を以下の様に定義します。

```bash:
WORK_DIR=$HOME/ws/petalinux
PROJ_NAME=kr260-gpio-user
PROJ_DIR=$WORK_DIR/$PROJ_NAME
BSP_FILE=$HOME/xilinx-kr260-starterkit-v2024.2-12072024.bsp
SDT_DIR=$HOME/sdt
```

これらは作業環境に応じて変更して下さい。但し`PROJ_NAME`はYoctoのRecipe名にも利用しますので'_'（アンダースコア）や英大文字は使わないで下さい。

`PROJ_BSP`はPetaLinuxで利用するBSPファイルです。下記から入手可能です。

https://japan.xilinx.com/member/forms/download/xef.html?filename=xilinx-kr260-starterkit-v2024.2-12072024.bsp

## 作業手順

### Project作成

Projectを作成して、Vivadoで作成したH/W情報を反映させます。

```bash:Project作成
mkdir -p $WORK_DIR
cd $WORK_DIR
petalinux-create project -n $PROJ_NAME -s $BSP_FILE
cd $PROJ_NAME
petalinux-config --get-hw-description $SDT_DIR
```

`petalinux-config`を実行して下記メッセージが表示されたら"y"を入力して下さい。

```
[WARNING] Your yocto SDK was changed in tool
Please input "y" to proceed the installing SDK into project, "n" to use existing yocto SDK:
```

次にConfiguration画面が表示されますので、[FPGA Manager]->[Fpga Manager]を選択します。

![PetaLinuxConfig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/a40b7892-0c26-4de7-90f8-6ab5151fd785.png)

`<Save>`を選択して設定を保存したら`<Exit>`を２回選択して終了します。

### DFX用Recipe作成

KR260を含むKria SOMsはこれまでの評価ボードとは起動手順が異なります。最初にPS部のみを初期化してLinuxを起動した後で、DFX(Dynamic Function eXchange)を用いてPL部をConfigurationします。この影響なのかは判りませんが、petalinux-configコマンドを使っただけでは作成したBitstreamがPetaLinuxに組み込まれませんでした。

この問題を解決する為にVivadoで作成したBitstreamを組み込むRecipeを追加します。先ず`petalinux-create`でRecipeの雛形を作成します。

```bash:
cd $PROJ_DIR
petalinux-create apps -n $PROJ_NAME --template dfx_user_dts --srcuri "components/plnx_workspace/device-tree/pl-overlay-full/pl.dtsi project-spec/hw-description/kr260-gpio-user.bin" --enable
```

引数で指定している`pl.dtsi`は`petalinux-config`を実行した時に生成されるファイルです。拡張子は.dtsiですが、単体でDTBOファイルにコンパイル可能な形に変換されています。

`pl.dtsi`ではPL部に対応するDevice Treeが定義されています。これだけでもGPIOが操作可能になりますが、[以前の記事](https://qiita.com/hkato-sssl/items/cad9e26e973942ed608c)と同様にsysfsからLEDを制御可能にする為の定義を追加します。`$PROJ_DIR/project-spec/meta-user/recipes-firmware/$PROJ_NAME/files`配下に下記ファイルを作成して下さい。

```:axi_gpio_leds.dts
#include "dt-bindings/gpio/gpio.h"
#include "pl.dtsi"

&{/} {
    axi_gpio_leds {
        compatible = "gpio-leds";
        uf1 {
            gpios = <&axi_gpio_0 0 GPIO_ACTIVE_HIGH>;
        };
        uf2 {
            gpios = <&axi_gpio_0 1 GPIO_ACTIVE_HIGH>;
        };
    };
};
```

続けて同じフォルダに`shell.json`を下記内容で作成します。これはDFXを実行する際に利用されます。

```json:shell.json
{
    "shell_type" : "XRT_FLAT",
    "num_slots": "1"
}
```

最後に作成したファイルをビルド対象に指定します。`$PROJ_DIR/project-spec/meta-user/recipes-firmware/$PROJ_NAME/$PROJ_NAME.bb`の最後に下記を追加して下さい。

```:kr260-gpio-user.bb追加
SRC_URI:append = " file://axi_gpio_leds.dts file://shell.json"
```

レシピの修正を終えたら、ビルドを実行します。

```bash:
petalinux-build
```

ビルドが完了したら、SD Cardに書き込むWICイメージを作成します。

```bash:
petalinux-package wic --images-dir images/linux/ --bootfiles "ramdisk.cpio.gz.u-boot,boot.scr,Image,system.dtb,system-zynqmp-sck-kr-g-revB.dtb"
```

コマンドを実行すると`images/linux/petalinux-sdimage.wic`が作成されます。

これでPetaLinuxのビルドは完了です。

## SD Cardへの書き込み

`petalinux-package`で生成されたWICファイルをbalenaEtcher等のツールを使ってSD Cardへ書き込んで下さい。

## Firmware更新

SOMに書き込まれているFirmwreが古いと起動しない場合があります。PetaLinuxが起動しない場合は下記URLを参考にFirmwareを更新して下さい。

https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/3020685316/Kria+SOM+Boot+Firmware+Update

# PetaLinux起動手順
## 電源投入

WICイメージを書き込んだSD Cardをボードに装着して電源を投入して下さい。後は自動的にPetaLinuxが起動します。

起動後はユーザー名`petalinux`でログインします。初回のログイン時はパスワードの設定を求められます。

## Bitstreamの切り替え

この後は全てroot権限で実行しますので、`sudo -s`を実行してrootに切り替えて下さい。

先ずは`xmutil`コマンドで利用可能なBitstreamを確認します。

```bash:
xilinx-kr260-starterkit-20242:~# xmutil listapps
                   Accelerator  Accel_type                    Base    Pid   Base_type  #slots(RPU+PL+AIE)    slot->handle
              k26-starter-kits    XRT_FLAT        k26-starter-kits  id_ok    XRT_FLAT             (0+0+0)           0->0,
               kr260-gpio-user    XRT_FLAT         kr260-gpio-user  id_ok    XRT_FLAT             (0+0+0)              -1
```

各イメージは`/lib/firmware/xilinx/`配下に置かれています。デフォルトで**k26-starter-kits**が選択されています。

下記コマンドで**kr260-gpio-user**へ切り替えます。

```bash:
xmutil unloadapp
xmutil loadapp kr260-gpio-user
```

幾つかワーニングが表示されますが、**FANの動作音が大きくなれば**ロード成功です。

デフォルトのBitstreamではFAN制御が行われており、PetaLinuxの起動後は動作音が静かになっていたと思います。今回作成したBtstreamではFAN制御の回路を組み込んでいないので、この様な現象が起こります。

## sysfsによるLチカ

Bitstreamの切り替えと同時にDevice Treeも更新されます。正常にビルド出来ていれば`/sys/class/leds/`配下に`uf1`と`uf2`が生成されます。

```bash:
xilinx-kr260-starterkit-20242:~# ls /sys/class/leds/
heartbeat  uf1  uf2  vbus_det
```

`uf1`と`uf2`はボード上のシルクプリントに対応しています。

![KR260_LEDS.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332407/a43aef89-f2d0-4ef8-b709-6e2701f8d242.jpeg)

各LEDの点灯方法は以下の通りです。

```bash:
echo 1 > /sys/class/leds/uf1/brightness
echo 1 > /sys/class/leds/uf2/brightness
```

`0`を書き込めばLEDは消灯します。

## Bitstreamの切り戻し

下記コマンドの実行で起動時のイメージに戻ります。

```bash:
xmutil unloadapp
xmutil loadapp k26-starter-kits
```

実行後は`/sys/class/leds`配下の`uf1`, `uf2`が削除され、LEDは消灯します。
FAN制御の回路が有効になり、動作音は静かになります。

システム起動時のBitstreamを変更したい場合は`/etc/dfx-mgrd/default_firmware`を変更します。

# おわりに

何とか自前のロジックやDevice Treeを組み込む事が出来ましたが、これが正解かは不明です。最近はYoctoのみでビルド可能な環境が提供されたりするので、もしかしたらpetalinux toolsが廃止になるのかなとも思っています。この先もビルド環境は変わって行きそうな感じがします。