为高放射性环境编译应用程序
为高放射性环境编译应用程序
技术背景
在高放射性环境中,如微型卫星等,电子组件容易受到单粒子翻转(SEU)的影响,导致软件和固件出现错误。为了确保应用程序在这种环境下的可靠性,需要从软件层面采取一系列措施来检测和恢复错误。
实现步骤
1. 提供实时更新/重新编译/刷新功能
在高电离环境中,软件和固件应具备实时更新、重新编译和刷新的能力,以应对可能出现的错误。
2. 准备最小工作版本的副本
在代码中准备多个响应式的最小版本软件/固件副本,类似于 Windows 的安全模式。这些最小版本通常只具备监听外部系统命令、更新当前软件/固件以及监控基本操作的内务数据等功能。
3. 准备冗余软件/固件
- 在 ARM uC 中准备冗余软件/固件,可将两个或多个相同的软件/固件放置在不同地址,并相互发送心跳信号,一次仅激活一个。若某个软件/固件无响应,则切换到其他副本。
- 在外部系统(如卫星的任务控制中心)中至少保留一个副本,以便与设备通信并更新软件/固件。
- 在设备的永久内存存储中保留副本,可触发其恢复运行系统的软件/固件。
4. 检测错误情况
错误必须能够被检测到,通常通过硬件的错误纠正/检测电路或一小段用于错误纠正/检测的代码实现。建议将此类代码编写得小而独立于主软件/固件,主要任务仅为检查/纠正。对于硬件电路/固件可靠的情况,可考虑进行错误纠正;否则,仅进行错误检测,由外部系统/设备进行纠正。
5. 确保硬件支持恢复
恢复操作最终依赖于负责恢复的硬件正常工作。若硬件永久损坏(通常在达到总电离剂量阈值后),软件将无法进行恢复。因此,对于高辐射环境下的设备,硬件的可靠性至关重要。
核心代码
安全激活代码示例
1 |
|
自定义安全数据类型示例
1 |
|
最佳实践
1. 采用冗余硬件
使用 2 个或更多相同的硬件设置和代码。若结果不同,则触发重置。使用 3 个或更多设备时,可采用“投票”系统识别出现问题的设备。
2. 优化编译器设置
避免使用复杂的编译器设置,以免引入更多未测试的代码路径。可使用一些编译器选项来增强代码的安全性,如 -mmitigate-rop
、-fstack-protector-all
、-D_FORTIFY_SOURCE=2
、-Wl,-z,relro,-z,now
和 -Wl,-z,noexecstack
等。
3. 测试和验证
使用自动化单元测试,在开发系统和目标系统上运行相同的测试用例,查找差异。检查嵌入式设备的勘误表,确保代码没有因硬件问题而崩溃。
4. 采用循环调度器
使用循环调度器,定期检查关键数据的正确性。对于周期性软件,可在周期之间重新初始化堆栈,避免使用中断调用的堆栈。
5. 应用 CRC 校验
对所有内容(包括执行代码)应用循环冗余校验(CRC),定期检查 CRC 值,促使内存的 ECC 控制器修复单比特错误。
6. 使用看门狗
在启动和运行过程中使用硬件看门狗,确保系统在出现问题时能够重启。
常见问题
1. 如何处理多个比特错误?
大多数 ECC 内存只能恢复单比特错误,因此应确保内存扫描频率足够高,以减少多比特错误的发生。
2. 如何确保代码的可靠性?
避免依赖编译器的默认优化设置,禁用可能导致问题的 C++ 特性(如异常、模板、iostream 等)。使用汇编语言编写关键代码,确保对寄存器和内存的精确控制。
3. 如何应对硬件故障?
若硬件故障无法避免,可使用冗余硬件和数据备份,确保在硬件故障时能够快速恢复。同时,通过日志记录和远程调试,定位和解决硬件问题。
4. 如何平衡性能和容错性?
采用冗余和错误纠正机制会增加处理时间和资源消耗,因此需要在性能和容错性之间进行权衡。可根据具体应用场景和需求,选择合适的容错技术。