编译用于高放射性环境的应用程序

新手上路,请多包涵

我们正在编译一个嵌入式 C++ 应用程序,该应用程序部署在受 电离辐射 轰击的环境中的屏蔽设备中。我们正在为 ARM 使用 GCC 和交叉编译。部署后,我们的应用程序会生成一些错误数据,并且崩溃的频率超出了我们的预期。硬件是为这个环境设计的,我们的应用程序已经在这个平台上运行了好几年。

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

原文由 rook 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 422
2 个回答

从事 小型卫星 软件/固件开发和环境测试工作约4-5年*,我想在这里分享我的经验。

*( _小型卫星比大型卫星更容易发生单事件扰动,因为其电子元件的尺寸相对较小且有限_)

非常简洁和直接:没有机制可以通过软件/固件本身从 可检测到的错误情况 中恢复,而至少 没有 一份 软件/固件的 最低工作版本 副本 用于 恢复 目的 - 并且 _硬件支持恢复_(功能)。

现在,这种情况通常在硬件和软件层面都得到处理。在这里,应您的要求,我将分享我们在软件层面可以做些什么。

  1. ……恢复目的…… 提供在真实环境中更新/重新编译/重新刷新您的软件/固件的能力。对于高度电离环境中的任何软件/固件来说,这 几乎是必备的 功能。如果没有这个,您 可以 拥有任意数量的冗余软件/硬件,但在某一时刻,它们都会爆炸。所以,准备这个功能!

  2. …最低工作版本… 在您的代码中具有响应式、多副本、最低版本的软件/固件。这就像 Windows 中的安全模式。不要只拥有一个功能齐全的软件版本,而是拥有软件/固件最低版本的多个副本。最小副本的大小通常比完整副本小得多,并且几乎总是 只有 以下两个或三个特征:

    1. 能够听从外部系统的命令,
    2. 能够更新当前的软件/固件,
    3. 能够监控基本操作的内务数据。
  3. …复制…某处… 在某处有冗余软件/固件。

    1. 无论 有没有冗余硬件,您都可以尝试在 ARM uC 中安装冗余软件/固件。这通常是通过 在不同的地址 中拥有两个或多个相同的软件/固件来完成的,这些软件/固件相互发送心跳 - 但一次只有一个处于活动状态。如果已知一个或多个软件/固件无响应,请切换到其他软件/固件。使用这种方法的好处是我们可以在发生错误后立即进行功能更换 - 无需与负责检测和修复错误的任何外部系统/方有任何联系(在卫星情况下,通常是任务控制中心( MCC))。

    严格来说,如果没有冗余硬件,这样做的缺点是您实际上 无法 消除 所有 单点故障。至少,您仍然会遇到 一个 单点故障,即 _开关本身_(或者通常是代码的开头)。尽管如此,对于在高度电离环境中受尺寸限制的设备(例如微微/毫微微卫星),在 没有 额外硬件的情况下将单点故障减少到一个点仍然值得考虑。此外,用于切换的一段代码肯定会比整个程序的代码少得多——显着降低了其中出现单事件的风险。

    1. 但是,如果您不这样做,您的外部系统中应该至少有一个副本,它可以与设备联系并更新软件/固件(在卫星情况下,它又是任务控制中心)。

    2. 您还可以将副本保存在设备的永久内存存储中,可以触发该副本以恢复正在运行的系统的软件/固件

  4. …可检测的错误情况。 错误必须是 可检测 的,通常由硬件 纠错/检测电路 或一小段代码进行纠错/检测。最好将此类代码小而多,并 独立 于主要软件/固件。它的主要任务 只是 检查/纠正。如果硬件电路/固件是 _可靠的_(例如它比其余的更耐辐射 - 或具有多个电路/逻辑),那么您可能会考虑使用它进行纠错。但如果不是,最好将其作为错误检测。可以通过外部系统/设备进行校正。对于纠错,您可以考虑使用 Hamming/Golay23 等基本纠错算法,因为它们可以更容易地在电路/软件中实现。但这最终取决于您团队的能力。对于错误检测,通常使用 CRC。

  5. …支持恢复的硬件 现在,谈到这个问题上最困难的方面。最终,恢复需要负责恢复的硬件 至少 可以正常工作。如果硬件永久损坏(通常在其 总电离剂量 达到一定水平后发生),那么(遗憾地)软件无法帮助恢复。因此,对于暴露在高辐射水平的设备(例如卫星)来说,硬件无疑是最重要的问题。

除了上述由于单事件扰动而导致固件错误的建议之外,我还建议您:

  1. 子系统间通信协议中的错误检测和/或纠错算法。为了避免从其他系统收到不完整/错误的信号,这是另一个几乎必须具备的

  2. 过滤您的 ADC 读数。 不要 直接使用 ADC 读数。通过中值过滤器、均值过滤器或任何其他过滤器对其进行过滤 - 永远不要 相信单个读数值。采样更多,而不是更少 - 合理。

原文由 Ian 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 循环调度程序。这使您能够添加定期维护时间以检查关键数据的正确性。最常遇到的问题是堆栈损坏。如果您的软件是循环的,您可以在循环之间重新初始化堆栈。不要为中断调用重复使用堆栈,为每个重要的中断调用设置一个单独的堆栈。

与看门狗概念类似的是截止时间计时器。在调用函数之前启动硬件计时器。如果函数在截止时间计时器中断之前没有返回,则重新加载堆栈并重试。如果在 35 次尝试后仍然失败,则需要从 ROM 重新加载。

将您的软件拆分为多个部分并隔离这些部分以使用单独的内存区域和执行时间(尤其是在控制环境中)。示例:信号采集、预处理数据、主要算法和结果实现/传输。这意味着一个部分的失败不会导致程序的其余部分失败。因此,当我们修复信号采集时,其余任务继续处理陈旧的数据。

一切都需要CRC。如果您在 RAM 之外执行,即使您的 .text 也需要 CRC。如果您使用循环调度程序,请定期检查 CRC。一些编译器(不是 GCC)可以为每个部分生成 CRC,并且一些处理器有专门的硬件来进行 CRC 计算,但我想这会超出你的问题范围。检查 CRC 还会提示内存上的 ECC 控制器在单个位错误成为问题之前对其进行修复。

使用看门狗进行启动不仅仅是一次操作。如果您的启动遇到问题,您需要硬件帮助。

原文由 Gerhard 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题