armink / EasyFlash

Lightweight IoT device information storage solution: KV/IAP/LOG. | 轻量级物联网设备信息存储方案:参数存储、在线升级及日志存储 ,全新一代版本请移步至 https://github.com/armink/FlashDB
MIT License
2.01k stars 765 forks source link

64bit 写入粒度,计算env_hdr.crc32错误 #165

Open wumingxu10 opened 6 months ago

wumingxu10 commented 6 months ago
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);
           }