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;
}