在嵌入式系统上工作时有两种情况。 嵌入式系统具有有限的资源,例如具有12 K闪存的ARM Cortex M0微控制器。
案例1: Bootloader和固件的常用功能/模块用法: Bootloader和Firmware可能需要使用相同的模块和功能来防止代码重复。否则,相同的代码将包括固件和Bootloader两次。 我们可以通过指定函数地址来防止这种情况,并通过地址调用函数来调用此函数。这是解决方案之一。
是否有提供常用功能的智能方法?
案例2: 有时,我们需要升级固件。引导加载程序的任务之一是固件升级。我们可以通过覆盖旧的固件来轻松升级固件。
正如我们所见,两个案例可以分开实施。但是当我们合并它们时,会出现一些问题。
问题: Bootloader通常是静态对象,但可以修改固件。因此,常用功能通常位于Bootloaders。但是当我们需要更新通用模块/功能时,我们该怎么办?
什么是通用或智能方法哪种引导加载程序,固件结构化嵌入式系统?另外,资源有限。
对于离散的通用模块/功能,一个或多个其他区域可以解决此问题。 固件,Bootloader和库(新区域)?
我想学习一般方法。是否有关于高级固件管理的论文,书籍和来源?
由于
答案 0 :(得分:2)
如果您在引导加载程序和主线固件应用程序之间共享代码,则引导加载程序将在闪烁应用程序空间时使用此代码。为了防止这种情况,您必须牺牲更新公共代码的能力,否则您的引导加载程序将崩溃。
只有12k的闪存,期望引导加载程序和主线应用程序适合,这是非常雄心勃勃的。您可以考虑在程序集中编写引导程序(喘气!)。一些Cortex M0器件(例如NXP LPC11xx系列)有一个额外的引导ROM,它存储了一些有用的功能,有助于减轻一些内存限制。
答案 1 :(得分:2)
你的问题正确地陈述了问题 - 你不能吃蛋糕并吃掉它。或者:
1.您需要占用较小的内存,并且不在引导加载程序中包含固件升级逻辑(即引导加载程序可能只是验证应用程序映像CRC等,但不会更复杂)。在这里,您可以共享功能以节省空间。 OR
2.引导加载程序具有固件升级功能。在这里,您必须将共享功能编译到app和bootloader中。共享功能应该很小 - 可能不是一个巨大的开销,但你需要这个空间 - 如果你没有它,那么你需要寻求更多的内存。
无法共享功能并可靠地从引导加载程序进行固件升级。
答案 2 :(得分:2)
根据目前关于固件更新过程中安全性的讨论,我想补充以下内容以澄清: 在引导程序和应用程序之间共享代码将为潜在的攻击打开另一扇门,所以你真的想避免这种情况。
引导程序部分是你实际上不想改变的部分,它应该尽可能地保持静态。如果引导程序被破坏,那么现场更新几乎不可能或至少不安全。
话虽如此,您可能想要使用不同的方法。 您可以为设备创建维护模式。 此模式打开JTAG接口,允许直接访问内存。比服务技术人员可以应用更新。
现在你只有"需要确保激活维护模式。 以下可能有效: 使用UART接口通知激活。
为了增加安全性,您肯定希望在类似的方案之后为维护系统ID付出一些努力。 ID应基本上取决于MAC地址或其他唯一硬件ID及其签名。应在维护系统的生产过程中在安全的环境中创建ID。唯一的硬件ID应该是外部可见的东西,因此服务器实际上可以验证接收的ID是否与维护系统与服务器通信匹配。
这整个设置可以在没有引导程序的情况下为您提供安全的固件更新。 要获得安全的固件更新,通常的理解是,您需要一个基于RSA等非对称加密的身份验证系统。如果您还需要验证码,上面将交换一个能够通过简单的UART接口接受更新的引导加载程序,从而节省了一些资源。
这是你要找的东西吗?
根据我的经验,商业引导程序使用4到8k的闪存,具体取决于闪存算法和其他一些东西。我一直坚持使用相同的供应商,所以这可能会因您的经验而异。
针对嵌入式系统优化的数字签名系统在闪存中使用大约4.5kByte(例如,请参见此处:https://www.segger.com/emlib-emsecure.html),并且不会有比堆栈更多的RAM。
你知道,在拥有一个可以在现场安全更新的系统方面,12k真的很低。更重要的是,如果您希望使用引导程序更新系统。