将标头添加到固件映像stm 32

时间:2018-04-07 09:36:09

标签: c stm32 bootloader

我正在开始在STM32上开发自定义引导程序(类似于IAP AN4657)。假设闪存分为3个区域,用户区,IAP代码(引导加载程序)和要升级的固件位于临时区域。我想要一个带有固件版本和校验和的标题,我需要了解如何实现标头到固件并从IAP(bootloader)代码检查固件的有效性。任何对资源的引用都表示赞赏。

2 个答案:

答案 0 :(得分:1)

您可以创建一个包含标题信息的结构,并将此标题放在flash中的已知位置。您可以看到使用的两种常规方法:

  1. 填充固件二进制文件,最大为闪存大小,减去标题大小并将其放在最后,
  2. 将固件标题放在开头的某处,在.text,.data和.bss之前放大。
  3. 这种方法取决于您的要求是什么,您希望引导加载程序的复杂程度以及您愿意投入多少精力来使其更加优化或灵活。通常希望引导加载程序尽可能简单并且通常不能自编程(在出厂之后永远不会修改一个引导加载程序部分)。无论哪种方式,标头应驻留在闪存内的恒定偏移量。进一步详细说明上述两种方法:

    <强> 1。 (填充)二进制文件末尾的固件标题。

    这是一种更简单的方法,尤其是一些工具/ IDE(例如IAR)具有现成的机制。我们假设您的固件标头具有以下格式:

    typedef struct
    {
      uint32_t firmware_verson;
      uint32_t crc32;
    } sFirmwareHeader;
    

    在这种情况下,您将固件二进制文件(例如0xFF)填充到FLASH_SIZE - sizeof(sFirmwareHeader)并将结构放在那里。这些相同的工具通常也能够计算固件二进制的CRC并将其放在最后,这正是这种方法的优点。最大的缺点是每次想要以这种方式进行固件升级时,都需要从头到尾传输整个应用程序二进制文件,包括填充字节。如果您的应用程序很小,则会传输相当多的不必要字节。当然,我没有提到任何会使这个更小的压缩方法,因为那会使你的引导加载程序更复杂,因此更容易出错。

    <强> 2。应用程序二进制文件开头的固件标头

    另一种方法是将固件标题放在开头的某处。这方面的好地方可能是在ISR向量之后但在.text,.data和.bss之前,在更改应用程序代码时它们的大小会有所不同。一个好主意是使用firmware_size字段扩展上述结构:

    typedef struct
    {
      uint32_t firmware_verson;
      uint32_t firmware_size;
      uint32_t crc32;
    } sFirmwareHeader;
    

    这样,引导加载程序仍然不仅可以验证要加载的固件文件的CRC,还可以验证已经加载到闪存中的应用程序的完整性,因为固件头仍然驻留在闪存中的恒定偏移下记忆,它不像第一种方法那样结束。此方法的优点是您只需要根据需要传输尽可能多的字节。缺点是可能不会为您提供任何现成的工具。在构建应用程序固件二进制文件后,您需要编写某种简单的程序/脚本来为您计算CRC值(firmware_size值可以由链接器提供)。

    为了使答案更加完整,这里有一段代码,无论您打算使用哪种方法,都应该为您提供一个良好的起点。这些是针对gcc。

    链接器脚本的一部分定义了一个部分,用于将固件头保持在从0x200内存部分开头算起的常量FLASH偏移处:

    __fw_header_offset = 0x200;
    
    SECTIONS
    {
        /* ISR vectors */
    
        .fw_header : ALIGN(4)
        {
          FILL(0xFF)
    
          . = ORIGIN(FLASH) + __fw_header_offset;
          KEEP(*(.fw_header))
        } >FLASH
    
        /* Other sections in Flash */
    }
    

    然后在您的应用程序代码中,您可以执行此操作:

    const sFirmwareHeader __attribute__ ((section(".fw_header"))) FirmwareHeader = {
        1,  // firmware_verson
        0   // crc32, this can be filled with an external application after building firmmwre binary
    };
    

    创建一个全局FirmwareHeader结构,并且位于`.fw_header&#39;部分定义的预告片。

答案 1 :(得分:0)

我也在我的项目中使用类似的东西。

具有固件版本和CRC校验和的标头在FLASH结尾处放置在链接器脚本中,因此在源代码中的一个位置定义了具有固件版本的头结构,校验和是二进制的最后字节。

使用简单的python脚本构建并将elf转换为二进制文件后添加了Checksum。但是一些编译器(IAR)具有计算和放置固件校验和的功能。

在我的情况下,我在启动后查看更新区域中的标题,如果有什么内容并且CRC正常,整个标题与应用程序中的标题不同,我开始将此更新区域复制到应用程序区域。