c - 将 header 添加到固件镜像 stm32

标签 c stm32 bootloader

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

最佳答案

您可以创建一个包含 header 信息的结构并将此 header 放在闪存中的已知位置。您看到正在使用两种通用方法:

  1. 将固件二进制文件填充到闪存的大小,减去 header 的大小并将其放在末尾,
  2. 将固件 header 放在开头的某个位置,在大小不同的 .text、.data 和 .bss 之前。

该方法取决于您的要求、您希望引导加载程序的复杂程度以及您愿意付出多少努力来使其更优化或更灵活。通常希望引导加载程序尽可能简单并且通常不能自编程(有一个引导加载程序部分在出厂后从未修改过)。无论哪种方式, header 都应位于闪存中的恒定偏移处。进一步阐述上述两种方法:

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

这是一种更简单的方法,尤其是因为某些工具/IDE(例如 IAR)为此具有现成的使用机制。假设您的固件 header 格式如下:

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

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

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

另一种方法是将固件 header 放在开头的某个位置。这样做的好地方可能是在 ISR vector 之后但在 .text、.data 和 .bss 之前,它们的大小会随着您更改应用程序代码而变化。一个好主意是使用 firmware_size 字段扩展上述结构:

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

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

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

链接器脚本的一部分定义了一个部分,用于将固件 header 保存在从 FLASH 内存部分开始计算的恒定 0x200 偏移处:

__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' 部分定义的 eariler 下。

关于c - 将 header 添加到固件镜像 stm32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49705924/

相关文章:

c - 如何声明变量参数的数据类型?

c - 如何在文本文件中插入N个空格

c - 嵌入式 C-UTF8 到 MARC8

stm32 - 如何控制JTAG设备向闪存写入二进制文件?

STM32 目标停止时切换 PIN

operating-system - Bootstrap 如何实现操作系统的双重引导

gcc - 设置执行原始二进制文件的起始地址

documentation - 哪里可以找到 PC MBR Bootloader 的源代码?

c - 使用c中的文件路径打开文件

同时为静态库和可执行文件创建 makefile