はじめに
KR260用PetaLinuxをビルドするとDFX(Dynamic Function eXchange)が有効化されたシステムがビルドされます。これはLinux起動後にPL部の構成を動的に変更可能となる便利な機能ですが、今までBOOT.BINやu-bootでPL部をコンフィグレーションしていた環境の移植では不便な時があります。
この機能を実現しているdfx-mgr.serviceを何とか無効化出来ないかと試行錯誤した結果について記述します。
本記事は自分でrootfsを作っている人は関係ありません。私の様に自分でrootfsは作らずPetaLinuxを利用したい人向けです。
dfx-mgr.serviceを無効化する方法
動作しているPetaLinux環境があれば下記コマンドを実行して下さい。
sudo systemctl mask dfx-mgr
これで無効化は完了です。後は、Bitstreamを含めたBOOT.BINを書き込むなり、u-bootからBitstreamを読み込むなりして下さい。
dfx-mgr.serviceを無効化しても、Linux環境を適切に作成しないとBOOT.BINに含まれるロジックが正常に動作しない事があります。
以降ではdfx-mgr.serviceを無効化したPetaLinuxプロジェクトをXSAファイルを元に作成する手順について記述します。
開発環境
Board
Kria KR260 Robotics Starter Kit
Tools
Vitis 2024.2
Vivado 2024.2
PetaLinux 2024.2
PetaLinux BSP
xilinx-kr260-starterkit-v2024.2-12072024.bsp
Host OS
Ubuntu 24.04 Desktop
今回の作業でVitisは使いませんが、System Device Treeを生成する際にVitisに含まれるツールやデータを利用する為、Vitisのインストールが必要です。
Vivado作業手順
BlockDesign イメージ
今回作成するBlockDesignのイメージです。
お約束のFAN Controlの他にボード上のLED2つをBinary Counterを使って点滅させます。
本記事ではLinuxの起動後でもLEDが点滅を続ける事でDFXが無効化されている事を確認します。
プロジェクト作成
以下のTCLスクリプトと制約ファイルを使い、プロジェクトの作成からXSAファイルの生成までを行います。TCLスクリプトの最初に定義しているパラメータは環境に合わせて変更して下さい。
kr260-blink-leds.tcl
とkr260-blink-leds.xdc
は同じディレクトリに置いて下さい。
kr260-blink-leds.tcl - プロジェクト作成&XSAファイル生成
# parameters
set JOBS 8
set PROJ_NAME kr260-blink-leds
set PROJ_DIR $env(HOME)/ws/vivado/$PROJ_NAME
set SCRIPT_DIR [file dirname [info script]]
set XDC_FILE $SCRIPT_DIR/$PROJ_NAME.xdc
# create the project
create_project $PROJ_NAME $PROJ_DIR -part xck26-sfvc784-2LV-c
set_property board_part xilinx.com:kr260_som:part0:1.1 [current_project]
set_property board_connections {som240_1_connector xilinx.com:kr260_carrier:som240_1_connector:1.1 som240_2_connector xilinx.com:kr260_carrier:som240_2_connector:1.1} [current_project]
set_property STEPS.WRITE_BITSTREAM.ARGS.BIN_FILE true [get_runs impl_1]
# create the block design
create_bd_design "design_1"
update_compile_order -fileset sources_1
create_bd_cell -type ip -vlnv xilinx.com:ip:zynq_ultra_ps_e:3.5 zynq_ultra_ps_e_0
apply_bd_automation -rule xilinx.com:bd_rule:zynq_ultra_ps_e -config {apply_board_preset "1" } [get_bd_cells zynq_ultra_ps_e_0]
set_property -dict [list \
CONFIG.PSU__TTC0__WAVEOUT__ENABLE {1} \
CONFIG.PSU__TTC0__WAVEOUT__IO {EMIO} \
CONFIG.PSU__CRL_APB__PL2_REF_CTRL__SRCSEL {IOPLL} \
CONFIG.PSU__FPGA_PL2_ENABLE {1} \
] [get_bd_cells zynq_ultra_ps_e_0]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_clk0] [get_bd_pins zynq_ultra_ps_e_0/maxihpm0_fpd_aclk]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_clk0] [get_bd_pins zynq_ultra_ps_e_0/maxihpm1_fpd_aclk]
create_bd_cell -type ip -vlnv xilinx.com:ip:c_counter_binary:12.0 c_counter_binary_0
set_property CONFIG.Output_Width {27} [get_bd_cells c_counter_binary_0]
create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_0
set_property -dict [list \
CONFIG.DIN_FROM {26} \
CONFIG.DIN_TO {25} \
CONFIG.DIN_WIDTH {27} \
] [get_bd_cells xlslice_0]
make_bd_pins_external [get_bd_pins xlslice_0/Dout]
set_property name LED [get_bd_ports Dout_0]
connect_bd_net [get_bd_pins c_counter_binary_0/Q] [get_bd_pins xlslice_0/Din]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/pl_clk2] [get_bd_pins c_counter_binary_0/CLK]
create_bd_cell -type ip -vlnv xilinx.com:ip:xlslice:1.0 xlslice_1
set_property -dict [list \
CONFIG.DIN_FROM {2} \
CONFIG.DIN_TO {2} \
CONFIG.DIN_WIDTH {3} \
] [get_bd_cells xlslice_1]
make_bd_pins_external [get_bd_pins xlslice_1/Dout]
set_property name FAN_CTRL [get_bd_ports Dout_0]
connect_bd_net [get_bd_pins zynq_ultra_ps_e_0/emio_ttc0_wave_o] [get_bd_pins xlslice_1/Din]
regenerate_bd_layout
# create the wrapper file
make_wrapper -files [get_files $PROJ_DIR/$PROJ_NAME.srcs/sources_1/bd/design_1/design_1.bd] -top
add_files -norecurse $PROJ_DIR/$PROJ_NAME.gen/sources_1/bd/design_1/hdl/design_1_wrapper.v
update_compile_order -fileset sources_1
# add the contraint file
add_files -fileset constrs_1 -norecurse $XDC_FILE
import_files -fileset constrs_1 $XDC_FILE
# generate the bitstream file
launch_runs impl_1 -to_step write_bitstream -jobs $JOBS
wait_on_run impl_1
# write the XSA file
write_hw_platform -fixed -include_bit -force -file $PROJ_DIR/$PROJ_NAME.xsa
kr260-blink-leds.xdc - 制約ファイル
set_property PACKAGE_PIN A12 [get_ports {FAN_CTRL[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {FAN_CTRL[0]}]
set_property PACKAGE_PIN E8 [get_ports {LED[1]}]
set_property IOSTANDARD LVCMOS18 [get_ports {LED[1]}]
set_property PACKAGE_PIN F8 [get_ports {LED[0]}]
set_property IOSTANDARD LVCMOS18 [get_ports {LED[0]}]
スクリプトはvivadoのBatch modeかGUIのTCL consoleから実行可能です。以下はBatch modeでの実行例です。
source /tools/Xilinx/Vivado/2024.2/settings64.sh
vivado -mode batch -source kr260-blink-leds.tcl
SDT生成
XSAファイルからSDTを生成します。生成には以下のスクリプトを利用します。
k26-gensdt.tcl - SDT生成
if { $argc < 2 } {
set script_name [file tail [info script]]
puts "\nUsage: xsct $script_name <xsa_file> <output_dir>"
exit 1
}
set xsa_file [lindex $argv 0]
set output_dir [lindex $argv 1]
puts ""
puts " XSA File: $xsa_file"
puts "Output Dir: $output_dir"
sdtgen set_dt_param -board_dts zynqmp-smk-k26-reva
sdtgen set_dt_param -xsa $xsa_file
sdtgen set_dt_param -dir $output_dir
sdtgen generate_sdt
以下が実行例です。ホーム・ディレクトリ配下にSDTを作成します。パラメータ定義はkr260-blink-leds.tclと合わせて下さい。
# parameters
PROJ_NAME=kr260-blink-leds
PROJ_DIR=$HOME/ws/petalinux/$PROJ_NAME
SDT_DIR=$HOME/${PROJ_NAME}_sdt
XSA_FILE=$PROJ_DIR/$PROJ_NAME.xsa
# generate the SDT
xsct k26-gensdt.tcl $XSA_FILE $SDT_DIR
PetaLinux作業手順
環境変数定義
作業時に利用する環境変数を以下の様に定義します。
BSP_FILE=$HOME/xilinx-kr260-starterkit-v2024.2-12072024.bsp
PROJ_NAME=kr260-blink-leds
PROJ_DIR=$HOME/ws/petalinux/$PROJ_NAME
SDT_DIR=$HOME/${PROJ_NAME}_sdt
BSP_FILE
はPetaLinuxのプロジェクト作成で利用するファイルです。下記から入手可能です。
BSP_FILE
はホームディレクトリ配下に置いている事を想定しています。ここのパスも作業環境に合わせて変更して下さい。
プロジェクト作成
BSP_FILE
を元にプロジェクトを作成します。
petalinux-create project -n $PROJ_DIR -s $BSP_FILE
cd $PROJ_DIR
petalinux-config --get-hw-description $SDT_DIR --silentconfig
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:
dfx-mgr.serviceのマスク処理追加
dfx-mgr_%.bbappend
のファイル名でdfx-mgr.service
をマスクする処理を追加します。
INST_DIR = "/etc/systemd/system"
SYMLINK_INST_DIR = "${sysconfdir}/systemd/system"
do_install:append() {
install -d ${D}${SYMLINK_INST_DIR};
ln -sf /dev/null ${D}${SYMLINK_INST_DIR}/${PN}.service
}
FILE:${PN}:append = " ${SYMLINK_INST_DIR}"
上記はコマンドラインからsystemctl mask dfx-mgr
を実行した時と同じ処理を実現しています。
bootarg 追加
カーネル・パラメータを定義するDevicetreeのbootargs
にclk_ignore_unused
とnet.ifnames=0
を追加します。project-spec/configs/config
のCONFIG_SUBSYSTEM_EXTRA_BOOTARGS
に
追加します。
-CONFIG_SUBSYSTEM_EXTRA_BOOTARGS="xilinx_tsn_ep.st_pcp=4 cma=900M"
+CONFIG_SUBSYSTEM_EXTRA_BOOTARGS="xilinx_tsn_ep.st_pcp=4 cma=900M clk_ignore_unused net.ifnames=0 "
clk_ignore_unused
はPetaLinuxで利用しないクロックの停止を抑止します。AMPで複数のOSを動作させている場合や、今回のLED制御の様にLinuxから制御しないけどPSからクロックを供給しているロジックが存在する場合は必須です。
net.ifnames=0
はEthernet I/Fの名称をeth0, eth1にする為に設定しています。これを指定しないとEthernet I/Fはend0, end1となりネットワークの初期化処理でエラーとなります。
Devicetree修正
PL部を記述しているpl.dtsiをプロジェクトのDevicetreeに追加します。Linuxから制御するロジックが存在する場合は必須の作業です。
device-treeレシピに含まれるsystem-user.dtsi
を以下の様に修正します。
/include/ "system-conf.dtsi"
/include/ "pl.dtsi"
/ {
};
次にdevice-tree.bbappend
を修正します。
FILESEXTRAPATHS:prepend := "${THISDIR}/files:"
FILESEXTRAPATHS:prepend := "${TOPDIR}/../project-spec/hw-description:"
SRC_URI:append = " file://system-user.dtsi"
SRC_URI:append = " file://pl.dtsi"
require ${@'device-tree-sdt.inc' if d.getVar('SYSTEM_DTFILE') != '' else ''}
PetaLinuxのビルド
レシピの修正を終えたらPetaLinuxのビルドを行います。
petalinux-build
BIFファイル作成
BOOT.BINを作成する為のBIFファイルを作成します。通常petalinux-packageコマンドでBOOT.BINが作成可能なのですが、KR260のBSPで作成したプロジェクトだと何故かBOOT.BINにBitstreamを含んでくれません。意地でもDFXを利用させる思想の様です。
仕方ないので、自前のBIFファイルとbootgenコマンドでBOOT.BINを作成します。以下がサンプルとなります。BIFファイルの中にはファイル名が含まれますが、ここではPetaLinuxのプロジェクト配下で実行する事を想定したパス指定となっています。
the_ROM_image:
{
[bootloader, destination_cpu=a53-0] images/linux/zynqmp_fsbl.elf
[pmufw_image] images/linux/pmufw.elf
[destination_device=pl] images/linux/system.bit
[destination_cpu=a53-0, exception_level=el-3, trustzone] images/linux/bl31.elf
[destination_cpu=a53-0, load=0x100000] images/linux/system.dtb
[destination_cpu=a53-0, exception_level=el-2] images/linux/u-boot.elf
}
BOOT.BIN生成
先程作成したBIFファイルを使いBOOT.BINを生成します。bootgenコマンドの実行はPetaLinuxのプロジェクト配下で実行して下さい。
cd $PROJ_DIR
bootgen -arch zynqmp -image kr260-bootgen.bif -o images/linux/BOOT.BIN
SDイメージ作成
最後にSDイメージを作成します。
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"
コマンド実行が成功すると$PROJ_DIR/image/linux/petalinux-sdimage.wic
が生成されます。
各イメージ・ファイルの書き込み
BOOT.BIN
とpetalinux-sdimage.wic
をKR260へ書き込みます。BOOT.BINの書き込みは下記ページを参考に実行して下さい。
WICイメージはbalenaEtcher等のツールを利用してSDメモリに書き込んで下さい。
動作確認
KR260にWICイメージを書き込んだSDメモリを挿入したら電源を投入して下さい。u-bootが起動する前にボード上のLEDが点滅するのを確認して下さい。
その後、Linuxを起動してログイン・プロンプトが表示されてもLEDが点滅していればDFXは実行されておらず成功となります。
この時、ログインしてsystemctrl
で状態を見ると以下の様に表示されます。
xilinx-kr260-starterkit-20242:~$ systemctl status dfx-mgr
* dfx-mgr.service
Loaded: masked (Reason: Unit dfx-mgr.service is masked.)
Active: inactive (dead)
おまけ
dfx-mgr.serviceをDisableにできない理由
dfx-mgr.serviceはdisable
できないのでmask
で無効化します。仮にdisable
に設定しても、下記の様にサービスが起動されます。
xilinx-kr260-starterkit-20242:~$ systemctl status dfx-mgr
* dfx-mgr.service - dfx-mgrd Dynamic Function eXchange
Loaded: loaded (/usr/lib/systemd/system/dfx-mgr.service; disabled; preset: enabled)
Active: active (running) since Wed 2025-07-16 03:55:21 PDT; 23s ago
Docs: https://github.com/Xilinx/dfx-mgr
Process: 965 ExecStartPre=/usr/bin/xlnx-firmware-detect (code=exited, status=0/SUCCESS)
Main PID: 1028 (dfx-mgrd)
Status: "dfx-mgr daemon started"
Tasks: 2 (limit: 3602)
Memory: 3.0M (peak: 4.2M)
CPU: 248ms
CGroup: /system.slice/dfx-mgr.service
`-1028 /usr/bin/dfx-mgrd
disabled
と表示されているのに起動している原因が解らず、かなり悩みました。これはdfx-mgr.serviceとkria-dashboard.serviceに依存関係がある事が原因と思われます。依存関係は/usr/lib/systemd/system/kria-dashboard.service
で設定されています。
/usr/lib/systemd/system/kria-dashboard.service
[Unit]
Description=kria-dashboard-init
Requires=network-online.target
After=network-online.target
Wants=dfx-mgr.service ★★ここで設定★★
[Service]
ExecStart=/usr/bin/kria-dashboard.sh
StandardOutput=journal+console
[Install]
WantedBy=multi-user.target
双方のサービスをdisable
に設定してからLinuxを再起動するとdfx-mgr.serviceは起動されません。
xilinx-kr260-starterkit-20242:~$ systemctl status dfx-mgr
* dfx-mgr.service - dfx-mgrd Dynamic Function eXchange
Loaded: loaded (/usr/lib/systemd/system/dfx-mgr.service; disabled; preset: enabled)
Active: inactive (dead)
Docs: https://github.com/Xilinx/dfx-mgr
kria-dashboard.serviceを無効化した時の影響が不明だったので、今回はdfx-mgr.serviceのみを無効化する形を取りました。