Debian/Ubuntu でKV260 で冷却ファンを制御する (その１)







# はじめに


KV260 には ZynqMP チップを冷却するためのファンがついています。この冷却ファンを Debian/Ubuntu から制御するための方法を３回に分けて説明します。今回はその１回目です。




# 冷却ファン関連のハードウェア/ソフトウェアスタック


Debian/Ubuntu では、冷却ファンを制御するために下の図で示すようなソフトウェア/ハードウェアスタックになっています。


![Fig.1 KV260 Fan Control Stack](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24981/6b8a7690-00b4-ea63-2082-38689b1483fb.jpeg "Fig.1 KV260 Fan Control Stack")

Fig.1 KV260 Fan Control Stack

<br />




# PWM制御機能付きファン



## 概要


PWM制御機能とは、Pulse Width Modulation (パルス幅変調) を用いた制御機能です。PWM制御機能付きファンは、コントロール端子に入力するパルス信号のデューティ比を変化させることによって、ファンの回転速度を外部から制御することが出来ます。


![Fig.2 PWM Controlled FAN](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24981/4e65a9b1-870e-9d4e-09d4-a96748621b04.jpeg "Fig.2 PWM Controlled FAN")

Fig.2 PWM Controlled FAN

<br />


# Programmable Logic



## 概要


この章では Prgrammable Logic 部の説明をします。Programmble Logic は下の図のシェードがかかった部分です。


![Fig.3 KV260 Fan Control Stack (Programmable Logic)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24981/6c44a9aa-1eb2-a626-70a6-79325b60ac26.jpeg "Fig.3 KV260 Fan Control Stack (Programmable Logic)")

Fig.3 KV260 Fan Control Stack (Programmable Logic)

<br />



KV260 では PWM制御機能付きファンを制御するためのコントロール信号が ZynqMP の A12 ピンに接続されています。この A12 ピンはZynqMP の Programmable Logic に接続されています。Programmable Logic でパルス信号を生成することでファンの回転数を制御することが出来ます。

なお、Programmable Logc がプログラムされていない時や、Programmable Logic が A12 ピンを制御しないようにプログラムされている場合、コントロール信号は High になって、常にフル回転でファンが回転するようになっています。


## プログラム例(簡易版)



### 概要


この節では、PWMの波形を生成するのに ZynqMP の TTC(Triple Timer Counter) モジュールを使った、非常に簡単な例の作り方を示します。

ここで示すプログラム例は、次の図が示すように、ZynqMP の ttc0 の wave 出力信号を FAN_EN ポート(A12) に直接つなげるだけの非常に簡単なものです。


![Fig.4 K26-Fan-Enable](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24981/076337b1-06bd-e03a-63ba-c4b997036ccf.png "Fig.4 K26-Fan-Enable")

Fig.4 K26-Fan-Enable

<br />

TTC(Triple Timer Counter) モジュールは、ZynqMP の PS (Processing System) 部にあるハードウェアで、3つの独立したタイマ/カウンタモジュールを提供します。ZynqMP にはこのTTCが４つ(ttc0、ttc1、ttc2、ttc3) 搭載されています。

この例では ttc0 のチャネル2を使います。そのため、ttc0 からの出力 emio_ttc0_wave_o[2:0] のうち emio_ttc0_wave_o[2] だけを取り出すために Slice IP (ttc0_slice) を使っています。



この例を Vivado  の GUI を使って生成する方法は、Ryuz88 さんが次の記事で詳細に説明されているので、そちらをご覧ください。

* [『Kria KV260 fanコントロール』 @Zenn]



ここでは Tcl を使って生成する方法を説明します。


### GitHub リポジトリの紹介


この例で説明する Tcl スクリプトは以下の Github のリポジトリで公開しています。ビルド済みのビットストリームファイルも提供しているので、ビルドするのが面倒な人がこちらを利用してください。

* https://github.com/ikwzm/K26-Fan-Enable.git


### 開発環境


・ Xilinx Vivado 2021.2

・ KV260 のボード情報


### Tclスクリプトの説明


まず次のような Tcl スクリプトを使います。


```Tcl:fpga/add_fan_enable.tcl
proc add_fan_enable { zynq_ultra_ps_e_0 port_name prefix} {
    variable slice_cell
    variable cell_name
    variable net_name_din
    variable net_name_dout
    if { $port_name eq "" } {
        set port_name FAN_EN
    }
    if { $prefix eq "" } {
	set prefix ttc0
    }
    
    append cell_name     $prefix    "_slice"
    append net_name_din  $cell_name "_din"
    append net_name_dout $cell_name "_dout"
    set_property -dict [list CONFIG.PSU__TTC0__WAVEOUT__ENABLE {1} ] $zynq_ultra_ps_e_0
    set_property -dict [list CONFIG.PSU__TTC0__WAVEOUT__IO {EMIO}  ] $zynq_ultra_ps_e_0
    set slice_cell  [ create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 $cell_name ]
    set_property -dict [ list CONFIG.DIN_FROM {2} CONFIG.DIN_TO {2} CONFIG.DIN_WIDTH {3} ] $slice_cell
    create_bd_port -dir O -from 0 -to 0 $port_name
    connect_bd_net -net $net_name_dout [get_bd_pins $slice_cell/Dout] [get_bd_ports $port_name] 
    connect_bd_net -net $net_name_din  [get_bd_pins $slice_cell/Din ] [get_bd_pins $zynq_ultra_ps_e_0/emio_ttc0_wave_o]
}

```


