EasyFlash
EasyFlash copied to clipboard
64bit 写入粒度,计算env_hdr.crc32错误
static EfErrCode create_env_blob(sector_meta_data_t sector, const char *key, const void *value, size_t len)
{
EfErrCode result = EF_NO_ERR;
struct env_hdr_data env_hdr;
bool is_full = false;
uint32_t env_addr = sector->empty_env;
if (strlen(key) > EF_ENV_NAME_MAX) {
EF_INFO("Error: The ENV name length is more than %d\n", EF_ENV_NAME_MAX);
return EF_ENV_NAME_ERR;
}
memset(&env_hdr, 0xFF, sizeof(struct env_hdr_data));//《---------初始化为FF,会漏掉最后4字节,导致后面计算crc错误
env_hdr.magic = ENV_MAGIC_WORD;
env_hdr.name_len = strlen(key);
env_hdr.value_len = len;
env_hdr.len = ENV_HDR_DATA_SIZE + EF_WG_ALIGN(env_hdr.name_len) + EF_WG_ALIGN(env_hdr.value_len);
if (env_hdr.len > SECTOR_SIZE - SECTOR_HDR_DATA_SIZE) {
EF_INFO("Error: The ENV size is too big\n");
return EF_ENV_FULL;
}
if (env_addr != FAILED_ADDR || (env_addr = new_env(sector, env_hdr.len)) != FAILED_ADDR) {
size_t align_remain;
/* update the sector status */
if (result == EF_NO_ERR) {
result = update_sec_status(sector, env_hdr.len, &is_full);//《--------①
}
if (result == EF_NO_ERR) {
uint8_t ff = 0xFF;
/* start calculate CRC32 */
env_hdr.crc32 = ef_calc_crc32(0, &env_hdr.name_len, ENV_HDR_DATA_SIZE - ENV_NAME_LEN_OFFSET);//《-----② 计算错误, 计算从&env_hdr.name_len开始的12字节(ENV_HDR_DATA_SIZE - ENV_NAME_LEN_OFFSET),最后4字节可能因为flash残留的数据且上面memset时没有为FF导致crc错误。
env_hdr.crc32 = ef_calc_crc32(env_hdr.crc32, key, env_hdr.name_len);
align_remain = EF_WG_ALIGN(env_hdr.name_len) - env_hdr.name_len;
while (align_remain--) {
env_hdr.crc32 = ef_calc_crc32(env_hdr.crc32, &ff, 1);
}
env_hdr.crc32 = ef_calc_crc32(env_hdr.crc32, value, env_hdr.value_len);
align_remain = EF_WG_ALIGN(env_hdr.value_len) - env_hdr.value_len;
while (align_remain--) {
env_hdr.crc32 = ef_calc_crc32(env_hdr.crc32, &ff, 1);
}
/* write ENV header data */
result = write_env_hdr(env_addr, &env_hdr);
}
/* write key name */
if (result == EF_NO_ERR) {
result = align_write(env_addr + ENV_HDR_DATA_SIZE, (uint32_t *) key, env_hdr.name_len);
#ifdef EF_ENV_USING_CACHE
if (!is_full) {
update_sector_cache(sector->addr,
env_addr + ENV_HDR_DATA_SIZE + EF_WG_ALIGN(env_hdr.name_len) + EF_WG_ALIGN(env_hdr.value_len));
}
update_env_cache(key, env_hdr.name_len, env_addr);
#endif /* EF_ENV_USING_CACHE */
}
/* write value */
if (result == EF_NO_ERR) {
result = align_write(env_addr + ENV_HDR_DATA_SIZE + EF_WG_ALIGN(env_hdr.name_len), value,
env_hdr.value_len);
}
/* change the ENV status to ENV_WRITE */
if (result == EF_NO_ERR) {
result = write_status(env_addr, env_hdr.status_table, ENV_STATUS_NUM, ENV_WRITE);
}
/* trigger GC collect when current sector is full */
if (result == EF_NO_ERR && is_full) {
EF_DEBUG("Trigger a GC check after created ENV.\n");
gc_request = true;
}
} else {
result = EF_ENV_FULL;
}
return result;
}
我一开始是直接把memset(&env_hdr, 0xFF, sizeof(struct env_hdr_data));改为memset(&env_hdr, 0xFF, ENV_HDR_DATA_SIZE);,第一个env的数据是正常了,但是第二个以后后面还是会因为crc校验错误,导致无法拿到env数据,调试后发现,在①函数执行后,我的env_hdr最后的四字节应该是FF FF FF FF,变成了00 FF FF FF,导致我crc错误,所以我把②的函数修改成
env_hdr.crc32 = ef_calc_crc32(0, &env_hdr.name_len, sizeof(struct env_hdr_data) - ENV_NAME_LEN_OFFSET);
align_remain = ENV_HDR_DATA_SIZE - sizeof(struct env_hdr_data);
while (align_remain--) {
env_hdr.crc32 = ef_calc_crc32(env_hdr.crc32, &ff, 1);
}