我们正在编译一个嵌入式C++应用程序,它部署在电离辐射轰击的环境中的屏蔽设备中。我们正在为ARM使用GCC和交叉编译。在部署时,我们的应用程序会生成一些错误的数据,并且比我们希望的更频繁地崩溃。硬件是为这个环境而设计的,我们的应用程序已经在这个平台上运行了几年。

我们是否可以对代码进行更改,或对编译时进行改进,以识别/纠正由单个事件扰乱导致的软错误和内存损坏?是否有其他开发人员成功地减少了软错误对长时间运行的应用程序的有害影响?


当前回答

既然您专门要求软件解决方案,而且您使用的是C++,为什么不使用运算符重载来创建自己的安全数据类型呢?例如:

不要使用uint32_t(以及double、int64_t等),而是制作自己的SAFE_uint32-t,其中包含uint32/t的倍数(最小值为3)。重载您想要执行的所有操作(*+-/<<>>==!=等),并使重载的操作对每个内部值独立执行,即不要执行一次并复制结果。在之前和之后,检查所有内部值是否匹配。如果值不匹配,可以将错误的值更新为最常见的值。如果没有最常见的值,您可以安全地通知存在错误。

这样,即使ALU、寄存器、RAM或总线上发生损坏也无所谓,您仍然可以多次尝试并很好地捕获错误。然而,请注意,这只适用于您可以替换的变量-例如,堆栈指针仍然是易受影响的。

附带故事:我遇到了一个类似的问题,也是在一个旧的ARM芯片上。结果发现,这是一个使用旧版本GCC的工具链,与我们使用的特定芯片一起,在某些边缘情况下触发了一个错误,这会(有时)破坏传递到函数中的值。在将设备归咎于无线电活动之前,确保设备没有任何问题,是的,有时是编译器错误=)

其他回答

你问的是一个非常复杂的话题——不容易回答。其他答案是可以的,但它们只涵盖了你需要做的所有事情的一小部分。

正如在评论中看到的,不可能100%解决硬件问题,但是使用各种技术很可能减少或解决这些问题。

如果我是你,我会创建最高安全完整性级别(SIL-4)的软件。获取IEC 61513文件(适用于核工业)并遵循该文件。

如何运行应用程序的许多实例。如果崩溃是由于随机的内存位变化造成的,那么你的一些应用程序实例很可能会通过并产生准确的结果。(对于有统计背景的人来说)很容易计算出在给定的比特翻转概率下需要多少个实例才能实现所希望的最小总体错误。

这里有大量的回复,但我将尝试总结我对此的想法。

某些东西崩溃或不正常工作可能是您自己的错误造成的,那么当您找到问题时,应该很容易解决。但也有可能出现硬件故障,如果不是不可能,整体上很难解决。

我建议首先尝试通过日志记录(堆栈、寄存器、函数调用)来捕捉问题情况——要么将它们记录到文件中的某个位置,要么以某种方式直接发送(“哦,不,我崩溃了”)。

从这种错误情况中恢复可以是重新启动(如果软件仍然处于活动状态)或硬件重置(例如硬件看门狗)。从第一个开始更容易。

若问题是硬件相关的,那个么日志记录应该可以帮助您确定在哪个函数调用中发生了问题,这可以让您了解什么是不工作的以及在哪里。

此外,如果代码相对复杂-“分割并征服”它是有意义的-这意味着你在怀疑问题所在的地方删除/禁用一些函数调用-通常禁用一半代码并启用另一半代码-你可以得到“确实有效”/“不有效”的决定,然后你可以专注于另一半代码。(问题所在)

若问题在一段时间后发生,那个么可以怀疑堆栈溢出,那个么最好监视堆栈点寄存器,若它们不断增长。

如果你设法完全最小化代码,直到“hello world”类型的应用程序出现故障,那么硬件问题是意料之中的,需要进行“硬件升级”,这意味着发明这样的cpu/ram/-能够更好地耐受辐射的硬件组合。

最重要的事情可能是,如果机器完全停止/重新设置/不工作,您如何取回日志-这可能是bootstap应该做的第一件事-如果有问题的情况被解决,您应该回家。

如果在您的环境中也可以发送信号和接收响应,那么您可以尝试构建某种在线远程调试环境,但您必须至少有通信媒体工作,并且某些处理器/某些ram处于工作状态。通过远程调试,我的意思是GDB/GDB存根类型的方法,或者您自己实现从应用程序中获取所需的内容(例如,下载日志文件、下载调用堆栈、下载ram、重新启动)

有人提到使用较慢的芯片来防止离子同样容易地翻转比特。以类似的方式,可能使用专门的cpu/ram,它实际上使用多个位来存储单个位。因此,提供了硬件容错,因为不太可能所有的位都被翻转。所以1=1111,但需要被击中4次才能真正翻转。(4可能是一个坏数字,因为如果2位被翻转,它就已经不明确了)。因此,如果您使用8,您得到的ram将减少8倍,访问时间也会慢一些,但数据表示更可靠。您可能可以在软件级别使用专门的编译器(为所有内容分配更多的空间)或语言实现(为以这种方式分配内容的数据结构编写包装器)来实现这一点。或具有相同逻辑结构但在固件中执行此操作的专用硬件。

你需要3台以上的从机,在辐射环境外有一台主机。所有I/O都通过包含表决和/或重试机制的主机。每个从设备必须有一个硬件监视器,并且撞击它们的调用应该被CRC等包围,以降低非自愿撞击的概率。转发应该由主机控制,因此与主机的连接丢失等于几秒钟内重新启动。

此解决方案的一个优点是,您可以对主机和从机使用相同的API,因此冗余成为一种透明的特性。

编辑:从评论中,我觉得有必要澄清“CRC的想法”。如果你用CRC来围绕碰撞,或者对来自主设备的随机数据进行摘要检查,那么从设备碰撞它自己的看门狗的可能性接近于零。只有当受监视的从设备与其他设备对齐时,才从主设备发送随机数据。随机数据和CRC/摘要在每次碰撞后立即清除。主从缓冲频率应超过看门狗超时的两倍。每次从主机发送的数据都是唯一生成的。