本文来自AMD XILINX工程师 Ivy Guo。
MultiBoot 是 FPGA 远程更新配置文件时一种非常普遍的应用--为了确保安全,我们通常需要安排一个 Golden Image,升级失败后 FPGA 能回跳 (Fallback) 到此配置,从而使 FPGA 始终处于可被检测的工作状态。
很多客户有同样的问题:我在升级 Update Image 一半时突然掉电了,为什么回跳机制不起作用了呢?FPGA 怎么挂死了呢?其实这个现象是"符合预期"的,回跳机制不能应付这种异常。如果配置文件写到一半突然中断,嵌在配置数据流里面的指令序列同样也没有了,并且有可能中断在任意位置。FPGA 的控制逻辑此时就失去了工作方向,不知道下一步该做什么。
Xapp1247, Appendix A提供了一个很好的解决方案。利用两个 timer 或者称之为 barrier 的小image,嵌在 Golden 和 Update 之间或附在 Update 之后,通过合理的给两个 timer 赋值,可以解决 Update Image 刷新时同步字丢失或者半程掉电的情况。
但是同时又有客户提出了问题:我的应用对回跳时间要求很高,Xapp1247,Appendix A的方案对于半程掉电的场景,只有搜索完整个 Update Image 区域,看到 Timer#2 的设置才能完成回跳。有没有办法缩短这段时间呢?
MultiBoot 的跳转实际上是非常灵活的,我们这里就尝试提供一种思路:
1. 去掉 Timer#2,只保留 Timer#1 作为 Golden 和 Update Image 之间的 barrier Image。
2. Update Image采取从后往前倒着烧录的办法。(在实际应用中,烧写 flash 都是用CPU/MCU/FPGA 控制或者第三方编程器实现的,所以这一点也很容易实现)。
3. 精确设定 Timer#1的值,使其看到Update中的TIMER指令及赋值但不需更多。
工作原理
Timer 寄存器的值只有在 Power-Cycle 或者 PROG_B 过程中才能被清除,或者被新的 Timer值覆盖,或者在整个配置数据加载完毕后自动失效。
我们通过精确设定 Timer#1的值,使 FPGA 控制逻辑有足够时间看到 Update Image 中新的Timer 值。TIMER 指令位于 Image 的头部。因为 Update Image 是倒着写入的,能看到新的Timer 值,说明 Update Image 基本已经更新好了。由于新的 timer 值是足够控制逻辑加载完整的配置数据的,Timer 寄存器被新值更新后,Timer#1 相当于失效了。FPGA 有充足时间可以顺利读入完整配置数据,开启正常工作。
如果由于断电等原因,Update 更新到一半就停止了,此时会缺失 Update 的同步字,TIMER指令等等位于头部的信息。Timer#1 在一个有限的时间内搜索 Update Timer 但是没有看到,timeout 之后就会直接触发回跳。因此不用等待搜索整个 Update 存储空间完毕,依靠尾部的Timer#2 才能触发回跳了。
整个解决方案的重点就在于设定 Timer#1 的值。
这个其实很简单,根据你自己生成的 Timer#1和Update的MCS文件 (方法参考Xapp1247),计算一下 Timer#1 的指令到 Update 的 TIMER 之间的字节数即可。
以 KU040 的 bit 为例,观察 Update Image 头部的命令/数据序列,可以看到有 3002 2001,这就是设置 Timer 寄存器的命令TIMER。我们想Timer#1的时间足够看到 Update 中的3002 2001命令以及赋值,其他不需要了,随意添加几个 cycle 或者几个字的裕量即可。
比如我们设到3000 8001,多3个字的余量。
Timer的格式如下:
Barrier/Timer#1 里从 TIMER 及赋值开始,后面有两个 NOOP 字,加上后续 Update 里从FFFFFFFF 开始直到 3000 8001 有28个字,一共30个字,那么就是30*32=960 bit。SPIx1 串行配置中,一个 CCLK 读取一个 bit,所以
Timer#1 的值设置为 h‘3C0.
如上图,30 03 E0 01是把 bus width 从默认的 x1 切到 x4 的命令。如果在读入 Timer#1 之前中执行了该命令(比如 Golden 里面),那么 Timer#1 的值需要按照一个 CCLK cycle,读取4个 bit 来计算。和 Timer 命令类似,在 FPGA 控制逻辑读取数据的过程中,如果没有碰到新的30 03 E0 01设定新的数据宽度,那么将一直按照之前设定的 bus width 来读入数据或者指令。
假设 Timer#1 以及 Update 都是以x4读取的,那么 Timer#1 需设为 h’F0.
综上,通过合理设定 barrier#1 中的 Timer#1 数值,我们可以极大地缩短升级掉电这种MultiBoot 失效场景的回跳时间。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !