国产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即可。

相关推荐
4SAPI1 分钟前
多模型API调用实战:一个项目接入GPT、Claude和DeepSeek
linux·人工智能·gpt·php
Escalating_xu10 分钟前
【Linux 网络编程】UDP Socket 编程(下):回调封装、网络字典与多线程聊天室
linux·网络·udp
看-是灰机10 分钟前
Milvus向量数据库
linux·运维·人工智能·机器学习·milvus
下辈子不要当码农13 分钟前
Linux驱动学习(1)
linux·运维·学习
HelloWorld工程师13 分钟前
不改动任何历史配置,也能让 SSL 证书自动续期
linux·服务器·网络协议·https·ssl
啦啦啦啦啦zzzz16 分钟前
分布式存储----缓存组
linux·服务器·c++·分布式·缓存
水饺编程1 小时前
第2章:Linux 基础,whoami 命令
linux·c语言·汇编
鱼很腾apoc1 小时前
【MySQL】 第2期 查询与函数系统详解:从基础 CRUD 到复合多表查询
linux·数据库·学习·mysql·dml
IMPYLH1 小时前
Linux 运维基础:从入门到实战的完整指南
linux·运维·php
Lsetea1 小时前
curl走HTTPS代理报SSL证书错误:proxy-cacert与cacert双层信任排查
linux·https·ssl证书·curl·代理服务器