使用FILL改善代码完整性

开发人员喜欢相信运行其软件的微处理器将忠实地遵循他们创建并无限期运行的程序流程。事实是,有时情况会出错,程序会运行到杂草中。造成这种情况的原因有很多,例如覆盖数组的边界,在初始化之前使用指针或其他许多可能的原因。在发生这种情况时,恢复系统最有用的技术之一就是用一些会引起故障的东西填充未使用的内存。

可用的内存可以填充的可能性有很多。第一个是复位向量的位置。万一发生故障,CPU将加载复位向量,程序将从第二个平方开始。这将更多地是应用程序的软性和不受控制的终止,几乎没有甚至没有关于原因的调试信息。硬件将处于不确定状态,无法保证系统不会从重置中正确恢复。

第二种,可能是更适当的行为是将已知的中断向量放置在空存储器中。在这种情况下,如果发生严重错误,应用程序将有机会捕获事件并提供一些线索,例如有关发生情况的CPU寄存器状态。然后,这使开发人员可以重现和调试原因,而不必盲目猜测。

如果不希望使用调试信息,则可以使用的第三个选项是使用HALT或分支到自身的指令填充内存。这将导致微控制器停止运行。这种技术的优点是它可以防止微控制器运行并继续错误地执行代码。相反,一切都停止了,每个开发人员都启用了(我希望)可信赖的看门狗计时器,该计时器通过超时并执行系统硬重置来解救。

确实不建议使用的最后一个选择是用乱码填充内存。选择一种位模式,例如0x55、0xAA,0xAA55,只是希望获得最好的效果。在这种情况下,内存的填充并不能真正提高应用程序的健壮性,而是最有可能提供除0xFF之外的已知值,以便可以执行ROM校验和。简短地搜索Internet就会发现一些聪明的位模式,例如0xDEADC0DE,0xDEADBEEF等。

现在,有许多种方法可以用特定的位模式填充内存。它们大体分为两类:基于IDE或链接器。在IDE实施中,“填充内存”选项可以隐藏在属性菜单的深处。根据IDE和工具链的不同,可能还有其他选项可以设置特定的模式,也可以由工具自行决定。大多数的IDE工具时,选择该选项为“填充内存”需要开发者选择将被填充的内存范围。反过来,这迫使开发人员继续监视应用程序结尾在链接器的.text部分中的位置。

基于链接器的方法使开发人员能够以更高的灵活性自定义填充解决方案。例如,使用GNU工具链可以创建一个包含FILL()链接器命令的新节输出。此命令传递了应该用于填充内存的位模式。从此内存部分,ORIGIN和LENGTH函数可用于获取将要填充的内存部分的大小。允许内存空间自动用位模式填充,而无需开发人员管理。图1中显示了一个名为.m的.text节的GNU链接器的fill节的示例。

.fillsection:

{

填充(0xAA55AA55);

。 =来源(m_text)+长度(m_text)– 1;

字节(0xAA)

} > m_text

图1 –使用GNU的示例链接器文件部分

空内存的结果是,在查看编译时生成的内存文件时,请求的位模式将填充内存:

十六进制内存填充
十六进制内存填充

图2 – S记录的位模式

使用链接器文件的优点之一是,您可以将项目配置为在填充内存的链接器和不填充内存的链接器之间切换。使用内存填充的缺点之一是每个内存位置都被写入。这意味着,如果您要调试应用程序,则每次更改代码时,都必须等待所有Flash写入,即使该应用程序不受影响。这会在实施阶段增加大量时间。因此,应该在开始时就将内存填充设置为代码承诺的一部分,但仍应提供启用和禁用它以进行调试的功能。请记住,开发人员希望尽可能多地使用此内存填充来捕获任何意外行为。

用中断向量或暂停命令正确地执行FILL命令可以提高软件系统的完整性。如果出现错误的指针,单事件翻转或其他问题,导致应用程序从意外的内存位置开始执行代码,则填充位模式可以将程序执行导回到已知的位置,在该位置可以恢复适当的错误处理过程系统。每个IDE和MCU的实现此功能的方式略有不同,但通常不比查看链接器数据表中有关如何使用FILL命令的复杂得多。

发表评论

您的电子邮件地址不会被公开。 必需的地方已做标记 *

该网站使用Akismet减少垃圾邮件。 了解如何处理您的评论数据.