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

相关推荐
脆皮炸鸡7552 小时前
进程通信----命名管道
linux·经验分享·笔记·算法·学习方法
Mapleay2 小时前
FE-BE 动态路机制之 DPCM 与 DAPM 协作
linux
IT大白鼠2 小时前
Linux故障分析与排查:系统日志、启动故障与文件系统修复
linux·运维·服务器
老詹图解IT3 小时前
统信 UOS 登录界面转圈闪退/卡登录等常见原因及处理
linux·服务器·网络
闫记康3 小时前
Linux学习笔记day1
linux·笔记·学习
轻颂呀3 小时前
进程间关系和守护进程
linux·网络
sbjdhjd3 小时前
02 (中)| K8s Pod 生产化落地:从配置到优化全流程
linux·运维·云原生·kubernetes·开源·podman·kubelet
皓月盈江3 小时前
Linux Ubuntu系统如何编辑Docker容器内的文件
linux·ubuntu·docker·容器·靶场·vulhub·编辑docker内文件
jingyu飞鸟3 小时前
linux系统二进制安装MySQL 8.4、8.0版本数据库,配置crontab和xtrabackup数据库热备份脚本
linux·数据库·mysql