处理MultiBoot升级半程掉电的原理和最基本方法

作者:Ivy Guo,AMD工程师;来源:AMD开发者社区

之前在《一个思路: 缩短MultiBoot流程中的回跳 (Fallback) 时间》中,提到过FPGA无法处理升级Image过程中半程掉电的情形。但是仍然陆续有客户咨询这个问题。这次再稍微深入讨论一下。

仍以UltraScale系列为例,参考UG570的Table 55:Sample KU040 Bitstream

https://docs.amd.com/r/en-US/ug570-ultrascale-configuration?tocId=__uoAGvOd16yWRXoFejPDQ

1.png

2.png

可以看到,FPGA的配置文件是数据中穿插着不同指令。对于Versal系列以前的FPGA来说,这些指令的顺序也几乎是固定的,不同family之间的指令字略有差异。

配置FPGA时,内部配置控制器要求外部配置源按照顺序发送这些指令和数据。比如接收到了Write TIMER register的3002 2001指令,那么下面接跟着必须是TIMER寄存器的值。此时如果你发送了一个错误数据,TIMER寄存器就会把这个错误数据写入内存。

对于TIMER这种寄存器来说,没有太大的危害,只是会时间设置错误。但是如果是配置寄存器COR0,COR1之类,那就把FPGA配置成其他行为模式了,根据应用场景有时会造成严重后果。

3.JPG

这也是我们严禁手动修改bit文件的原因之一。

假设FPGA已经正确接收了一个指令字,比如TIMER写指令,由于配置控制器其实是一个状态机,那么它此时进入等待TIMER的具体数值写入的状态了。如果迟迟没有数据进入,控制器就会在此不停循环,而不会跳过去接收处理下一个指令字 ——这是FPGA ‘Non-Continuous SelectMAP Data Loading’  (UG570, Ch. 5)工作的基础。也因为如此,如果MultiBoot Image升级过程中半程掉电的话,FPGA就会挂死在某个等待状态无法回跳,只能复位解决问题。

另一个知识点,bitstream中的同步字AA99 5566是配置开始的标志,位于有效数据最开始的位置。配置控制器不看到这个同步字,它永远不会进行下一步动作。哪怕送来的是正确的其他指令字和对应数据,也会被它全部忽略掉。

基于上述两点讨论,我们给客户的“升级掉电场景“处理的最多的建议就是升级文件倒着写。进一步看,这个方法的关键点其实是升级的最后一步才写入同步字AA 99 55 66。所以升级过程也可以先跳过同步字位置空着不写,仍然顺序写入bitstream的内容,全部写好后,最后一步跳回来把同步字补上。

这样如果半程掉电,文件不管丢失前半部分还是后半部分都没有关系。没有同步字,配置控制器不会去读这些数据,也就不存在给指令字写入了错误数据,或者缺失指令对应数据而循环等待的场景了。配置控制器不会挂死,golden或者header里面的原来的timer仍然生效,在其时间耗尽而未找到同步字(意味着没找到新的image)情况下,回跳会正确发生。