国产ZYNQ multiboot功能介绍与实现

1、背景介绍

当前因为国产化的需要,项目中几乎都用国产芯片,但国产芯片有时候不太稳定,就拿国产flash芯片来说,小概率会出现flash内存储的数据发生异常,导致系统无法启动。在这种背景下,引入了国产zynq的multiboot功能。

2、multiboot描述

下面是国产ZYNQ厂家自己的介绍

在FPGA实际开发过程中,我们一般都有升级系统程序的需求。一般我们用下载器下载就行了,可是,这个在实验室还好说,如果在正式产品中比如已经装机了,可能插下载器就不是那么方便了,于是产生了"在线升级"的需求。由于在线升级是靠程序做的,那么有可能在升级过程中出现意外导致升级失败,这样程序就自己把自己给弄死了,也就是我们经常听到的变砖了。出现这种情况咋办?如果不做保护措施,那就只能开盖用下载器烧程序了。

为了解决上述问题,于是multiboot 出现了,字面意思就是多重引导。就是用冗余的方式来保证在线升级的可靠性。 多重引导,就是在flash 中放两个或多个版本,一般放两个就行了,我们一般称呼这个两个版本:一个叫golden版本,一个叫update版本。golden 版本我们一般就只在生产时烧写一次,后面都不动这个版本了,所以出错的概率相对就低了。我们要更新功能时,就不断更新update 即可,如果 update 更新失败了, golden就是拿来救命的,从而保证不变砖。

从上面介绍能看到,这个multiboot主要是针对后面更新来用的,但其实针对flash异常情况也是可以用的,因为存放了多个版本,如果flash中某段数据异常了,存放在其中的这个版本自然无法使用,于是可以从另一个版本加载,这样就有了双保险。

3、启动过程描述

国产zynq启动这块和进口xilinx zynq一样(进口zynq启动过程),首先也是启动Bootrom,但是这里Bootrom已经自带了一个跳转功能,机制是这样的(进口xilinx的zynq也有该功能)。

如图所示,启动过程中国产ZYNQ会自动按照32K地址递增的方式去找寻正确的BOOT.bin,那么可以在flash中32K地址对齐的地方,烧写两个版本 BOOT.bin 即可实现多版本加载。

4、操作步骤

首先根据flash容量制定好空间划分情况,两个版本的boot.bin偏移要为32K的整数倍,比如下面这个例子

flash_total:0x2000000

uboot.bin_size:4.6MB ( 实际预留 0x500000 Byte)

image.ub_size :10.1MB( 实际预留 0xaf0000 Byte)

|-------------|-----------|-----------|--------------------------------------------------------------------------------------|
| 名称 | Start | End | 说明 |
| uboot.bin_1 | 0x000000 | 0x500000 | |
| uboot.bin_2 | 0x500000 | 0xA00000 | |
| Image校验值 | 0xA00000 | 0xA10000 | 0xA01000为起始地址写四个字节的image.ub_1的CRC32校验值 如果存放的校验值与image.ub_1计算出的校验值不一致,则直接启动image.ub_2 |
| image.ub_1 | 0xA10000 | 0x1500000 | |
| image.ub_2 | 0x1500000 | 0x1FF0000 | |
| 环境变量 | 0x1FF0000 | 0x2000000 | 预留1*64KB 环境变量 |

上面例子中flash总容量是32MB,Bootrom搜寻范围只能是前16MB,于是这里将uboot.bin和image.ub分开来了,两个uboot.bin存放在前16MB。

同时由于uboot.bin和image.ub分开存放,除了针对uboot.bin能够进行multiboot,针对image.ub也可以进行multiboot, 即将image.ub也保存两份,第一份计算出校验值存放在一个地方,如果校验值与第一份不匹配才加载第二份image.ub。流程图如下:

Uboot中配置的环境变量如下:

bash 复制代码
"spiboot=echo Copying FIT from SPI flash to RAM... && " \
	"sf probe && sf read 0x2000000 0xA10000 0xaf0000 && crc32 0x2000000 0xaf0000 0x3000000 && sf read 0x3100000 0xA01000 4 && " \
	"if cmp.b 0x3000000 0x3100000 4;then echo compare correct...;else echo compare incorrect!!! && sf probe && sf read 0x2000000 0x1500000 0xaf0000;fi && " \
	"bootm 0x2000000\0" \

第一次烧写只能用下载器烧写,制作镜像采用下面工具

在step4 Add中添加fsbl bit uboot.elf的校验值 chechsum选择sha2

注:如果checksum为none,则Bootrom不会进行校验

后面只要uboot能够启动,都可以在uboot下面操作。

第1步:擦除flash

bash 复制代码
sf probe && sf erase 0 0x2000000

第2步:按照上面表格往指定地址写入uboot.bin和image.ub

注:flash首次烧写还是用jtag,后面如果有uboot就可以不用jtag了。

第3步:重启

第4步:crc32 校验指定位置

第1处:

bash 复制代码
sf probe && sf read 0x2000000 0xA10000 0xaf0000 && crc32 0x2000000 0xaf0000

第2处:

bash 复制代码
sf probe && sf read 0x2000000 0x1500000 0xaf0000 && crc32 0x2000000 0xaf0000

第5步:对比两次的校验值

第6步:将校验值写入 0xA01000 地址,写入4Byte

bash 复制代码
sf probe && sf read 0x2000000 0xA10000 0xaf0000 && crc32 0x2000000 0xaf0000 0x3000000 && md.b 0x3000000 4 && sf probe && sf update 0x3000000 0xA01000 4

第7步:将flash数据读到内存,并读出内存数据,确认是否写入crc32校验值正确

bash 复制代码
sf probe && sf read 0x3100000 0xA01000 4 && md.b 0x3100000 4

第8步:比较计算出的和写入flash的数据是否相同

bash 复制代码
sf probe && sf read 0x2000000 0xA10000 0xaf0000 && crc32 0x2000000 0xaf0000 0x3000000 && sf probe && sf read 0x3100000 0xA01000 4 && if cmp.b 0x3000000 0x3100000 4;then echo compare correct...;else echo compare incorrect!!!;fi

备注:

1、擦除image.ub的CRC32校验值:

bash 复制代码
sf probe && sf erase 0xA01000 0x1000

2、擦除完读出确认是否擦除成功:

bash 复制代码
sf probe && sf read 0x3000000 0xA01000 0x10 && md.b 0x3000000 0x10

说明:上面例子中因为flash容量够大,因此实现了uboot和image各存放两份。当然,也可以uboot保存两份,image只保留一份。或者将uboot和image.ub打包在一起组成一个完整的启动镜像boot.bin,然后针对这个完整的boot.bin存放两份。总之,只要确保存放引导文件的起始位置在FLASH的前16MB即可。

相关推荐
戴为沐20 小时前
Linux内存扩容指南
linux
zylyehuo1 天前
Linux 彻底且安全地删除文件
linux
用户805533698032 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297912 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
Web3探索者4 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
zylyehuo4 天前
Linux系统中网线与USB网络共享冲突
linux
Sokach10155 天前
Linux Shell 脚本从零到能用:一个新手的一天学习总结
linux
AlfredZhao5 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone
zzzzzz3107 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode7 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