You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32自定义IAP Bootloader固件头部添加与有效性校验技术问询

Hey there! Let's walk through how to implement the firmware header and validation logic for your STM32 custom IAP Bootloader, matching your Flash layout (scratch, user app, IAP) and referencing AN4657.

1. Define the Firmware Header Structure

First, create a packed struct to hold all necessary metadata. This will sit at the start of your scratch Flash area. We'll include fields to quickly validate firmware validity and track versioning:

#include <stdint.h>

// Packed struct to avoid padding issues on STM32's 32-bit architecture
typedef __packed struct {
    uint32_t magic_word;      // Unique identifier (e.g., 0xABCD1234) to flag valid firmware
    uint32_t version;         // Version number (e.g., 0x01020304 = v1.2.3.4)
    uint32_t firmware_length; // Length of the user application (excluding this header)
    uint32_t checksum;        // CRC32 checksum of the user application data
} FirmwareHeader_t;
  • Magic Word: Acts as a quick sanity check—if this doesn't match your predefined value, the firmware is immediately invalid.
  • Version: Lets you implement version checks (e.g., only upgrade to newer versions).
  • Firmware Length: Ensures you don't read beyond valid Flash boundaries during validation.
  • Checksum: Guarantees the firmware data hasn't been corrupted during transfer/storage. CRC32 is recommended here because it's fast to compute on embedded hardware.
2. Add the Header to Your Upgrade Firmware

You'll need to prepend this header to your compiled user application binary before transferring it to the scratch area. The most flexible way is to use a post-compilation script (Python works great for this):

import crcmod

# Configuration
USER_APP_BIN = "user_app.bin"
UPGRADE_BIN = "upgrade_with_header.bin"
MAGIC_WORD = 0xABCD1234
FIRMWARE_VERSION = 0x01020304

# Read the raw user application binary
with open(USER_APP_BIN, "rb") as f:
    firmware_data = f.read()

# Calculate CRC32 checksum of the firmware data
crc32 = crcmod.predefined.mkPredefinedCrcFun('crc-32')
calculated_checksum = crc32(firmware_data)

# Build the header (STM32 uses little-endian byte order)
header = b""
header += MAGIC_WORD.to_bytes(4, byteorder="little")
header += FIRMWARE_VERSION.to_bytes(4, byteorder="little")
header += len(firmware_data).to_bytes(4, byteorder="little")
header += calculated_checksum.to_bytes(4, byteorder="little")

# Combine header and firmware into the final upgrade binary
with open(UPGRADE_BIN, "wb") as f:
    f.write(header + firmware_data)

Alternatively, if you control the user application code, you could embed the header as a global const at a fixed address—but this is less flexible for version updates.

3. Validate Firmware in the IAP Bootloader

Once the upgrade firmware is in the scratch area, your Bootloader needs to run through three validation steps before proceeding with the upgrade:

Step 1: Check the Magic Word

First, verify the magic word to confirm this is a legitimate firmware image:

#include "stm32f4xx_hal.h"

#define SCRATCH_FLASH_START 0x08020000  // Adjust to your actual scratch area start address
#define USER_APP_MAX_SIZE   0x10000      // Max size of your user application area

void validate_and_upgrade(void) {
    FirmwareHeader_t *fw_header = (FirmwareHeader_t *)SCRATCH_FLASH_START;

    // Check magic word first
    if (fw_header->magic_word != 0xABCD1234) {
        // Invalid firmware—exit upgrade flow
        return;
    }

Step 2: Validate Firmware Length

Ensure the firmware doesn't exceed the size of your user application area (prevents writing outside valid Flash):

// Check if firmware length is within valid bounds
    if (fw_header->firmware_length == 0 || fw_header->firmware_length > USER_APP_MAX_SIZE) {
        return;
    }

Step 3: Verify the Checksum

Use STM32's hardware CRC peripheral to compute the checksum of the firmware data and compare it to the header's value:

// Initialize CRC peripheral
    CRC_HandleTypeDef hcrc;
    hcrc.Instance = CRC;
    hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
    hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
    hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
    hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_NONE;
    hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;

    if (HAL_CRC_Init(&hcrc) != HAL_OK) {
        // CRC init failed—exit
        return;
    }

    // Calculate CRC32 of the firmware data (skip the header)
    uint32_t computed_crc = HAL_CRC_Calculate(&hcrc, 
        (uint32_t*)(SCRATCH_FLASH_START + sizeof(FirmwareHeader_t)), 
        fw_header->firmware_length / 4);

    // Handle cases where firmware length isn't a multiple of 4
    // (add logic to process remaining bytes if needed)

    // Compare computed CRC to header value
    if (computed_crc != fw_header->checksum) {
        HAL_CRC_DeInit(&hcrc);
        return;
    }

    // All checks passed—proceed to copy firmware from scratch to user area
    HAL_CRC_DeInit(&hcrc);
    // ... add your Flash erase/write logic here
}
4. Key Additional Tips
  • Flash Alignment: STM32 Flash is erased in pages, so ensure your scratch area size aligns with the Flash page size of your MCU.
  • Byte Order: Always use little-endian for multi-byte fields (matches STM32's native byte order).
  • AN4657 Reference: ST's AN4657 document includes full IAP examples—focus on the Firmware Validation and Firmware Update sections. You can adapt their Flash handling and upgrade logic to fit your custom layout.

内容的提问来源于stack exchange,提问作者SamForiYana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:47:59