zynq动态加载bit

zynq动态加载bit

前言

zynq作为一款集成arm与fpga的soc,在工业领域具有很大的用武之地,使用petalinux进行开发有很大的便利,但是编译的的系统,需要将fsbl,uboot,bit打包为BOOT.bin文件用于启动,对于fpga人员来说,更换bit需要进行一些列的linux的编译,实属麻烦,况且fpga人员可能一般不太熟悉linux,这会对linux的开发带来很多麻烦。下面介绍一种在petalinux下将bit分离出BOOT.bin中,可以单独替换bit的一种办法。

提示:以下是本篇文章正文内容,下面案例可供参考

一、petalinux编译流程

通常 PetaLinux 工具遵循顺序设计流程模型,如下表所示: 从上表可以看到,使用 Vivado 搭建好硬件平台后,通过几个命令就完成了 Linux 系统的 定制,极其方便。 需要说明的是以上设计流程不是按部就班的每一步都执行一遍,可以根据使用场景有选 择的执行。一般的设计流程如下:

  1. 通过 Vivado 创建硬件平台,得到 hdf 硬件描述文件;
  2. 运行 source <petalinux 安装路径>/settings.sh,设置 Petalinux 运行环境
  3. 通过 petalinux-create -t project 创建 petalinux 工程;
  4. 使用 petalinux-config --get-hw-description,将 hdf 文件导入到 petalinux 工程当中并配置 petalinux 工程;
  5. 使用 petalinux-config -c kernel 配置 Linux 内核;
  6. 使用 petalinux-config -c rootfs 配置 Linux 根文件系统;
  7. 配置设备树文件;
  8. 使用 petalinux-build 编译整个工程;
  9. 使用 petalinux-package --boot 制作 BOOT.BIN 启动文件;
  10. 制作 SD 启动卡,将 BOOT.BIN 和 image.ub 以及根文件系统部署到 SD 卡中;
  11. 将 SD 卡插入开发板,并将开发板启动模式设置为从 SD 卡启动;
  12. 开发板连接串口线并上电启动,串口上位机打印启动信息,登录进入 Linux 系统。

具体的编译命令

第一步:创建工程

petalinux-create -t project --template zynq -n zynq

即可创建一个名为zynq的一个petalinux工程。

第二步:拷贝hdf文件并且配置工程

进入工程目录zynq

cd zynq

拷贝hdf到zynq目录下,并且使用命令配置工程

petalinux-config --get-hw-description ./

第三步:编译工程生成uboot与内核

petalinux-build

在工程目录的imag/linux下可看到对于的uboot.bin,system.bit,image.ub文件

第四步:打包生成BOOT.bin文件

ZYNQ 的启动文件 BOOT.BIN 一般包含 fsbl 文件、bitstream 文件和 uboot 文件。使用下面命令可生成 BOOT.BIN 文件:

petalinux-package --boot --fsbl --fpga --u-boot --force

第五步:启动linux

将BOOT.bin与内核文件image.ub拷贝到sd卡即可启动linux。

二、动态加载bit文件

以上的是正常的petalinux开发linux操作,不过boot.bin文件将fpga文件的bit一起打包在一起了,以下流程可将bit分离出来,实现动态加载,只需更替bit文件即可。

第一步:修改platform-top.h文件

在zynq目录project-spec/meta-user/recipes-bsp/u-boot/files下 platform-top.h文件是uboot配置的一些常数文件

修改前

#include <configs/platform-auto.h>
#define CONFIG_SYS_BOOTM_LEN 0xF000000
#define DFU_ALT_INFO_RAM 
                "dfu_ram_info=" 
        "setenv dfu_alt_info " 
        "image.ub ram $netstart 0x1e00000" 
        "dfu_ram=run dfu_ram_info && dfu 0 ram 0" 
        "thor_ram=run dfu_ram_info && thordown 0 ram 0"

#define DFU_ALT_INFO_MMC 
        "dfu_mmc_info=" 
        "set dfu_alt_info " 
        "${kernel_image} fat 0 1\\;" 
        "dfu_mmc=run dfu_mmc_info && dfu 0 mmc 0" 
        "thor_mmc=run dfu_mmc_info && thordown 0 mmc 0"


/*Required for uartless designs */
#ifndef CONFIG_BAUDRATE
#define CONFIG_BAUDRATE 115200
#ifdef CONFIG_DEBUG_UART
#undef CONFIG_DEBUG_UART
#endif
#endif

