文档OTA流程说的明白, 但是CRC32的计算没有说明
我穷举各种CRC32的算法, 结果都不能和库中crc32函数算出的结果一样,
因为crc32这个函数不可见, 所以不能知道其具体算法.
uint32_t crc32(uint32_t crc, const uint8_t *buf, uint32_t len);
我的OTA操作方式如下:
- 把编译出的bin文件原封不动直接下载到B区.
1.下载成功之后, 让单片机自己去计算B区的信息数据, 然后写入B区信息位置(4-8K的位置). - 复位单片机,让自带的bootloader将B区固件升级到A区.
代码如下.
#define A_ZONE_INFO_OFFSET 0
#define B_ZONE_INFO_OFFSET SZ_4KB
#define A_ZONE_IMAGE_OFFSET SZ_8KB
#define B_ZONE_IMAGE_OFFSET SZ_8KB
if (cmd_code == CMD_DOWNLOAD_B_ZONE_IMAGE)
{
uint32_t b_zone_image_base_addr = (pcmd_data[0] << 8 | pcmd_data[1]) * SZ_4KB; //BIN的下载地址
uint32_t image_length = (pcmd_data[2] << 8 | pcmd_data[3]) * SZ_1KB; //BIN的下载长度
uint32_t image_offset = b_zone_image_base_addr + B_ZONE_IMAGE_OFFSET; //bin中程序代码的偏移, bin的前4KB+4KB都是固件信息数据,
if(Download_data(b_zone_image_base_addr, image_length) != true)
{
Printf_info("■->固件下载失败.");
return;
}
//====
Printf_info("->下载完成.");
Printf_info("->设置B区固件信息.");
struct image_info_t info = { 0 };
flash_read(b_zone_image_base_addr, sizeof(struct jump_table_t), (uint8_t *)&info);
info.compressed_info.compressed_label = 0xFFFFFFFF;
info.compressed_info.compressed_image_crc = 0;
info.crc.image_crc = crc32(0xffffffff, (const uint8_t *)(QSPI0_DAC_ADDRESS + image_offset), image_length);
info.crc.jump_table_crc = crc32(0xffffffff, (const uint8_t *)(&info), (uint32_t)&(((struct jump_table_t *)0)->checkword));
info.image_storage_offset = image_offset;
info.image_length = image_length;
info.flash_protect_mask = 0x7C;//0xFFFFFFFF;
info.image_valid = JUMP_TABLE_OTA_IMAGE_VALID;
//---
GLOBAL_INT_DISABLE();
uint16_t status = flash_read_status(false);
flash_write_status(status & (0xff), false);
//擦除扇区
flash_erase(B_ZONE_INFO_OFFSET, SZ_4KB);
flash_write_status(status, false);
//写入数据
flash_write_status(status & (0xff), false);
flash_write(B_ZONE_INFO_OFFSET, sizeof(struct image_info_t), (uint8_t *)&info);
//校验写入的数据
flash_write_status(status, false);
GLOBAL_INT_RESTORE();
uint8_t* Ps = (uint8_t *)&info;
uint8_t* Pd = (uint8_t*)(QSPI0_DAC_ADDRESS + B_ZONE_INFO_OFFSET);
for (int i = 0; i < sizeof(struct image_info_t); i++)
{
if (*Ps++ != *Pd++)
{
Printf_info("■->数据写入错误.");
Printf_info("->.");
return;
}
}
Printf_info("->设置B区固件信息完毕.");
Printf_info("->软复位,进行自动升级.");
Printf_info("->.");
Delay_ms(123);
NVIC_SystemReset();
}