提问者:小点点

在高放射性环境中使用的应用程序的汇编


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

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


共3个答案

匿名用户

在小型化卫星的软件/固件开发和环境测试方面工作了大约4-5年*,我想在此分享我的经验。

*(小型化卫星比大型卫星更容易发生单粒子故障,因为它的电子元件相对较小,尺寸有限)

简明扼要地说:如果软件/固件本身没有至少一个用于恢复目的的软件/固件最低工作版本的副本,并且硬件支持恢复(功能),就没有任何机制可以从可检测的错误情况中恢复。

现在,这种情况通常在硬件和软件两个层次上处理。在这里,按照你的要求,我将分享我们在软件层面可以做些什么。

>

  • .。。恢复用途。。。。提供在真实环境中更新/重新编译/重放你的软件/固件的能力。对于在高电离环境中的任何软件/固件来说,这几乎是一个必须具备的特性。如果没有这个,你可以有你想要的多余的软件/硬件,但是在某一点上,它们都将被炸毁。所以,准备好这个特性吧!

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

    1. 能够监听来自外部系统的命令,
    2. 能够更新当前软件/固件,
    3. 能够监控基本操作的内务管理数据。

    收到。某处。。。有多余的软件/固件。

    >

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

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

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

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

    。。。支持恢复的硬件现在,来到了这个问题上最困难的方面。最终,恢复要求负责恢复的硬件至少能够正常工作。如果硬件永久损坏(通常发生在其总电离剂量达到一定水平之后),那么(可悲的是)软件没有办法帮助恢复。因此,对于暴露在高辐射水平下的设备(如卫星)来说,硬件无疑是最重要的关注点。

    除了上面的建议,预计固件错误由于单件翻转,我还想建议您有:

    >

  • 子系统间通信协议中的错误检测和/或错误校正算法。这是为了避免从其它系统接收到的不完整/错误信号而几乎必须具有的另一个

    ADC读数中的滤波器。请勿直接使用ADC读数。通过中值滤波器,均值滤波器或任何其他滤波器对其进行过滤--永远不要信任单个读取值。合理地多采样,而不是少采样。

  • 匿名用户

    NASA有一篇关于抗辐射软件的论文。它描述了三项主要任务:

    1. 定期监视内存中的错误,然后清除这些错误,
    2. 健壮的错误恢复机制,和
    3. 在某些东西不再工作时重新配置的功能。

    请注意,存储器扫描速率应足够频繁,以便很少发生多位错误,因为大多数ECC存储器可以从单位错误中恢复,而不是从多位错误中恢复。

    健壮的错误恢复包括控制流传输(通常在错误发生之前的某个点重新启动进程),资源释放和数据恢复。

    他们对于数据恢复的主要建议是通过将中间数据视为临时数据来避免对数据恢复的需要,这样在错误发生之前重新启动也会将数据回滚到可靠的状态。这听起来类似于数据库中的“事务”概念。

    它们讨论了特别适用于面向对象语言(如C++)的技术。例如

    1. 用于连续内存对象的基于软件的ECC
    2. 按约定编程:验证前置条件和后置条件,然后检查对象以验证其是否仍处于有效状态。

    而且,恰巧,NASA已经将C++用于诸如火星漫游者之类的重大项目。

    C++类抽象和封装支持多个项目和开发人员之间的快速开发和测试。

    他们避免了某些可能产生问题的C++特性:

    1. 例外
    2. 模板
    3. IOStream(无控制台)
    4. 多重继承
    5. 运算符重载(除newdelete)
    6. 动态分配(使用专用内存池和放置new以避免系统堆损坏的可能性)。

    匿名用户

    下面是一些想法和想法:

    更有创造性地使用ROM。

    在ROM中存储任何可以存储的内容。不是计算东西,而是在ROM中存储查找表。(确保您的编译器正在将查找表输出到只读部分!在运行时打印出内存地址以进行检查!)将您的中断向量表存储在ROM中。当然,运行一些测试,看看您的ROM与RAM相比有多可靠。

    将您最好的RAM用于堆栈。

    堆栈中的SEU可能是最有可能的崩溃源,因为它通常是索引变量,状态变量,返回地址和各种类型的指针之类的东西所在的地方。

    实现定时器节拍和看门狗定时器例程。

    您可以运行一个“健全检查”例程,每一个计时器滴答,以及一个看门狗例程处理系统锁定。您的主代码还可以定期递增一个计数器来指示进度,而健全性检查例程可以确保这已经发生。

    在软件中实现纠错码。

    您可以向数据添加冗余,以便能够检测和/或纠正错误。这会增加处理时间,潜在地使处理器暴露在辐射中的时间更长,从而增加出错的机会,因此您必须考虑权衡。

    记住那些藏匿处。

    检查CPU缓存的大小。您最近访问或修改的数据可能会在缓存中。我相信您至少可以禁用一些缓存(以很大的性能代价);您应该尝试这样做,看看缓存对SEU的敏感性有多大。如果缓存比RAM更坚硬,那么您可以定期读取和重写关键数据,以确保它留在缓存中,并使RAM恢复正常。

    巧妙地使用页面错误处理程序。

    如果您将一个内存页标记为不存在,那么当您试图访问它时,CPU将发出一个页面错误。您可以创建一个页面错误处理程序,该处理程序在为读取请求提供服务之前进行一些检查。(PC操作系统使用它透明地加载已交换到磁盘的页面。)

    对关键的事情(可能是一切)使用汇编语言。

    使用汇编语言,您知道寄存器中的内容和RAM中的内容;您知道CPU正在使用什么特殊的RAM表,并且您可以以迂回的方式设计事物以降低风险。

    使用objdump实际查看生成的汇编语言,并计算每个例程占用多少代码。

    如果您使用的是像Linux这样的大操作系统,那么您就是在自找麻烦;有太多的复杂性和太多的事情要出错。

    记住这是一个概率游戏。

    一位评论者说

    您为捕获错误而编写的每个例程都会由于相同的原因而失败。

    虽然这是真的,但是在检查例程正常工作所需的(比如说)100字节的代码和数据中发生错误的几率要比其他地方发生错误的几率小得多。如果您的ROM非常可靠,几乎所有的代码/数据都在ROM中,那么您的胜算就更大了。

    使用冗余硬件。

    使用2个或更多具有相同代码的相同硬件设置。如果结果不同,则应触发复位。对于3个或更多的设备,您可以使用一个“投票”系统来尝试识别哪个设备已经被破坏。