この Tcl スクリプトは次の処理を行うプロシージャを定義しています。



  1. zynqmp_ultra_ps_e\_0 の ttc0 波形出力を有効化
  2. zynqmp_ultra_ps_e\_0 のttc0 波形出力先を EMIO に設定
  3. Slice IP を追加
  4. Slice IP の入力ビット幅を３に、出力ビット幅を１に設定
  5. Slice IP の入力の2番目を出力に設定
  6. 外部ポートを port_name 名を使って生成
  7. 外部ポートと Slice IP の出力ポートを接続
  8. zynqmp_ultra_ps_e\_0 の emio_ttc0_wave_o と Slice IP の入力ポートを接続



この Tcl スクリプトを取り込んで add_fan_enable プロシージャを実行します。この例を示します。


```Tcl:fpga/design_1_bd_2021.2.tcl
source [file join $project_directory "add_fan_enable.tcl"  ]
  
set zynq_ultra_ps_e_0 [ create_bd_cell -type ip -vlnv xilinx.com:ip:zynq_ultra_ps_e:3.3 zynq_ultra_ps_e_0 ]
apply_bd_automation -rule xilinx.com:bd_rule:zynq_ultra_ps_e -config {apply_board_preset "1"} $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__M_AXI_GP0   {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__M_AXI_GP1   {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__IRQ0        {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__USE__FABRIC__RST {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__FPGA_PL0_ENABLE  {0} ] $zynq_ultra_ps_e_0
set_property -dict [list CONFIG.PSU__FPGA_PL1_ENABLE  {0} ] $zynq_ultra_ps_e_0
add_fan_enable $zynq_ultra_ps_e_0 FAN_EN ttc0

```




この例では、以下のことを実行しています。



  1. add_fan_enable.tcl を読み込み
  2. zynqmp_ultra_ps_e を Add IP 
  3. プリセットされているボード情報を元に zynqmp_ultra_ps_e を設定
  4. この例では不要な zynqmp_ultra_ps_e の各種ポートを無効化
  5. add_fan_enable を実行




### プロジェクトの生成


Vivado のバッチモードでプロジェクトを生成する場合は次のようにします。


```Shell
shell$ cd fpga
shell$ vivado -mode batch -source create_project.tcl
```




Vivado の GUI モードでプロジェクトを生成する場合は次のようにします。


```Shell
Vivado > Tools > Run Tcl Script... > fpga/create_project.tcl
```





### 論理合成と配置配線


Vivado のバッチモードで論理合成と配置配線を行う場合は次のようにします。


```Shell
shell$ cd fpga
shell$ vivado -mode batch -source implementation.tcl
```




Vivado の GUI モードで論理合成と配置配線を行う場合は、前節で生成したプロジェクトをVivado で開き、Run Synthesis と Run Imlementation を実行します。




### ビットストリームファイルの生成


配置配線後のビットストリームファイルを、Linux で扱うことの出来るビットストリームファイルに変換します。


```Shell
shell$ cd fpga
shell$ bootgen -arch zynqmp -image k26-fan-enable.bif -w -o ../k26-fan-enable.bin
```





### KV260 のPL部にロード


ここではデバイスツリーオーバーレイを使って、ビットストリームファイルを KV260 の PL 部にロードする例を示します。まず次のようなデバイスツリーファイルを用意します。


```devicetree:k26-fan-enable.dts
/dts-v1/; /plugin/;
/ {
	fragment@0 {
		target-path = "/fpga-full";
		__overlay__ {
			firmware-name = "k26-fan-enable.bin";
		};
 	};
};
```




前節でビルドしたビットストリームファイルを /lib/firmware にコピーします。なお、紹介した GitHub のリポジトリには gz 圧縮したビットストリームファイルが用意されているので、解凍してから /lib/firmware にコピーしてください。


```Shell
shell$ sudo cp k26-fan-enable.bin /lib/firmware
```




デバイスツリーオーバーレイを実行します。dtbo-config を使う場合は次のようにします。


```Shell
shell$ sudo dtbo-config --install k26-fan-enable --dts k26-fan-enable.dts
```




dtbo-config が無い場合は、次の手順でデバイスツリーオーバーレイを実行できます。


```Shell
shell$ dtc -I dts -O dtb -@ -o k26-fan-enable.dtb k26-fan-enable.dts
shell$ sudo mkdir /config/device-tree/overlays/k26-fan-enable
shell$ sudo cp k26-fan-enable.dtb /config/device-tree/overlays/k26-fan-enable/dtbo
```





# 参考



## 今回の関連記事


* [『Debian/Ubuntu でKV260 で冷却ファンを制御する (その２)』 @Qiita]
* [『Debian/Ubuntu でKV260 で冷却ファンを制御する (その３)』 @Qiita]


## 参考にした記事


* [『Kria KV260 fanコントロール』 @Zenn]


## GitHub リポジトリ


* https://github.com/ikwzm/K26-Fan-Enable.git


[『Debian/Ubuntu でKV260 で冷却ファンを制御する (その１)』 @Qiita]: https://qiita.com/ikwzm/items/345184df3a7abd6b4a26 "『Debian/Ubuntu でKV260 で冷却ファンを制御する (その１)』 @Qiita"
[『Debian/Ubuntu でKV260 で冷却ファンを制御する (その２)』 @Qiita]: https://qiita.com/ikwzm/items/f94748f5353271aab5ee "『Debian/Ubuntu でKV260 で冷却ファンを制御する (その２)』 @Qiita"
[『Debian/Ubuntu でKV260 で冷却ファンを制御する (その３)』 @Qiita]: https://qiita.com/ikwzm/items/23149d29339e8442eed2 "『Debian/Ubuntu でKV260 で冷却ファンを制御する (その３)』 @Qiita"
[『Kria KV260 fanコントロール』 @Zenn]: https://zenn.dev/ryuz88/articles/kria_fan_control "『Kria KV260 fanコントロール』 @Zenn"