|
楼主 |
发表于 2014-5-17 10:52:54
|
显示全部楼层
接下来就开始构建我们的NVRAM设备,对于NVRAM设备我们一般是为EEPROM作为存储介质的,而项目中EEPROM的第一次上电
总是空的,所以我们需要一个默认的参数列表,因此我们定义一个默认的参数列表放在程序代码里,当发现是一个新的或是无效的
EEPROM时就使用默认的参数来进行初始化。
- static const struct nvram_sysparam nvram_sysparam_default = {
- .hdr = {NVRAM_FLAGSINFO_VALID, 0, 0, 0},
- .type = 0,
- .rev = 0,
- .sn = "N/A",
- .name = "N/A",
- /* 以下是用户定义数据类型 */
- .reserve32_1 = 0,
- .reserve16_1 = 0,
- .reserve08_1 = 0,
- };
复制代码
我们的NVRAM设备需要在多任务环境下使用因此,我们需要进行临界段处理,即进行共享资源互斥,这里使用互斥信号,
而且为了快速对NVRAM进行处理,我们需要定义一个缓冲区来加速应用程序的访问。
- extern const struct nvram_chip nvram_ee24lc512;
- static OS_MUTEX sysparam_locker;
- static struct nvram_sysparam sysparam_cache;
- const struct nvram_partition sysparam_partition = {
- .name = "sysparam_partition", /* 抽象设备的名称 */
- .chip = (struct nvram_chip *)&nvram_ee24lc512,/* 底层驱动指针 */
- .offset = 0, /* 该分区位于NVRAM_CHIP设备的偏移量,因为一个NVRAM_CHIP可以
- 拥有多个分区 */
- .size = 1024*16, /* 该分区的大小 */
- .cache_image = (void *)&nvram_sysparam_default,
- .cache_addr = (void *)&sysparam_cache,
- .total_cache_size = sizeof(sysparam_cache),
- .tbl = (struct nvram_param_info *)¶m_system_map_tbl[0], /* 把NVRAM设备与对应的名称映射表进行绑定 */
- .tbl_size = plat_countof(param_system_map_tbl),
- .locker = &sysparam_locker,
- };
复制代码
到此我们的NVRAM设备已经抽象出来了,下面就是实现具体的接口函数了,这里我给出我实现这些接口函数的代码如下:
- #define PARTITION_FLAGS_INVALID 1
- #define PARTITION_CRC_VERIFY_FAILED 2
- #define PARTITION_USE_DEFAULT_IMAGE 3
- #define PARTITION_USE_BACKUP_IMAGE 4
- #define PARTITION_CHIP_RW_ERR 5
- #define get_partition_hdr(p)\
- ((struct nvram_hdr *)p->cache_addr)
- #define get_chip_offset(p, offs)\
- (unsigned long)(p->offset + offs)
- #define get_chip_bak_offset(p, offs)\
- (unsigned long)(p->offset + (p->size >> 2) + offs)
- /**
- * @brief None.
- *
- * @param partition
- * @return
- * @note None.
- */
- static int init_partition_locker(struct nvram_partition *partition)
- {
- OS_ERR os_err;
- OSMutexCreate(partition->locker, "partition locker", &os_err);
- if (os_err != OS_ERR_NONE) {
- kprintf("error:%u nvram partition create locker failed\n", os_err);
- return -1;
- }
- return 0;
- }
- static void lock_partition(struct nvram_partition *partition)
- {
- OS_ERR os_err;
- OSMutexPend(partition->locker, 0, OS_OPT_PEND_BLOCKING, 0, &os_err);
- }
- static void unlock_partition(struct nvram_partition *partition)
- {
- OS_ERR os_err;
- OSMutexPost(partition->locker, OS_OPT_POST_NONE, &os_err);
- }
- /**
- * @brief None.
- *
- * @param partition
- * @return
- * @note None.
- */
- static int chk_partition_info(struct nvram_partition *partition)
- {
- struct nvram_chip *chip = partition->chip;
- if (!partition->name) {
- return -1;
- }
- if (!partition->chip) {
- return -1;
- }
- if (!partition->cache_image) {
- return -1;
- }
- if (!partition->cache_addr) {
- return -1;
- }
- if (!partition->cache_image) {
- return -1;
- }
- if (!partition->tbl) {
- return -1;
- }
- if (!partition->locker) {
- return -1;
- }
- if (partition->total_cache_size < 1) {
- return -1;
- }
- if (partition->size < (partition->total_cache_size * 2)) {
- return -1;
- }
- if (chip->size < partition->size) {
- return -1;
- }
- if ((partition->offset + partition->size) > chip->size) {
- return -1;
- }
- return 0;
- }
- /**
- * @brief 计算CRC32.
- *
- * @param partition
- * @return
- * @note None.
- */
- static uint32_t calc_partition_cache_crc(struct nvram_partition *partition)
- {
- uint32_t verify;
- unsigned long verify_size;
- struct nvram_hdr *hdr;
- hdr = get_partition_hdr(partition);
- verify_size = ((unsigned char *)partition->cache_addr +
- partition->total_cache_size) - (unsigned char *)hdr->data;
- // 计算参数区的crc32其中包括hdr区的数据data[1]内容
- verify = 0;
- verify = crc32(verify, (const unsigned char *)hdr->data, verify_size);
- return verify;
- }
- /**
- * @brief 复制分区中默认的IMAGE数据到用户CACHE中供应用程序使用.
- *
- * @param partition
- * @return None.
- * @note None.
- */
- static void copy_default_image(struct nvram_partition *partition)
- {
- struct nvram_hdr *hdr;
- hdr = (struct nvram_hdr *)partition->cache_addr;
- memcpy(partition->cache_addr, partition->cache_image,
- partition->total_cache_size);
- hdr->flags = NVRAM_FLAGSINFO_VALID;
- hdr->verify_crc = calc_partition_cache_crc(partition);
- }
- /**
- * @brief 从EEPROM中某个区域取了一定数量的数据,此时判断此EEPROM区域是否是有
- * 效的区域,如果是有效区域则查看是CRC校验是否正确.
- *
- * @param partition
- * @param force_offset
- * @param verify_crc
- * @return -1: 表示读取EEPROM出错.
- * 1:表示是一个新的EEPROM区域
- * 2:表示是一个有效的EEPROM区域,但是CRC校验出错
- * @note None.
- */
- static int chk_partition_and_verify(struct nvram_partition *partition,
- unsigned long force_offset, uint32_t *verify_crc)
- {
- uint32_t verify;
- struct nvram_chip *chip;
- struct nvram_hdr *hdr;
- chip = partition->chip;
- hdr = get_partition_hdr(partition);
- // 读取chip对应的此分区并进行有效性标识检查
- if (chip->read(chip, partition->offset + force_offset, partition->cache_addr,
- partition->total_cache_size) != 0) {
- return -1;
- }
- // 如果flags不是一个有效则表示是一个新的EEPROM
- if (hdr->flags != NVRAM_FLAGSINFO_VALID) {
- kprintf("find a new chip partition mapping, %s-->%s offset:%u size:%u\n",
- chip->name, partition->name, partition->offset, partition->size);
- // 返回表示chip对应的此分区是一个新的分区
- return PARTITION_FLAGS_INVALID;
- } else {
- // 对CRC再次检验
- verify = calc_partition_cache_crc(partition);
- *verify_crc = verify;
- if (verify != hdr->verify_crc) {
- // 出现这种原因主要可能是SysParaInfo结构中成员数量有所变化,如程序更改时
- kprintf("%s verify crc failed, verify:%u, hdr->verify_crc:%u",
- partition->name, verify, hdr->verify_crc);
- return PARTITION_CRC_VERIFY_FAILED;
- } else {
- return 0;
- }
- }
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param force_offset
- * @return
- * @note None.
- */
- static int program_partitions(struct nvram_partition *partition,
- unsigned long force_offset)
- {
- int r;
- struct nvram_chip *chip;
- chip = partition->chip;
- r = chip->write(chip, partition->offset + force_offset, partition->cache_addr,
- partition->total_cache_size);
- r = (r == 0) ? 0 : -1;
- return r;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @return
- * @note None.
- */
- static int init_partitions_cache(struct nvram_partition *partition)
- {
- uint32_t verify_crc1, verify_crc_bak;
- int r1, r_bak;
- unsigned long force_offset;
- /* --------------------------- 从原始位置读取参数 */
- /* 读取参数区有效性标识 */
- force_offset = partition->size >> 1;
- r_bak = chk_partition_and_verify(partition, force_offset, &verify_crc_bak);
- r1 = chk_partition_and_verify(partition, 0, &verify_crc1);
- // 如果两个位置有一个读取失败则返回
- if ((r1 == -1) || (r_bak == -1)) {
- copy_default_image(partition);
- return -1;
- }
- /*
- * 如果首要位置读取成功,则需要判定备份位置是否正确,如果不正确则恢复备份位置
- * 到首要位置状态
- */
- if (r1 == 0) {
- /* 原始数据区读取有效且数据效验正确 */
- if ((r_bak) || (verify_crc1 != verify_crc_bak)) {
- r1 = program_partitions(partition, force_offset);
- }
- return r1;
- } else if (r1 == PARTITION_CRC_VERIFY_FAILED) {
- /* 原始数据区读取有效但数据校验错误 */
- } else if (r1 == PARTITION_FLAGS_INVALID) {
- /* 原始数据区读取有效但是一个新的或是空的区域 */
- }
- /* ---------- 程序到此则表明原始的EEPROM区域无法校验通过或是一个新的EEPROM */
- /* 如果加载出错则需要再次从备份区域加载参数 */
- r_bak = chk_partition_and_verify(partition, force_offset, &verify_crc_bak);
- /* 判断备份位置参数是否正确 */
- if (r_bak == 0) {
- /* 到此说明最原始的EEPROM区域已无效因此需要更新原始EEPROM区域 */
- r1 = program_partitions(partition, 0);
- return ((r1 == 0) ? PARTITION_USE_BACKUP_IMAGE : -1);
- } else if (r_bak == -1) {
- kprintf("%s use the default partition image\n", partition->name);
- copy_default_image(partition);
- } else if ((r_bak == PARTITION_CRC_VERIFY_FAILED) ||
- (r_bak == PARTITION_FLAGS_INVALID)) {
- kprintf("%s use the default partition image\n", partition->name);
- /*
- * 如果备份区域也是一个无效的区域或是一个无法校验通过的区域,则此时需要
- * 使用默认的参数来保证程序的运行
- */
- copy_default_image(partition);
- r_bak = program_partitions(partition, force_offset);
- r1 = program_partitions(partition, 0);
- if ((r_bak == 0) && (r1 == 0)) {
- return PARTITION_USE_DEFAULT_IMAGE;
- }
- }
- return -1;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param offset_addr
- * @param buf
- * @param n_bytes
- * @return None.
- * @note None.
- */
- static int nvram_raw_write(struct nvram_partition *partition, unsigned long offset_addr,
- const char *buf, unsigned long n_bytes)
- {
- struct nvram_chip *chip;
- struct nvram_hdr *hdr;
- uint32_t verify;
- unsigned long chip_offset;
- memcpy(partition->cache_addr + offset_addr, buf, n_bytes);
- // 对CRC再次检验
- verify = calc_partition_cache_crc(partition);
- chip = partition->chip;
- hdr = get_partition_hdr(partition);
- hdr->verify_crc = verify;
- // 写EEPROM原始位置
- chip_offset = get_chip_offset(partition, offset_addr);
- if (chip->write(chip, chip_offset, buf, n_bytes) < 0) {
- return -1;
- }
- chip_offset = get_chip_offset(partition, plat_offsetof(struct nvram_hdr, verify_crc));
- if (chip->write(chip, chip_offset, (const char *)&verify, sizeof(verify)) < 0) {
- return -1;
- }
- // 更新备份位置
- chip_offset = get_chip_bak_offset(partition, offset_addr);
- if (chip->write(chip, chip_offset, buf, n_bytes) < 0) {
- return -1;
- }
- chip_offset = get_chip_bak_offset(partition, plat_offsetof(struct nvram_hdr, verify_crc));
- if (chip->write(chip, chip_offset, (const char *)&verify, sizeof(verify)) < 0) {
- return -1;
- }
- return 0;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param offset_addr
- * @param buf
- * @param n_bytes
- * @return
- * @note None.
- */
- static int nvram_raw_read(struct nvram_partition *partition,
- unsigned long offset_addr, char *buf,
- unsigned long n_bytes)
- {
- memcpy(buf, partition->cache_addr + offset_addr, n_bytes);
- return 0;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param name
- * @return
- * @note None.
- */
- static struct nvram_param_info *get_param_info(
- struct nvram_partition *partition, const char *name) {
- struct nvram_param_info *tbl;
- tbl = partition->tbl;
- for (unsigned int i = 0; i < partition->tbl_size; i++) {
- if (strcmp(name, tbl->name) == 0)
- return tbl;
- tbl++;
- }
- return NULL;
- }
- /**
- * @brief None.
- *
- * @param part_tbl
- * @param counter
- * @return
- * @note None.
- */
- int nvram_init_partitions(struct nvram_partition *part_tbl, unsigned int counter)
- {
- struct nvram_partition *partition;
- if (!part_tbl) {
- return -1;
- }
- if (counter < 1) {
- return -1;
- }
- for (unsigned int i = 0; i < counter; i++) {
- partition = &part_tbl[i];
- if (chk_partition_info(partition) < 0) {
- return -1;
- }
- if (init_partition_locker(partition)) {
- return -1;
- }
- switch (init_partitions_cache(partition)) {
- case 0:
- break;
- case PARTITION_USE_DEFAULT_IMAGE:
- break;
- case PARTITION_USE_BACKUP_IMAGE:
- break;
- default:
- break;
- }
- }
- return 0;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param name
- * @param buf
- * @param size
- * @return
- * @note None.
- */
- int nvram_set(struct nvram_partition *partition, const char *name, const char *buf, int size)
- {
- int r = -1;
- uint32_t param_value;
- int32_t param_value_signed;
- struct nvram_param_info *param_info;
- if (!partition) {
- return -1;
- }
- if (!name) {
- return -1;
- }
- if (!buf) {
- return -1;
- }
- if (size < 0) {
- return -1;
- }
- if (size == 0) {
- return 0;
- }
- param_info = get_param_info(partition, name);
- if (param_info == NULL) {
- return -1;
- }
- lock_partition(partition);
- if ((param_info->type == NVRAM_PARAM_TYPE_UVALUE) ||
- (param_info->type == NVRAM_PARAM_TYPE_SVALUE)) {
- switch (param_info->n_byte) {
- case 1:
- case 2:
- case 4:
- param_value = 0;
- param_value_signed = 0;
- if (param_info->type == NVRAM_PARAM_TYPE_UVALUE) {
- param_value = (uint32_t)strtoul(buf, 0, 0);
- r = nvram_raw_write(partition, param_info->offset,
- (char *)¶m_value, param_info->n_byte);
- } else {
- param_value_signed = (int32_t)strtol(buf, 0, 0);
- r = nvram_raw_write(partition, param_info->offset,
- (char *)¶m_value_signed, param_info->n_byte);
- }
- break;
- default:
- break;
- }
- } else if (param_info->type == NVRAM_PARAM_TYPE_STRING) {
- unsigned int value_len = DEF_MIN(size, param_info->n_byte);
- r = nvram_raw_write(partition, param_info->offset, buf, value_len);
- }
- unlock_partition(partition);
- return r;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param name
- * @param buf
- * @param size
- * @return
- * @note None.
- */
- int nvram_get(struct nvram_partition *partition, const char *name, char *buf, int size)
- {
- int r = -1;
- uint32_t param_value;
- int32_t param_value_signed;
- struct nvram_param_info *param_info;
- if (!partition) {
- return -1;
- }
- if (!name) {
- return -1;
- }
- if (!buf) {
- return -1;
- }
- if (size < 0) {
- return -1;
- }
- if (size == 0) {
- return 0;
- }
- param_info = get_param_info(partition, name);
- if (param_info == NULL) {
- return -1;
- }
- lock_partition(partition);
- if ((param_info->type == NVRAM_PARAM_TYPE_UVALUE) ||
- (param_info->type == NVRAM_PARAM_TYPE_SVALUE)) {
- switch (param_info->n_byte) {
- case 1:
- case 2:
- case 4:
- param_value = 0;
- param_value_signed = 0;
- if (param_info->type == NVRAM_PARAM_TYPE_UVALUE) {
- r = nvram_raw_read(partition, param_info->offset,
- (char *)¶m_value, param_info->n_byte);
- ksnprintf(buf, size, "%u", param_value);
- } else {
- r = nvram_raw_read(partition, param_info->offset,
- (char *)¶m_value_signed, param_info->n_byte);
- ksnprintf(buf, size, "%s", param_value_signed);
- }
- break;
- default:
- break;
- }
- } else if (param_info->type == NVRAM_PARAM_TYPE_STRING) {
- unsigned int value_len = DEF_MIN(size, param_info->n_byte);
- r = nvram_raw_read(partition, param_info->offset, buf, value_len);
- }
- unlock_partition(partition);
- return r;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param name
- * @param value
- * @return
- * @note None.
- */
- int nvram_set_ulong(struct nvram_partition *partition, const char *name, unsigned long value)
- {
- struct nvram_param_info *param_info;
- int r = -1;
- if (!partition) {
- return -1;
- }
- if (!name) {
- return -1;
- }
- param_info = get_param_info(partition, name);
- if (param_info == NULL) {
- return -1;
- }
- lock_partition(partition);
- if ((param_info->type == NVRAM_PARAM_TYPE_UVALUE) ||
- (param_info->type == NVRAM_PARAM_TYPE_SVALUE)) {
- switch (param_info->n_byte) {
- case 1:
- case 2:
- case 4:
- r = nvram_raw_write(partition, param_info->offset,
- (char *)&value, param_info->n_byte);
- break;
- default:
- break;
- }
- }
- unlock_partition(partition);
- return r;
- }
- /**
- * @brief None.
- *
- * @param partition
- * @param name
- * @param value
- * @return
- * @note None.
- */
- int nvram_get_ulong(struct nvram_partition *partition,
- const char *name, unsigned long *value)
- {
- int r = -1;
- unsigned long param_value;
- struct nvram_param_info *param_info;
- if (!partition) {
- return -1;
- }
- if (!name) {
- return -1;
- }
- if (!value) {
- return -1;
- }
- param_info = get_param_info(partition, name);
- if (param_info == NULL) {
- return -1;
- }
- lock_partition(partition);
- if ((param_info->type == NVRAM_PARAM_TYPE_UVALUE) ||
- (param_info->type == NVRAM_PARAM_TYPE_SVALUE)) {
- switch (param_info->n_byte) {
- case 1:
- case 2:
- case 4:
- param_value = 0;
- r = nvram_raw_read(partition, param_info->offset,
- (char *)¶m_value, param_info->n_byte);
- if (r == 0) {
- *value = (unsigned long)param_value;
- }
- break;
- default:
- break;
- }
- }
- unlock_partition(partition);
- return r;
- }
复制代码 |
|