zynq 通过linux 加载fpga的bit文件 -fpga_manager

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"
};

附图一张

posted @ 2020-07-15 15:30  tccxy  阅读(5713)  评论(0编辑  收藏  举报