/*Define CONFIG_ZYNQ_EEPROM here and its necessaries in u-boot menuconfig if you had EEPROM memory. */
#ifdef CONFIG_ZYNQ_EEPROM
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN         1
#define CONFIG_SYS_I2C_EEPROM_ADDR             0x54
#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS      4
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS  5
#define CONFIG_SYS_EEPROM_SIZE                 1024 /* Bytes */
#define CONFIG_SYS_I2C_MUX_ADDR                0x74
#define CONFIG_SYS_I2C_MUX_EEPROM_SEL          0x4
#endif

修改后

#include <configs/platform-auto.h>
#define CONFIG_FPGA_ZYNQPL
#define CONFIG_SYS_BOOTM_LEN 0xF000000
#define DFU_ALT_INFO_RAM 
                "dfu_ram_info=" 
        "setenv dfu_alt_info " 
	"bitstream_bit=system.bit"	
	"bitstream=system.bit"	
	"loadbit_addr=0x100000"	
	"mmc_loadbit=echo Loading bitstream from SD/MMC/eMMC to RAM.. && " 
		"mmcinfo && " 
		"load mmc 0 ${loadbit_addr} ${bitstream} && " 
		"fpga loadb 0 ${loadbit_addr} ${filesize}" 
        "image.ub ram $netstart 0x1e00000" 
        "dfu_ram=run dfu_ram_info && dfu 0 ram 0" 
        "thor_ram=run dfu_ram_info && thordown 0 ram 0"

#define DFU_ALT_INFO_MMC 
        "dfu_mmc_info=" 
        "set dfu_alt_info " 
        "${kernel_image} fat 0 1\\;" 
        "dfu_mmc=run dfu_mmc_info && dfu 0 mmc 0" 
        "thor_mmc=run dfu_mmc_info && thordown 0 mmc 0"


/*Required for uartless designs */
#ifndef CONFIG_BAUDRATE
#define CONFIG_BAUDRATE 115200
#ifdef CONFIG_DEBUG_UART
#undef CONFIG_DEBUG_UART
#endif
#endif

/*Define CONFIG_ZYNQ_EEPROM here and its necessaries in u-boot menuconfig if you had EEPROM memory. */
#ifdef CONFIG_ZYNQ_EEPROM
#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN         1
#define CONFIG_SYS_I2C_EEPROM_ADDR             0x54
#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS      4
#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS  5
#define CONFIG_SYS_EEPROM_SIZE                 1024 /* Bytes */
#define CONFIG_SYS_I2C_MUX_ADDR                0x74
#define CONFIG_SYS_I2C_MUX_EEPROM_SEL          0x4
#endif

#define CONFIG_BOOTCOMMAND	"run mmc_loadbit; run default_bootcmd"

主要做了几处修改

#define CONFIG_FPGA_ZYNQPL //开启uboot加载bit命令

增加加载bit命令,下面代码是从sd卡加载名字为system.bit文件名的bit文件,在uboot运行mmc_loadbit即可加载bit

"bitstream_bit=system.bit"	
	"bitstream=system.bit"	
	"loadbit_addr=0x100000"	
	"mmc_loadbit=echo Loading bitstream from SD/MMC/eMMC to RAM.. && " 
		"mmcinfo && " 
		"load mmc 0 ${loadbit_addr} ${bitstream} && " 
		"fpga loadb 0 ${loadbit_addr} ${filesize}" 

下面的是启动命令,在启动内核前先调研run mmc_loadbit加载bit后再运行default_bootcmd,这是加载内核进入系统的命令。

#define CONFIG_BOOTCOMMAND	"run mmc_loadbit; run default_bootcmd"

在另外一个文件platform-auto.h文件中可看到,具体原因不详说了,这涉及到uboot具体启动方式,不是一两句可以说清楚,有兴趣的朋友可以自己研究 platform-auto.h在目录zynq/project-spec/meta-plnx-generated/recipes-bsp/u-boot/configs下

第二步:重新编译

petalinux-build

第三步:重新生成BOOT.BIN文件

这里去掉了fpga的文件,打包后的文件不会包含bit 修改后

petalinux-package --boot --fsbl  --u-boot --force

未修改前

petalinux-package --boot --fsbl --fpga --u-boot --force

第四步:拷贝文件到sd卡

这里与之前多拷贝了system.bit文件,改文件是fpga的文件,可以从hdf中得到,也可以使用vivado生成的bit文件,两者是等价的。

三、启动系统

使用uboot加载bit

uboot界面,可使用mmc_loadbit命令进行加载bit

run mmc_loadbit

可看到成功加载界面

上电自动加载bit

由于配置好了上电加载bit,系统启动期间只要不打断,让他自动加载系统即可自动加载bit 或者在uboot命令行使用bootcmd进入系统

run bootcmd

总结

希望对大家有所帮助

经验分享 程序员 微信小程序 职场和发展