zynq通過linux加載fpga的bit流文件
zynq 我們熟知分為pl和ps兩個部分,自然代碼也就分為這兩部分,對於較大的項目來說,必然也是由不同的人員去開發的,例如邏輯工程師搞定pl,嵌入式工程師搞定ps
這是我們很自然的想到,能否將pl的固件作為一個單獨部分由內核去管理呢,這樣我就可以根據不同的場景,去加載不通bit流文件
xilinx已經提供了這部分功能接下來將記錄如何去做
需要說明的是 ps的部分還是在fsbl中的 這一點是無法更改的,否則內核也肯定起不來啊
我這邊構建的是一個很簡單的vivado框架,就是一個自己hls寫的led的小ip
petalinux將bit文件打包到BOOT.bin時可以看到文件大小,是比較大的
zw@zw-pc:~/swap/explore/hls/led_project/petalinux/led/images/linux$ ls -la
total 517232
drwxrwxr-x 2 zw zw 4096 4月 20 14:11 .
drwxrwxr-x 3 zw zw 4096 4月 17 13:10 ..
-rw-rw-r-- 1 zw zw 4604224 4月 20 14:02 BOOT.BIN
-rw-r--r-- 1 zw zw 3954692 4月 17 14:45 image.ub
-rw-r--r-- 1 zw zw 74806272 4月 17 14:45 rootfs.cpio
-rw-r--r-- 1 zw zw 20917537 4月 17 14:45 rootfs.cpio.bz2
-rw-r--r-- 1 zw zw 23337430 4月 17 14:45 rootfs.cpio.gz
-rw-r--r-- 1 zw zw 23337494 4月 17 14:45 rootfs.cpio.gz.u-boot
首先進到image/linux目錄
- 拷貝vivado的bit文件到當前目錄
位於vivado工程project_1.runs/impl_1/design_1_wrapper.bit .
#創建Full_Bitstream.bif內容如下
zw@zw-pc:~/swap/explore/hls/led_project/petalinux/led/images/linux$ cat Full_Bitstream.bif
all:
{
design_1_wrapper.bit
}
#執行bootgen
zw@zw-pc:~/swap/explore/hls/led_project/petalinux/led/images/linux$bootgen -image Full_Bitstream.bif -arch zynq -process_bitstream bin
#執行生成BOOT.bin,去掉fpga選項
zw@zw-pc:~/swap/explore/hls/led_project/petalinux/led/images/linux$ petalinux-package --boot --fsbl ./images/linux/zynq_fsbl.elf --u-boot --force
#可以看到生成的bit流文件,以及BOOT.bin大大減小
zw@zw-pc:~/swap/explore/hls/led_project/petalinux/led/images/linux$ ls -la
total 521184
drwxrwxr-x 2 zw zw 4096 4月 20 14:19 .
drwxrwxr-x 3 zw zw 4096 4月 17 13:10 ..
-rw-rw-r-- 1 zw zw 558656 4月 20 14:19 BOOT.BIN
-rw-rw-r-- 1 zw zw 4045676 4月 20 14:13 design_1_wrapper.bit
-rw-rw-r-- 1 zw zw 4045568 4月 20 14:17 design_1_wrapper.bit.bin
-rw-rw-r-- 1 zw zw 31 4月 20 13:15 Full_Bitstream.bif
-rw-r--r-- 1 zw zw 3954692 4月 17 14:45 image.ub
-rw-r--r-- 1 zw zw 74806272 4月 17 14:45 rootfs.cpio
上板子
#將固件放到/lib/firmware下!!一定是這個目錄
#執行
root@localhost:~# echo 0 > /sys/class/fpga_manager/fpga0/flags
#執行,就可以了
root@localhost:~# echo design_1_wrapper.bit.bin > /sys/class/fpga_manager/fpga0/firmware
- 實現說明
其實看內核的代碼,可以看到
#driver/zynq-fpga.c
#對應的config在Kconfig中都可以很容易找到
#ifdef CONFIG_OF
static const struct of_device_id zynq_fpga_of_match[] = {
{ .compatible = "xlnx,zynq-devcfg-1.0", },
{},
};
MODULE_DEVICE_TABLE(of, zynq_fpga_of_match);
#endif
static struct platform_driver zynq_fpga_driver = {
.probe = zynq_fpga_probe,
.remove = zynq_fpga_remove,
.driver = {
.name = "zynq_fpga_manager",
.of_match_table = of_match_ptr(zynq_fpga_of_match),
},
};
#driver/fpga/fpga-mgr.c
#sysgroup的節點生成 store/show的實現都可以看個大概
static DEVICE_ATTR_RO(name);
static DEVICE_ATTR_RO(state);
static DEVICE_ATTR_WO(firmware);
static DEVICE_ATTR_RW(flags);
static DEVICE_ATTR_RW(key);
static DEVICE_ATTR_RW(iv);
static DEVICE_ATTR_RO(status);
static struct attribute *fpga_mgr_attrs[] = {
&dev_attr_name.attr,
&dev_attr_state.attr,
&dev_attr_firmware.attr,
&dev_attr_flags.attr,
&dev_attr_key.attr,
&dev_attr_iv.attr,
&dev_attr_status.attr,
NULL,
};
ATTRIBUTE_GROUPS(fpga_mgr);
#driver/base/firmware_loader/main.c
#基於firmware框架實現,因此要放到/lib/firmware下
/* direct firmware loading support */
static char fw_path_para[256];
static const char * const fw_path[] = {
fw_path_para,
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
"/lib/firmware"
};
附圖一張