stm32 OTA固件制作(在固件中增加id hardve software crc)

本文介绍了在STM32的OTA升级过程中如何确保固件一致性,包括填充固定大小、添加元数据(如ID、硬件版本和软件版本)、计算CRC校验以验证完整性,并提供了Windows下的固件填充代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

     stm32等在OTA升级过程中,确保固件的一致性非常关键,为了防止下载到的固件在单片机上出现故障。为了实现这一目标,通常采取以下步骤:

1 固件制作说明

(1)填充固件到固定大小:将下载的固件(通常以二进制格式)填充到固定的大小。这可以通过向文件添加字节或字节序列来实现,使其达到所需的固定大小。

(2)添加元数据:在固件的末尾添加元数据,通常包括以下信息:

        ID(标识):唯一标识固件的信息,通常用于版本跟踪。

        硬件版本:描述固件所适用的硬件版本信息。

        软件版本:指示固件的版本号或标识。

        CRC(循环冗余校验):用于验证固件完整性的校验和。

(3)计算CRC校验和:对整个固件文件进行CRC校验,以确保其完整性。如果CRC校验失败,说明固件已损坏,需要重新下载。

        这种方法可以帮助确保下载的固件是有效且完整的,从而降低单片机砖化的风险。在实际OTA升级中,通常还会有额外的安全性和错误处理措施,以确保升级的成功性和可靠性。

2 windows下固件填充代码

  (1) 将下面的代码在windows下或者ubuntu下使用以下指令编译

gcc -o firmware '.\firmware.c

(2)编译以后的固件

(3)使用方法

firmware.exe test.bin 102400 1 1 3

使用上面的指令以后 将固件使用0xff扩充到 并在后面一次增加产品id 硬件版本号 软件版本号 以及校验和等信息。扩充后的固件为output.bin 总大小为102400 

(4)程序源码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, int8_t *argv[])
{
    uint32_t i = 0;
    if (argc != 6)
    {
        printf("Usage:  <file> <size> <id> <hardware> <software>\n");
        printf("sample: firmware test.bin 524288 10 11 12 \n");
        return 1;
    }

    int8_t *input_filename = argv[1];
    uint32_t size = atoi(argv[2]);
    uint32_t id = 0;
    uint32_t hardware;
    uint32_t software;

    id = atoi(argv[3]);
    hardware = atoi(argv[4]);
    software = atoi(argv[5]);

    printf("id=%d hardware=%d software=%d\n", id, hardware, software);

    // 删除已存在的output.bin文件(如果存在)
    remove("output.bin");

    FILE *input_file = fopen(input_filename, "rb");
    if (input_file == NULL)
    {
        perror("Error opening input file");
        return 1;
    }

    FILE *output_file = fopen("output.bin", "wb+");
    if (output_file == NULL)
    {
        perror("Error creating output file");
        fclose(input_file);
        return 1;
    }

    fseek(input_file, 0, SEEK_END);
    uint32_t input_size = ftell(input_file);

    // 复制数据到输出文件
    fseek(input_file, 0, SEEK_SET);
    int8_t ch;
    for (i = 0; i < input_size; i++)
    {
        ch = fgetc(input_file);
        fputc(ch, output_file);
    }

    // 确保没有复制错误
    int8_t ch1;
    fseek(input_file, 0, SEEK_SET);
    fseek(output_file, 0, SEEK_SET);

    for (i = 0; i < input_size; i++)
    {
        ch = fgetc(input_file);
        ch1 = fgetc(output_file);
        if (ch1 != ch)
        {
            fclose(input_file);
            fclose(output_file);
            printf("copy file error");
            return -1;
        }
    }

    // 获取当前输出文件大小
    fseek(output_file, 0, SEEK_END);
    int output_size = ftell(output_file);

    // 补充0xFF以满足size-16
    while (output_size < size - 16)
    {
        fputc(0xFF, output_file);
        output_size++;
    }

    // 固件末位增加id hardware software
    fseek(output_file, output_size, SEEK_SET);
    fwrite(&id, sizeof(unsigned int), 1, output_file);
    output_size += 4;
    fwrite(&hardware, sizeof(unsigned int), 1, output_file);
    output_size += 4;
    fwrite(&software, sizeof(unsigned int), 1, output_file);
    output_size += 4;

    // 计算校验和
    uint32_t value1 = 0;
    uint8_t temp0 = 0;
    fseek(output_file, 0, SEEK_SET);
    for (i = 0; i < output_size; i++)
    {
        temp0 = fgetc(output_file);
        value1 += temp0;
    }
    printf("crc=%u  0x%x\n", value1, value1);

    // 固件末位增加校验
    fwrite(&value1, sizeof(unsigned int), 1, output_file);

    fclose(input_file);
    fclose(output_file);

    printf("File successfully processed.\n");

    return 0;
}

### OTA汽车远程升级数据格式解释 #### 数据包基本结构 在OTA(Over-The-Air)车辆升级过程中,传输的数据通常被封装成特定格式的数据包。这些数据包不仅包含了待更新的软件或固件本身,还携带了用于确保数据完整性和正确性的元数据。 一个典型的数据包可能具有如下结构: | 字段 | 描述 | |----------------| | 帧头 | 表明新消息开始的特殊字符序列 | | 帧序号 | 用来标识当前帧在整个文件中的位置 | | 帧序反码 | 对应于帧序号按位取反的结果 | | 实际数据 | 需要传送的有效负载 | | CRC校验高字节 | 循环冗余检验值的一部分 | | CRC校验低字节 | 另一部分循环冗余检验值 | 这种设计有助于接收端验证接收到的信息是否完好无损,并能识别出任何潜在错误[^3]。 对于具体到STM32这样的微控制器平台而言,在执行FOTA(Firmware Over The Air)操作时会通过Wi-Fi等方式建立网络连接来获取新的固件版本并将其写入内部存储器中完成整个过程[^2]。 当涉及到更复杂的SOTA(Software Over The Air),除了上述提到的基础字段外,可能会增加更多关于应用程序级别的控制指令以及额外的安全措施以保护敏感信息不被篡改或泄露[^1]。 ```python # Python伪代码展示如何解析简单的OTA数据包 def parse_ota_packet(packet_bytes): header = packet_bytes[:4] # 获取前四个字节作为头部标志 seq_num = int.from_bytes(packet_bytes[4:6], byteorder='big') # 序列号占两个字节 inverted_seq = ~seq_num & 0xFFFF # 计算反转后的序列号 data_start_index = 8 # 跳过前面固定的几个部分到达有效载荷起始处 crc_high = packet_bytes[-2] # 最后第二个字节为CRC高位 crc_low = packet_bytes[-1] # 最后一字节为CRC低位 payload = packet_bytes[data_start_index:-2] return { "header": header, "sequence_number": seq_num, "inverted_sequence": inverted_seq, "payload": payload, "crc_checksum": (crc_high << 8) + crc_low } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值