diff --git a/easyflash/inc/easyflash.h b/easyflash/inc/easyflash.h deleted file mode 100644 index 2aab0b1..0000000 --- a/easyflash/inc/easyflash.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2014-2019, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: It is an head file for this library. You can see all be called functions. - * Created on: 2014-09-10 - */ - - -#ifndef EASYFLASH_H_ -#define EASYFLASH_H_ - -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* easyflash.c */ -EfErrCode easyflash_init(void); - -#ifdef EF_USING_ENV -/* only supported on ef_env.c */ -size_t ef_get_env_blob(const char *key, void *value_buf, size_t buf_len, size_t *saved_value_len); -bool ef_get_env_obj(const char *key, env_node_obj_t env); -size_t ef_read_env_value(env_node_obj_t env, uint8_t *value_buf, size_t buf_len); -EfErrCode ef_set_env_blob(const char *key, const void *value_buf, size_t buf_len); - -/* ef_env.c, ef_env_legacy_wl.c and ef_env_legacy.c */ -EfErrCode ef_load_env(void); -void ef_print_env(void); -char *ef_get_env(const char *key); -EfErrCode ef_set_env(const char *key, const char *value); -EfErrCode ef_del_env(const char *key); -EfErrCode ef_save_env(void); -EfErrCode ef_env_set_default(void); -size_t ef_get_env_write_bytes(void); -EfErrCode ef_set_and_save_env(const char *key, const char *value); -EfErrCode ef_del_and_save_env(const char *key); -#endif - -#ifdef EF_USING_IAP -/* ef_iap.c */ -EfErrCode ef_erase_bak_app(size_t app_size); -EfErrCode ef_erase_user_app(uint32_t user_app_addr, size_t user_app_size); -EfErrCode ef_erase_spec_user_app(uint32_t user_app_addr, size_t app_size, - EfErrCode (*app_erase)(uint32_t addr, size_t size)); -EfErrCode ef_erase_bl(uint32_t bl_addr, size_t bl_size); -EfErrCode ef_write_data_to_bak(uint8_t *data, size_t size, size_t *cur_size, - size_t total_size); -EfErrCode ef_copy_app_from_bak(uint32_t user_app_addr, size_t app_size); -EfErrCode ef_copy_spec_app_from_bak(uint32_t user_app_addr, size_t app_size, - EfErrCode (*app_write)(uint32_t addr, const uint32_t *buf, size_t size)); -EfErrCode ef_copy_bl_from_bak(uint32_t bl_addr, size_t bl_size); -uint32_t ef_get_bak_app_start_addr(void); -#endif - -#ifdef EF_USING_LOG -/* ef_log.c */ -EfErrCode ef_log_read(size_t index, uint32_t *log, size_t size); -EfErrCode ef_log_write(const uint32_t *log, size_t size); -EfErrCode ef_log_clean(void); -size_t ef_log_get_used_size(void); -#endif - -/* ef_utils.c */ -uint32_t ef_calc_crc32(uint32_t crc, const void *buf, size_t size); - -/* ef_port.c */ -EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size); -EfErrCode ef_port_erase(uint32_t addr, size_t size); -EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size); -void ef_port_env_lock(void); -void ef_port_env_unlock(void); -void ef_log_debug(const char *file, const long line, const char *format, ...); -void ef_log_info(const char *format, ...); -void ef_print(const char *format, ...); - -#ifdef __cplusplus -} -#endif - -#endif /* EASYFLASH_H_ */ diff --git a/easyflash/inc/ef_cfg.h b/easyflash/inc/ef_cfg.h deleted file mode 100644 index 717748b..0000000 --- a/easyflash/inc/ef_cfg.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2019, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: It is the configure head file for this library. - * Created on: 2015-07-14 - */ - -#ifndef EF_CFG_H_ -#define EF_CFG_H_ - -/* using ENV function, default is NG (Next Generation) mode start from V4.0 */ -#define EF_USING_ENV - -#ifdef EF_USING_ENV -/* Auto update ENV to latest default when current ENV version number is changed. */ -/* #define EF_ENV_AUTO_UPDATE */ -/** - * ENV version number defined by user. - * Please change it when your firmware add a new ENV to default_env_set. - */ -#define EF_ENV_VER_NUM /* @note you must define it for a value, such as 0 */ - -/* MCU Endian Configuration, default is Little Endian Order. */ -/* #define EF_BIG_ENDIAN */ - -#endif /* EF_USING_ENV */ - -/* using IAP function */ -/* #define EF_USING_IAP */ - -/* using save log function */ -/* #define EF_USING_LOG */ - -/* The minimum size of flash erasure. May be a flash sector size. */ -#define EF_ERASE_MIN_SIZE /* @note you must define it for a value */ - -/* the flash write granularity, unit: bit - * only support 1(nor flash)/ 8(stm32f4)/ 32(stm32f1) */ -#define EF_WRITE_GRAN /* @note you must define it for a value */ - -/* - * - * This all Backup Area Flash storage index. All used flash area configure is under here. - * |----------------------------| Storage Size - * | Environment variables area | ENV area size @see ENV_AREA_SIZE - * |----------------------------| - * | Saved log area | Log area size @see LOG_AREA_SIZE - * |----------------------------| - * |(IAP)Downloaded application | IAP already downloaded application, unfixed size - * |----------------------------| - * - * @note all area sizes must be aligned with EF_ERASE_MIN_SIZE - * - * The EasyFlash add the NG (Next Generation) mode start from V4.0. All old mode before V4.0, called LEGACY mode. - * - * - NG (Next Generation) mode is default mode from V4.0. It's easy to settings, only defined the ENV_AREA_SIZE. - * - The LEGACY mode has been DEPRECATED. It is NOT RECOMMENDED to continue using. - * Beacuse it will use ram to buffer the ENV and spend more flash erase times. - * If you want use it please using the V3.X version. - */ - -/* backup area start address */ -#define EF_START_ADDR /* @note you must define it for a value */ - -/* ENV area size. It's at least one empty sector for GC. So it's definition must more then or equal 2 flash sector size. */ -#define ENV_AREA_SIZE /* @note you must define it for a value if you used ENV */ - -/* saved log area size */ -#define LOG_AREA_SIZE /* @note you must define it for a value if you used log */ - -/* print debug information of flash */ -#define PRINT_DEBUG - -#endif /* EF_CFG_H_ */ diff --git a/easyflash/inc/ef_def.h b/easyflash/inc/ef_def.h deleted file mode 100644 index 0339c01..0000000 --- a/easyflash/inc/ef_def.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2019-2020, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: It is the definitions head file for this library. - * Created on: 2019-11-20 - */ - -#ifndef EF_DEF_H_ -#define EF_DEF_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* EasyFlash software version number */ -#define EF_SW_VERSION "4.1.99" -#define EF_SW_VERSION_NUM 0x40199 - -/* - * ENV version number defined by user. - * Please change it when your firmware add a new ENV to default_env_set. - */ -#ifndef EF_ENV_VER_NUM -#define EF_ENV_VER_NUM 0 -#endif - -/* the ENV max name length must less then it */ -#ifndef EF_ENV_NAME_MAX -#define EF_ENV_NAME_MAX 32 -#endif - -/* EasyFlash debug print function. Must be implement by user. */ -#ifdef PRINT_DEBUG -#define EF_DEBUG(...) ef_log_debug(__FILE__, __LINE__, __VA_ARGS__) -#else -#define EF_DEBUG(...) -#endif -/* EasyFlash routine print function. Must be implement by user. */ -#define EF_INFO(...) ef_log_info(__VA_ARGS__) -/* EasyFlash assert for developer. */ -#define EF_ASSERT(EXPR) \ -if (!(EXPR)) \ -{ \ - EF_DEBUG("(%s) has assert failed at %s.\n", #EXPR, __FUNCTION__); \ - while (1); \ -} - -typedef struct _ef_env { - char *key; - void *value; - size_t value_len; -} ef_env, *ef_env_t; - -/* EasyFlash error code */ -typedef enum { - EF_NO_ERR, - EF_ERASE_ERR, - EF_READ_ERR, - EF_WRITE_ERR, - EF_ENV_NAME_ERR, - EF_ENV_NAME_EXIST, - EF_ENV_FULL, - EF_ENV_INIT_FAILED, -} EfErrCode; - -/* the flash sector current status */ -typedef enum { - EF_SECTOR_EMPTY, - EF_SECTOR_USING, - EF_SECTOR_FULL, -} EfSecrorStatus; - -enum env_status { - ENV_UNUSED, - ENV_PRE_WRITE, - ENV_WRITE, - ENV_PRE_DELETE, - ENV_DELETED, - ENV_ERR_HDR, - ENV_STATUS_NUM, -}; -typedef enum env_status env_status_t; - -struct env_node_obj { - env_status_t status; /**< ENV node status, @see node_status_t */ - bool crc_is_ok; /**< ENV node CRC32 check is OK */ - uint8_t name_len; /**< name length */ - uint32_t magic; /**< magic word(`K`, `V`, `4`, `0`) */ - uint32_t len; /**< ENV node total length (header + name + value), must align by EF_WRITE_GRAN */ - uint32_t value_len; /**< value length */ - char name[EF_ENV_NAME_MAX]; /**< name */ - struct { - uint32_t start; /**< ENV node start address */ - uint32_t value; /**< value start address */ - } addr; -}; -typedef struct env_node_obj *env_node_obj_t; - -#ifdef __cplusplus -} -#endif - -#endif /* EF_DEF_H_ */ diff --git a/easyflash/plugins/types/README.md b/easyflash/plugins/types/README.md deleted file mode 100644 index 9f70741..0000000 --- a/easyflash/plugins/types/README.md +++ /dev/null @@ -1,152 +0,0 @@ -# EasyFlash Types 插件(plugin) - ---- - -## 1、介绍 - -目前 EasyFlash 会将环境变量以字符串形式存储于 Flash 中,在这种模式下,对于非字符串类型的环境变量在使用时,就必须得增加额外的字符串转换代码。设计 Types 插件就是为了方便用户在使用 EasyFlash 时,以更加简单的方式去操作各种类型的环境变量。 - -主要支持的类型包括:C 的 **基本类型** 、 **数组类型** 以及 **结构体类型** 。对于结构体类型, Types 插件内部采用 [struct2json](https://github.com/armink/struct2json) 库进行转换,所以项目中需要依赖 [struct2json](https://github.com/armink/struct2json) 库。 - -## 2、使用 - -### 2.1 源码导入 - -导入之前需要确认自己的项目中已包含 EasyFlash 核心源码,即包括 "\easyflash\inc"、"\easyflash\port" 及 "\easyflash\src" 下相关文件(导入方法可以参考这个移植文档:[点击打开](https://github.com/armink/EasyFlash/blob/master/docs/zh/port.md))。再将 Types 插件源码导入到项目中,最好连同 "plugins\types" 文件夹一起拷贝至项目中已有的 easyflash 文件夹下。然后需要添加 `easyflash\plugins\types\struct2json\inc` 及 `easyflash\plugins\types` 两个文件夹路径到项目头文件路径中即可。 - -### 2.2 初始化 - -```C -void ef_types_init(S2jHook *hook) -``` - -这个方法为 Types 插件的初始化方法,主要初始化 struct2json 库所需的内存管理方法。默认使用的 malloc 及 free 作为内存管理方法,如果使用默认内存管理方式,则无需初始化。例如如果使用 RT-Thread 操作系统自带的内存管理方法,则可以参考下面的初始化代码: - -```C -S2jHook s2jHook = { - .free_fn = rt_free, - .malloc_fn = (void *(*)(size_t))rt_malloc, -}; -ef_types_init(&s2jHook); -``` - -### 2.3 操作环境变量 - -#### 2.3.1 基本类型 - -对于基本类型的环境变量操作方法与 EasyFlash 原有的 API 一致,只是修改了入参及出参的类型,所有可用的 API 如下: - -```C -bool ef_get_bool(const char *key); -char ef_get_char(const char *key); -short ef_get_short(const char *key); -int ef_get_int(const char *key); -long ef_get_long(const char *key); -float ef_get_float(const char *key); -double ef_get_double(const char *key); -EfErrCode ef_set_bool(const char *key, bool value); -EfErrCode ef_set_char(const char *key, char value); -EfErrCode ef_set_short(const char *key, short value); -EfErrCode ef_set_int(const char *key, int value); -EfErrCode ef_set_long(const char *key, long value); -EfErrCode ef_set_float(const char *key, float value); -EfErrCode ef_set_double(const char *key, double value); -``` - -#### 2.3.2 数组类型 - -与基本类型的操作方法大体一致,不同点在于:获取到的环境变量需通过指针类型的入参进行返回。所有可用的 API 如下: - -```C -void ef_get_bool_array(const char *key, bool *value); -void ef_get_char_array(const char *key, char *value); -void ef_get_short_array(const char *key, short *value); -void ef_get_int_array(const char *key, int *value); -void ef_get_long_array(const char *key, long *value); -void ef_get_float_array(const char *key, float *value); -void ef_get_double_array(const char *key, double *value); -void ef_get_string_array(const char *key, char **value); -EfErrCode ef_set_bool_array(const char *key, bool *value, size_t len); -EfErrCode ef_set_char_array(const char *key, char *value, size_t len); -EfErrCode ef_set_short_array(const char *key, short *value, size_t len); -EfErrCode ef_set_int_array(const char *key, int *value, size_t len); -EfErrCode ef_set_long_array(const char *key, long *value, size_t len); -EfErrCode ef_set_float_array(const char *key, float *value, size_t len); -EfErrCode ef_set_double_array(const char *key, double *value, size_t len); -EfErrCode ef_set_string_array(const char *key, char **value, size_t len); -``` -#### 2.3.3 结构体类型 - -对于结构体类型,这里首先需要使用 struct2json 库来编写与该结构体对应的 JSON 互转方法,再将编写好的互转方法作为入参进行使用。结构体类型环境变量操作的 API 如下: - -```C -void *ef_get_struct(const char *key, ef_types_get_cb get_cb); -EfErrCode ef_set_struct(const char *key, void *value, ef_types_set_cb set_cb); -``` - -具体使用流程及结构体与 JSON 之间的互转方法可以参考下面的 Demo: - -```C -/* 定义结构体 */ -typedef struct { - char name[16]; -} Hometown; -typedef struct { - uint8_t id; - double weight; - uint8_t score[8]; - char name[16]; - Hometown hometown; -} Student; - -/* 定义结构体转 JSON 的方法 */ -static cJSON *stu_set_cb(void* struct_obj) { - Student *struct_student = (Student *)struct_obj; - /* 创建 Student JSON 对象 */ - s2j_create_json_obj(json_student); - /* 序列化数据到 Student JSON 对象 */ - s2j_json_set_basic_element(json_student, struct_student, int, id); - s2j_json_set_basic_element(json_student, struct_student, double, weight); - s2j_json_set_array_element(json_student, struct_student, int, score, 8); - s2j_json_set_basic_element(json_student, struct_student, string, name); - /* 序列化数据到 Student.Hometown JSON 对象 */ - s2j_json_set_struct_element(json_hometown, json_student, struct_hometown, struct_student, Hometown, hometown); - s2j_json_set_basic_element(json_hometown, struct_hometown, string, name); - return json_student; -} - -/* 定义 JSON 转结构体的方法 */ -static void *stu_get_cb(cJSON* json_obj) { - /* 创建 Student 结构体对象(提示: s2j_ 开头的方法是 struct2json 库提供的) */ - s2j_create_struct_obj(struct_student, Student); - /* 反序列化数据到 Student 结构体对象 */ - s2j_struct_get_basic_element(struct_student, json_obj, int, id); - s2j_struct_get_array_element(struct_student, json_obj, int, score); - s2j_struct_get_basic_element(struct_student, json_obj, string, name); - s2j_struct_get_basic_element(struct_student, json_obj, double, weight); - /* 反序列化数据到 Student.Hometown 结构体对象 */ - s2j_struct_get_struct_element(struct_hometown, struct_student, json_hometown, json_obj, Hometown, hometown); - s2j_struct_get_basic_element(struct_hometown, json_hometown, string, name); - return struct_student; -} - -/* 设置结构体类型环境变量 */ -Student orignal_student = { - .id = 24, - .weight = 71.2, - .score = {1, 2, 3, 4, 5, 6, 7, 8}, - .name = "张三", - .hometown.name = "北京", -}; -ef_set_struct("张三学生", &orignal_student, stu_set_cb); - -/* 获取结构体类型环境变量 */ -Student *student; -ef_get_struct("张三学生", student, stu_get_cb); - -/* 打印获取到的结构体内容 */ -printf("姓名:%s 籍贯:%s \n", student->name, student->hometown.name); - -/* 释放获取结构体类型环境变量过程中开辟的动态内存 */ -s2jHook.free_fn(student); -``` \ No newline at end of file diff --git a/easyflash/plugins/types/ef_types.c b/easyflash/plugins/types/ef_types.c deleted file mode 100644 index 8c516b9..0000000 --- a/easyflash/plugins/types/ef_types.c +++ /dev/null @@ -1,395 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2016, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Types plugin source code for this library. - * Created on: 2015-12-16 - */ - -#include "ef_types.h" -#include -#include - -/** - * array support types - */ -typedef enum { - EF_ARRAY_TYPES_BOOL, - EF_ARRAY_TYPES_CHAR, - EF_ARRAY_TYPES_SHORT, - EF_ARRAY_TYPES_INT, - EF_ARRAY_TYPES_LONG, - EF_ARRAY_TYPES_FLOAT, - EF_ARRAY_TYPES_DOUBLE, - EF_ARRAY_TYPES_STRING, -} ef_array_types; - -/** - * EasyFlash types plugin initialize. - * - * @param hook Memory management hook function. - * If hook is null or not call this function, then use free and malloc of C library. - */ -void ef_types_init(S2jHook *hook) { - s2j_init(hook); -} - -bool ef_get_bool(const char *key) { - char *value = ef_get_env(key); - if(value) { - return atoi(value) == 0 ? false : true; - } else { - EF_INFO("Couldn't find this ENV(%s)!\n", key); - return false; - } -} - -char ef_get_char(const char *key) { - return ef_get_long(key); -} - -short ef_get_short(const char *key) { - return ef_get_long(key); -} - -int ef_get_int(const char *key) { - return ef_get_long(key); -} - -long ef_get_long(const char *key) { - char *value = ef_get_env(key); - if(value) { - return atol(value); - } else { - EF_INFO("Couldn't find this ENV(%s)!\n", key); - return NULL; - } -} - -float ef_get_float(const char *key) { - return ef_get_double(key); -} - -double ef_get_double(const char *key) { - char *value = ef_get_env(key); - if(value) { - return atof(value); - } else { - EF_INFO("Couldn't find this ENV(%s)!\n", key); - return NULL; - } -} - -/** - * get array ENV value - * - * @param key ENV name - * @param value returned ENV value - * @param types ENV array's type - */ -static void ef_get_array(const char *key, void *value, ef_array_types types) { - char *char_value = ef_get_env(key); - cJSON *array; - size_t size, i; - - EF_ASSERT(value); - - if (char_value) { - array = cJSON_Parse(char_value); - if (array) { - size = cJSON_GetArraySize(array); - for (i = 0; i < size; i++) { - switch (types) { - case EF_ARRAY_TYPES_BOOL: { - *((bool *) value + i) = cJSON_GetArrayItem(array, i)->valueint; - break; - } - case EF_ARRAY_TYPES_CHAR: { - *((char *) value + i) = cJSON_GetArrayItem(array, i)->valueint; - break; - } - case EF_ARRAY_TYPES_SHORT: { - *((short *) value + i) = cJSON_GetArrayItem(array, i)->valueint; - break; - } - case EF_ARRAY_TYPES_INT: { - *((int *) value + i) = cJSON_GetArrayItem(array, i)->valueint; - break; - } - case EF_ARRAY_TYPES_LONG: { - *((long *) value + i) = cJSON_GetArrayItem(array, i)->valueint; - break; - } - case EF_ARRAY_TYPES_FLOAT: { - *((float *) value + i) = cJSON_GetArrayItem(array, i)->valuedouble; - break; - } - case EF_ARRAY_TYPES_DOUBLE: { - *((double *) value + i) = cJSON_GetArrayItem(array, i)->valuedouble; - break; - } - case EF_ARRAY_TYPES_STRING: { - *((char **) value + i) = cJSON_GetArrayItem(array, i)->valuestring; - break; - } - } - } - } else { - EF_INFO("This ENV(%s) value type has error!\n", key); - } - cJSON_Delete(array); - } else { - EF_INFO("Couldn't find this ENV(%s)!\n", key); - } -} - -void ef_get_bool_array(const char *key, bool *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_BOOL); -} - -void ef_get_char_array(const char *key, char *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_CHAR); -} - -void ef_get_short_array(const char *key, short *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_SHORT); -} - -void ef_get_int_array(const char *key, int *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_INT); -} - -void ef_get_long_array(const char *key, long *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_LONG); -} - -void ef_get_float_array(const char *key, float *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_FLOAT); -} - -void ef_get_double_array(const char *key, double *value) { - ef_get_array(key, value, EF_ARRAY_TYPES_DOUBLE); -} - -void ef_get_string_array(const char *key, char **value) { - ef_get_array(key, value, EF_ARRAY_TYPES_STRING); -} - -/** - * get structure ENV value - * - * @param key ENV name - * @param get_cb get structure callback function. - * You can use json to structure function which in the struct2json lib(https://github.com/armink/struct2json). - * - * @return value returned structure ENV value pointer. @note The returned value will malloc new ram. - * You must free the value then used finish. - */ -void *ef_get_struct(const char *key, ef_types_get_cb get_cb) { - char *char_value = ef_get_env(key); - cJSON *json_value = cJSON_Parse(char_value); - void *value = NULL; - - if (json_value) { - value = get_cb(json_value); - cJSON_Delete(json_value); - } - return value; -} - -EfErrCode ef_set_bool(const char *key, bool value) { - char char_value[2] = { 0 }; - if (!value) { - strcpy(char_value, "0"); - } else { - strcpy(char_value, "1"); - } - return ef_set_env(key, char_value); -} - -EfErrCode ef_set_char(const char *key, char value) { - return ef_set_long(key, value); -} - -EfErrCode ef_set_short(const char *key, short value) { - return ef_set_long(key, value); -} - -EfErrCode ef_set_int(const char *key, int value) { - return ef_set_long(key, value); -} - -EfErrCode ef_set_long(const char *key, long value) { - char char_value[21] = { 0 }; - - snprintf(char_value, 20, "%ld", value); - - return ef_set_env(key, char_value); -} - -EfErrCode ef_set_float(const char *key, float value) { - return ef_set_double(key, value); -} - -EfErrCode ef_set_double(const char *key, double value) { - char char_value[21] = { 0 }; - - snprintf(char_value, 20, "%lf", value); - - return ef_set_env(key, char_value); -} - -/** - * set array ENV value - * - * @param key ENV name - * @param value ENV value - * @param len array length - * @param types ENV array's type - * - * @return ENV set result - */ -static EfErrCode ef_set_array(const char *key, void *value, size_t len, ef_array_types types) { - char *char_value = NULL; - cJSON *array = NULL, *array_item = NULL; - size_t i; - EfErrCode result = EF_NO_ERR; - - EF_ASSERT(value); - - array = cJSON_CreateArray(); - if (array) { - for (i = 0; i < len; i++) { - switch (types) { - case EF_ARRAY_TYPES_BOOL: { - array_item = cJSON_CreateBool(*((bool *) value + i)); - break; - } - case EF_ARRAY_TYPES_CHAR: { - array_item = cJSON_CreateNumber(*((char *) value + i)); - break; - } - case EF_ARRAY_TYPES_SHORT: { - array_item = cJSON_CreateNumber(*((short *) value + i)); - break; - } - case EF_ARRAY_TYPES_INT: { - array_item = cJSON_CreateNumber(*((int *) value + i)); - break; - } - case EF_ARRAY_TYPES_LONG: { - array_item = cJSON_CreateNumber(*((long *) value + i)); - break; - } - case EF_ARRAY_TYPES_FLOAT: { - array_item = cJSON_CreateNumber(*((float *) value + i)); - break; - } - case EF_ARRAY_TYPES_DOUBLE: { - array_item = cJSON_CreateNumber(*((double *) value + i)); - break; - } - case EF_ARRAY_TYPES_STRING: { - array_item = cJSON_CreateString(*((char **) value + i)); - break; - } - default: - /* the types parameter has error */ - EF_ASSERT(0); - } - if (array_item) { - cJSON_AddItemToArray(array, array_item); - } else { - result = EF_ENV_FULL; - EF_INFO("Memory full!\n", key); - break; - } - } - char_value = cJSON_PrintUnformatted(array); - if (char_value) { - result = ef_set_env(key, char_value); - s2jHook.free_fn(char_value); - } else { - result = EF_ENV_FULL; - EF_INFO("Memory full!\n", key); - } - cJSON_Delete(array); - } else { - result = EF_ENV_FULL; - EF_INFO("Memory full!\n", key); - } - return result; -} - -EfErrCode ef_set_bool_array(const char *key, bool *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_BOOL); -} - -EfErrCode ef_set_char_array(const char *key, char *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_CHAR); -} - -EfErrCode ef_set_short_array(const char *key, short *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_SHORT); -} - -EfErrCode ef_set_int_array(const char *key, int *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_INT); -} - -EfErrCode ef_set_long_array(const char *key, long *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_LONG); -} - -EfErrCode ef_set_float_array(const char *key, float *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_FLOAT); -} - -EfErrCode ef_set_double_array(const char *key, double *value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_DOUBLE); -} - -EfErrCode ef_set_string_array(const char *key, char **value, size_t len) { - return ef_set_array(key, value, len, EF_ARRAY_TYPES_STRING); -} - -/** - * set structure ENV value - * - * @param key ENV name - * @param value structure ENV value pointer - * @param get_cb set structure callback function. - * You can use structure to json function which in the struct2json lib(https://github.com/armink/struct2json). - */ -EfErrCode ef_set_struct(const char *key, void *value, ef_types_set_cb set_cb) { - EfErrCode result = EF_NO_ERR; - cJSON *json_value = set_cb(value); - char *char_value = cJSON_PrintUnformatted(json_value); - - result = ef_set_env(key, char_value); - - cJSON_Delete(json_value); - s2jHook.free_fn(char_value); - - return result; -} diff --git a/easyflash/plugins/types/ef_types.h b/easyflash/plugins/types/ef_types.h deleted file mode 100644 index f861898..0000000 --- a/easyflash/plugins/types/ef_types.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2016, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: It is an head file for this plugin. You can see all be called functions. - * Created on: 2015-12-16 - */ - -#ifndef EF_TYPES_H_ -#define EF_TYPES_H_ - -#include -#include -#include "struct2json\inc\s2j.h" - -/* EasyFlash types plugin's software version number */ -#define EF_TYPES_SW_VERSION "0.11.03" - -typedef cJSON *(*ef_types_set_cb)(void* struct_obj); -typedef void *(*ef_types_get_cb)(cJSON* json_obj); - -void ef_types_init(S2jHook *hook); -bool ef_get_bool(const char *key); -char ef_get_char(const char *key); -short ef_get_short(const char *key); -int ef_get_int(const char *key); -long ef_get_long(const char *key); -float ef_get_float(const char *key); -double ef_get_double(const char *key); -void ef_get_bool_array(const char *key, bool *value); -void ef_get_char_array(const char *key, char *value); -void ef_get_short_array(const char *key, short *value); -void ef_get_int_array(const char *key, int *value); -void ef_get_long_array(const char *key, long *value); -void ef_get_float_array(const char *key, float *value); -void ef_get_double_array(const char *key, double *value); -void ef_get_string_array(const char *key, char **value); -void *ef_get_struct(const char *key, ef_types_get_cb get_cb); -EfErrCode ef_set_bool(const char *key, bool value); -EfErrCode ef_set_char(const char *key, char value); -EfErrCode ef_set_short(const char *key, short value); -EfErrCode ef_set_int(const char *key, int value); -EfErrCode ef_set_long(const char *key, long value); -EfErrCode ef_set_float(const char *key, float value); -EfErrCode ef_set_double(const char *key, double value); -EfErrCode ef_set_bool_array(const char *key, bool *value, size_t len); -EfErrCode ef_set_char_array(const char *key, char *value, size_t len); -EfErrCode ef_set_short_array(const char *key, short *value, size_t len); -EfErrCode ef_set_int_array(const char *key, int *value, size_t len); -EfErrCode ef_set_long_array(const char *key, long *value, size_t len); -EfErrCode ef_set_float_array(const char *key, float *value, size_t len); -EfErrCode ef_set_double_array(const char *key, double *value, size_t len); -EfErrCode ef_set_string_array(const char *key, char **value, size_t len); -EfErrCode ef_set_struct(const char *key, void *value, ef_types_set_cb set_cb); - -#endif /* EF_TYPES_H_ */ diff --git a/easyflash/plugins/types/struct2json/inc/cJSON.h b/easyflash/plugins/types/struct2json/inc/cJSON.h deleted file mode 100644 index 634fe22..0000000 --- a/easyflash/plugins/types/struct2json/inc/cJSON.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifndef cJSON__h -#define cJSON__h - -#include - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* cJSON Types: */ -#define cJSON_False 0 -#define cJSON_True 1 -#define cJSON_NULL 2 -#define cJSON_Number 3 -#define cJSON_String 4 -#define cJSON_Array 5 -#define cJSON_Object 6 - -#define cJSON_IsReference 256 -#define cJSON_StringIsConst 512 - -/* The cJSON structure: */ -typedef struct cJSON { - struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ - struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ - - int type; /* The type of the item, as above. */ - - char *valuestring; /* The item's string, if type==cJSON_String */ - int valueint; /* The item's number, if type==cJSON_Number */ - double valuedouble; /* The item's number, if type==cJSON_Number */ - - char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ -} cJSON; - -typedef struct cJSON_Hooks { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} cJSON_Hooks; - -/* Supply malloc, realloc and free functions to cJSON */ -extern void cJSON_InitHooks(cJSON_Hooks* hooks); - - -/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ -extern cJSON *cJSON_Parse(const char *value); -/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ -extern char *cJSON_Print(cJSON *item); -/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ -extern char *cJSON_PrintUnformatted(cJSON *item); -/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ -extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); -/* Delete a cJSON entity and all subentities. */ -extern void cJSON_Delete(cJSON *c); - -/* Returns the number of items in an array (or object). */ -extern int cJSON_GetArraySize(cJSON *array); -/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ -extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); -/* Get item "string" from object. Case insensitive. */ -extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); -extern int cJSON_HasObjectItem(cJSON *object,const char *string); -/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ -extern const char *cJSON_GetErrorPtr(void); - -/* These calls create a cJSON item of the appropriate type. */ -extern cJSON *cJSON_CreateNull(void); -extern cJSON *cJSON_CreateTrue(void); -extern cJSON *cJSON_CreateFalse(void); -extern cJSON *cJSON_CreateBool(int b); -extern cJSON *cJSON_CreateNumber(double num); -extern cJSON *cJSON_CreateString(const char *string); -extern cJSON *cJSON_CreateArray(void); -extern cJSON *cJSON_CreateObject(void); - -/* These utilities create an Array of count items. */ -extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); -extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); -extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); -extern cJSON *cJSON_CreateStringArray(const char **strings,int count); - -/* Append item to the specified array/object. */ -extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); -extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ -/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ -extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); -extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); - -/* Remove/Detatch items from Arrays/Objects. */ -extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); -extern void cJSON_DeleteItemFromArray(cJSON *array,int which); -extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); -extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); - -/* Update array items. */ -extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ -extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); -extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); - -/* Duplicate a cJSON item */ -extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); -/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will -need to be released. With recurse!=0, it will duplicate any children connected to the item. -The item->next and ->prev pointers are always zero on return from Duplicate. */ - -/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ -extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); - -extern void cJSON_Minify(char *json); - -/* Macros for creating things quickly. */ -#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) -#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) -#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) -#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) -#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) -#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) - -/* When assigning an integer value, it needs to be propagated to valuedouble too. */ -#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) -#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) - -/* Macro for iterating over an array */ -#define cJSON_ArrayForEach(pos, head) for(pos = (head)->child; pos != NULL; pos = pos->next) - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/easyflash/plugins/types/struct2json/inc/s2j.h b/easyflash/plugins/types/struct2json/inc/s2j.h deleted file mode 100644 index 73ec4df..0000000 --- a/easyflash/plugins/types/struct2json/inc/s2j.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of the struct2json Library. - * - * Copyright (c) 2015, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: It is an head file for this library. You can see all be called functions. - * Created on: 2015-10-14 - */ - -#ifndef __S2J_H__ -#define __S2J_H__ - -#include -#include -#include "s2jdef.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* struct2json software version number */ -#define S2J_SW_VERSION "1.0.2" - -/* Create JSON object */ -#define s2j_create_json_obj(json_obj) \ - S2J_CREATE_JSON_OBJECT(json_obj) - -/* Delete JSON object */ -#define s2j_delete_json_obj(json_obj) \ - S2J_DELETE_JSON_OBJECT(json_obj) - -/* Set basic type element for JSON object */ -#define s2j_json_set_basic_element(to_json, from_struct, type, element) \ - S2J_JSON_SET_BASIC_ELEMENT(to_json, from_struct, type, element) - -/* Set array type element for JSON object */ -#define s2j_json_set_array_element(to_json, from_struct, type, element, size) \ - S2J_JSON_SET_ARRAY_ELEMENT(to_json, from_struct, type, element, size) - -/* Set child structure type element for JSON object */ -#define s2j_json_set_struct_element(child_json, to_json, child_struct, from_struct, type, element) \ - S2J_JSON_SET_STRUCT_ELEMENT(child_json, to_json, child_struct, from_struct, type, element) - -/* Create structure object */ -#define s2j_create_struct_obj(struct_obj, type) \ - S2J_CREATE_STRUCT_OBJECT(struct_obj, type) - -/* Delete structure object */ -#define s2j_delete_struct_obj(struct_obj) \ - S2J_DELETE_STRUCT_OBJECT(struct_obj) - -/* Get basic type element for structure object */ -#define s2j_struct_get_basic_element(to_struct, from_json, type, element) \ - S2J_STRUCT_GET_BASIC_ELEMENT(to_struct, from_json, type, element) - -/* Get array type element for structure object */ -#define s2j_struct_get_array_element(to_struct, from_json, type, element) \ - S2J_STRUCT_GET_ARRAY_ELEMENT(to_struct, from_json, type, element) - -/* Get child structure type element for structure object */ -#define s2j_struct_get_struct_element(child_struct, to_struct, child_json, from_json, type, element) \ - S2J_STRUCT_GET_STRUCT_ELEMENT(child_struct, to_struct, child_json, from_json, type, element) - -/* s2j.c */ -extern S2jHook s2jHook; -void s2j_init(S2jHook *hook); - -#ifdef __cplusplus -} -#endif - -#endif /* __S2J_H__ */ diff --git a/easyflash/plugins/types/struct2json/inc/s2jdef.h b/easyflash/plugins/types/struct2json/inc/s2jdef.h deleted file mode 100644 index be445ac..0000000 --- a/easyflash/plugins/types/struct2json/inc/s2jdef.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of the struct2json Library. - * - * Copyright (c) 2015, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: It is an head file for this library. - * Created on: 2015-10-14 - */ - -#ifndef __S2JDEF_H__ -#define __S2JDEF_H__ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - void *(*malloc_fn)(size_t sz); - void (*free_fn)(void *ptr); -} S2jHook, *S2jHook_t; - -#define S2J_STRUCT_GET_int_ELEMENT(to_struct, from_json, _element) \ - json_temp = cJSON_GetObjectItem(from_json, #_element); \ - if (json_temp) (to_struct)->_element = json_temp->valueint; - -#define S2J_STRUCT_GET_string_ELEMENT(to_struct, from_json, _element) \ - json_temp = cJSON_GetObjectItem(from_json, #_element); \ - if (json_temp) strcpy((to_struct)->_element, json_temp->valuestring); - -#define S2J_STRUCT_GET_double_ELEMENT(to_struct, from_json, _element) \ - json_temp = cJSON_GetObjectItem(from_json, #_element); \ - if (json_temp) (to_struct)->_element = json_temp->valuedouble; - -#define S2J_STRUCT_ARRAY_GET_int_ELEMENT(to_struct, from_json, _element, index) \ - (to_struct)->_element[index] = from_json->valueint; - -#define S2J_STRUCT_ARRAY_GET_string_ELEMENT(to_struct, from_json, _element, index) \ - strcpy((to_struct)->_element[index], from_json->valuestring); - -#define S2J_STRUCT_ARRAY_GET_double_ELEMENT(to_struct, from_json, _element, index) \ - (to_struct)->_element[index] = from_json->valuedouble; - -#define S2J_STRUCT_ARRAY_GET_ELEMENT(to_struct, from_json, type, _element, index) \ - S2J_STRUCT_ARRAY_GET_##type##_ELEMENT(to_struct, from_json, _element, index) - -#define S2J_JSON_SET_int_ELEMENT(to_json, from_struct, _element) \ - cJSON_AddNumberToObject(to_json, #_element, (from_struct)->_element); - -#define S2J_JSON_SET_double_ELEMENT(to_json, from_struct, _element) \ - cJSON_AddNumberToObject(to_json, #_element, (from_struct)->_element); - -#define S2J_JSON_SET_string_ELEMENT(to_json, from_struct, _element) \ - cJSON_AddStringToObject(to_json, #_element, (from_struct)->_element); - -#define S2J_JSON_ARRAY_SET_int_ELEMENT(to_json, from_struct, _element, index) \ - cJSON_AddItemToArray(to_json, cJSON_CreateNumber((from_struct)->_element[index])); - -#define S2J_JSON_ARRAY_SET_double_ELEMENT(to_json, from_struct, _element, index) \ - cJSON_AddItemToArray(to_json, cJSON_CreateNumber((from_struct)->_element[index])); - -#define S2J_JSON_ARRAY_SET_string_ELEMENT(to_json, from_struct, _element, index) \ - cJSON_AddItemToArray(to_json, cJSON_CreateString((from_struct)->_element[index])); - -#define S2J_JSON_ARRAY_SET_ELEMENT(to_json, from_struct, type, _element, index) \ - S2J_JSON_ARRAY_SET_##type##_ELEMENT(to_json, from_struct, _element, index) - - -#define S2J_CREATE_JSON_OBJECT(json_obj) \ - cJSON *json_obj = cJSON_CreateObject(); - -#define S2J_DELETE_JSON_OBJECT(json_obj) \ - cJSON_Delete(json_obj); - -#define S2J_JSON_SET_BASIC_ELEMENT(to_json, from_struct, type, _element) \ - S2J_JSON_SET_##type##_ELEMENT(to_json, from_struct, _element) - -#define S2J_JSON_SET_ARRAY_ELEMENT(to_json, from_struct, type, _element, size) \ - { \ - cJSON *array; \ - size_t index = 0; \ - array = cJSON_CreateArray(); \ - if (array) { \ - while (index < size) { \ - S2J_JSON_ARRAY_SET_ELEMENT(array, from_struct, type, _element, index++); \ - } \ - cJSON_AddItemToObject(to_json, #_element, array); \ - } \ - } - -#define S2J_JSON_SET_STRUCT_ELEMENT(child_json, to_json, child_struct, from_struct, type, _element) \ - type *child_struct = &((from_struct)->_element); \ - cJSON *child_json = cJSON_CreateObject(); \ - if (child_json) cJSON_AddItemToObject(to_json, #_element, child_json); - -#define S2J_CREATE_STRUCT_OBJECT(struct_obj, type) \ - cJSON *json_temp; \ - type *struct_obj = s2jHook.malloc_fn(sizeof(type)); \ - if (struct_obj) memset(struct_obj, 0, sizeof(type)); - -#define S2J_DELETE_STRUCT_OBJECT(struct_obj) \ - s2jHook.free_fn(struct_obj); - -#define S2J_STRUCT_GET_BASIC_ELEMENT(to_struct, from_json, type, _element) \ - S2J_STRUCT_GET_##type##_ELEMENT(to_struct, from_json, _element) - -#define S2J_STRUCT_GET_ARRAY_ELEMENT(to_struct, from_json, type, _element) \ - { \ - cJSON *array, *array_element; \ - size_t index = 0, size = 0; \ - array = cJSON_GetObjectItem(from_json, #_element); \ - if (array) { \ - size = cJSON_GetArraySize(array); \ - while (index < size) { \ - array_element = cJSON_GetArrayItem(array, index); \ - if (array_element) S2J_STRUCT_ARRAY_GET_ELEMENT(to_struct, array_element, type, _element, index++); \ - } \ - } \ - } - -#define S2J_STRUCT_GET_STRUCT_ELEMENT(child_struct, to_struct, child_json, from_json, type, _element) \ - type *child_struct = &((to_struct)->_element); \ - cJSON *child_json = cJSON_GetObjectItem(from_json, #_element); - -#ifdef __cplusplus -} -#endif - -#endif /* __S2JDEF_H__ */ diff --git a/easyflash/plugins/types/struct2json/readme.md b/easyflash/plugins/types/struct2json/readme.md deleted file mode 100644 index dea28be..0000000 --- a/easyflash/plugins/types/struct2json/readme.md +++ /dev/null @@ -1,61 +0,0 @@ -# C缁撴瀯浣撲笌 JSON 蹇熶簰杞簱 - ---- - -## struct2json - -[struct2json](https://github.com/armink/struct2json) 鏄竴涓紑婧愮殑C缁撴瀯浣撲笌 JSON 蹇熶簰杞簱锛屽畠鍙互蹇熷疄鐜 **缁撴瀯浣撳璞** 涓 **JSON 瀵硅薄** 涔嬮棿搴忓垪鍖栧強鍙嶅簭鍒楀寲瑕佹眰銆傚揩閫熴佺畝娲佺殑 API 璁捐锛屽ぇ澶ч檷浣庣洿鎺ヤ娇鐢 JSON 瑙f瀽搴撴潵瀹炵幇姝ょ被鍔熻兘鐨勪唬鐮佸鏉傚害銆 - -## 璧锋簮 - -鎶婇潰鍚戝璞¤璁″簲鐢ㄥ埌C璇█涓紝鏄綋涓嬪緢娴佽鐨勮璁℃濇兂銆傜敱浜嶤璇█涓病鏈夌被锛屾墍浠ヤ竴鑸娇鐢ㄧ粨鏋勪綋 `struct` 鍏呭綋绫伙紝閭d箞缁撴瀯浣撳彉閲忓氨鏄璞°傛湁浜嗗璞′箣鍚庯紝寰堝鏃跺欓渶瑕佽冭檻瀵硅薄鐨勫簭鍒楀寲鍙婂弽搴忓垪鍖栭棶棰樸侰璇█涓嶅儚寰堝楂樼骇璇█鎷ユ湁鍙嶅皠绛夋満鍒讹紝浣垮緱瀵硅薄搴忓垪鍖栧強鍙嶅簭鍒楀寲琚師鐢熺殑鏀寔銆 - -瀵逛簬C璇█鏉ヨ锛屽簭鍒楀寲涓 JSON 瀛楃涓叉槸涓笉閿欑殑閫夋嫨锛屾墍浠ュ氨寰椾娇鐢 [cJSON](https://github.com/kbranigan/cJSON) 杩欑被 JSON 瑙f瀽搴擄紝浣嗘槸浣跨敤鍚庣殑浠g爜鍐椾綑涓旈昏緫鎬у樊锛屾墍浠ヨ悓鐢熷cJSON搴撹繘琛屼簩娆″皝瑁咃紝瀹炵幇涓涓 struct 涓 JSON 涔嬮棿蹇熶簰杞殑搴撱 struct2json 灏辫癁鐢熶簬姝ゃ備笅闈㈡槸 struct2json 涓昏浣跨敤鍦烘櫙锛 - -- **鎸佷箙鍖** 锛氱粨鏋勪綋瀵硅薄搴忓垪鍖栦负 JSON 瀵硅薄鍚庯紝鍙洿鎺ヤ繚瀛樿嚦鏂囦欢銆丗lash锛屽疄鐜板缁撴瀯浣撳璞$殑鎺夌數瀛樺偍锛 -- **閫氫俊** 锛氶珮绾ц瑷瀵笿SON鏀寔鐨勫緢鍙嬪ソ锛屼緥濡傦細 Javascript銆丟roovy 灏卞 JSON 鍏锋湁鍘熺敓鐨勬敮鎸侊紝鎵浠 JSON 涔熷彲浣滀负C璇█涓庡叾浠栬瑷杞欢涔嬮棿鐨勯氫俊鍗忚鏍煎紡鍙婂璞′紶閫掓牸寮忥紱 -- **鍙鍖** 锛氬簭鍒楀寲涓 JSON 鍚庣殑瀵硅薄锛屽彲浠ユ洿鍔犵洿瑙傜殑灞曠ず鍒版帶鍒跺彴鎴栬 UI 涓婏紝鍙敤浜庝骇鍝佽皟璇曘佷骇鍝佷簩娆″紑鍙戠瓑鍦烘櫙锛 - -## 濡備綍浣跨敤 - -### 澹版槑缁撴瀯浣 - -濡備笅澹版槑浜嗕袱涓粨鏋勪綋锛岀粨鏋勪綋 `Hometown` 鏄粨鏋勪綋 `Student` 鐨勫瓙缁撴瀯浣 - -```C -/* 绫嶈疮 */ -typedef struct { - char name[16]; -} Hometown; - -/* 瀛︾敓 */ -typedef struct { - uint8_t id; - uint8_t score[8]; - char name[10]; - double weight; - Hometown hometown; -} Student; -``` - -### 灏嗙粨鏋勪綋瀵硅薄搴忓垪鍖栦负 JSON 瀵硅薄 - -|浣跨敤鍓嶏紙[婧愭枃浠禲(https://github.com/armink/struct2json/blob/master/docs/zh/assets/not_use_struct2json.c)锛墊浣跨敤鍚庯紙[婧愭枃浠禲(https://github.com/armink/struct2json/blob/master/docs/zh/assets/used_struct2json.c)锛墊 -|:-----:|:-----:| -|![缁撴瀯浣撹浆JSON-浣跨敤鍓峕(https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/not_use_struct2json.png)| ![缁撴瀯浣撹浆JSON-浣跨敤鍚嶿(https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/used_struct2json.png)| - -### 灏 JSON 瀵硅薄鍙嶅簭鍒楀寲涓虹粨鏋勪綋瀵硅薄 - -|浣跨敤鍓嶏紙[婧愭枃浠禲(https://github.com/armink/struct2json/blob/master/docs/zh/assets/not_use_struct2json_for_json.c)锛墊浣跨敤鍚庯紙[婧愭枃浠禲(https://github.com/armink/struct2json/blob/master/docs/zh/assets/used_struct2json_for_json.c)锛墊 -|:-----:|:-----:| -|![JSON杞粨鏋勪綋-浣跨敤鍓峕(https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/not_use_struct2json_for_json.png)| ![JSON杞粨鏋勪綋-浣跨敤鍚嶿(https://git.oschina.net/Armink/struct2json/raw/master/docs/zh/images/used_struct2json_for_json.png)| - -娆㈣繋澶у **fork and pull request**([Github](https://github.com/armink/struct2json)|[OSChina](http://git.oschina.net/armink/struct2json)|[Coding](https://coding.net/u/armink/p/struct2json/git)) 銆傚鏋滆寰楄繖涓紑婧愰」鐩緢璧烇紝鍙互鐐瑰嚮[椤圭洰涓婚〉](https://github.com/armink/struct2json) 鍙充笂瑙掔殑**Star**锛屽悓鏃舵妸瀹冩帹鑽愮粰鏇村鏈夐渶瑕佺殑鏈嬪弸銆 - -## 鏂囨。 - -鍏蜂綋鍐呭鍙傝僛`\docs\zh\`](https://github.com/armink/struct2json/tree/master/docs/zh)涓嬬殑鏂囦欢銆傚姟蹇呬繚璇佸湪 **闃呰鏂囨。** 鍚庡啀浣跨敤銆 - -## 璁稿彲 - -MIT Copyright (c) armink.ztl@gmail.com diff --git a/easyflash/plugins/types/struct2json/src/cJSON.c b/easyflash/plugins/types/struct2json/src/cJSON.c deleted file mode 100644 index 67afd8f..0000000 --- a/easyflash/plugins/types/struct2json/src/cJSON.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - Copyright (c) 2009 Dave Gamble - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -/* cJSON */ -/* JSON parser in C. */ - -#include -#include -#include -#include -#include -#include -#include -#include "cJSON.h" - -static const char *ep; - -const char *cJSON_GetErrorPtr(void) {return ep;} - -static int cJSON_strcasecmp(const char *s1,const char *s2) -{ - if (!s1) return (s1==s2)?0:1;if (!s2) return 1; - for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; - return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); -} - -static void *(*cJSON_malloc)(size_t sz) = malloc; -static void (*cJSON_free)(void *ptr) = free; - -static char* cJSON_strdup(const char* str) -{ - size_t len; - char* copy; - - len = strlen(str) + 1; - if ((copy = (char*)cJSON_malloc(len)) == NULL) return 0; - memcpy(copy,str,len); - return copy; -} - -void cJSON_InitHooks(cJSON_Hooks* hooks) -{ - if (!hooks) { /* Reset hooks */ - cJSON_malloc = malloc; - cJSON_free = free; - return; - } - - cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; - cJSON_free = (hooks->free_fn)?hooks->free_fn:free; -} - -/* Internal constructor. */ -static cJSON *cJSON_New_Item(void) -{ - cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); - if (node) memset(node,0,sizeof(cJSON)); - return node; -} - -/* Delete a cJSON structure. */ -void cJSON_Delete(cJSON *c) -{ - cJSON *next; - while (c) - { - next=c->next; - if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); - if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); - if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); - cJSON_free(c); - c=next; - } -} - -/* Parse the input text to generate a number, and populate the result into item. */ -static const char *parse_number(cJSON *item,const char *num) -{ - double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; - - if (*num=='-') sign=-1,num++; /* Has sign? */ - if (*num=='0') num++; /* is zero */ - if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ - if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ - if (*num=='e' || *num=='E') /* Exponent? */ - { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ - while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ - } - - n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ - - item->valuedouble=n; - item->valueint=(int)n; - item->type=cJSON_Number; - return num; -} - -static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } - -typedef struct {char *buffer; int length; int offset; } printbuffer; - -static char* ensure(printbuffer *p,int needed) -{ - char *newbuffer;int newsize; - if (!p || !p->buffer) return 0; - needed+=p->offset; - if (needed<=p->length) return p->buffer+p->offset; - - newsize=pow2gt(needed); - newbuffer=(char*)cJSON_malloc(newsize); - if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} - if (newbuffer) memcpy(newbuffer,p->buffer,p->length); - cJSON_free(p->buffer); - p->length=newsize; - p->buffer=newbuffer; - return newbuffer+p->offset; -} - -static int update(printbuffer *p) -{ - char *str; - if (!p || !p->buffer) return 0; - str=p->buffer+p->offset; - return p->offset+strlen(str); -} - -/* Render the number nicely from the given item into a string. */ -static char *print_number(cJSON *item,printbuffer *p) -{ - char *str=0; - double d=item->valuedouble; - if (d==0) - { - if (p) str=ensure(p,2); - else str=(char*)cJSON_malloc(2); /* special case for 0. */ - if (str) strcpy(str,"0"); - } - else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) - { - if (p) str=ensure(p,21); - else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ - if (str) sprintf(str,"%d",item->valueint); - } - else - { - if (p) str=ensure(p,64); - else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ - if (str) - { - if (fpclassify(d) != FP_ZERO && !isnormal(d)) sprintf(str,"null"); - else if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60) sprintf(str,"%.0f",d); - else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); - else sprintf(str,"%f",d); - } - } - return str; -} - -static unsigned parse_hex4(const char *str) -{ - unsigned h=0; - if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; - h=h<<4;str++; - if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; - h=h<<4;str++; - if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; - h=h<<4;str++; - if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; - return h; -} - -/* Parse the input text into an unescaped cstring, and populate item. */ -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; -static const char *parse_string(cJSON *item,const char *str) -{ - const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; - if (*str!='\"') {ep=str;return 0;} /* not a string! */ - - while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ - - out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ - if (!out) return 0; - - ptr=str+1;ptr2=out; - while (*ptr!='\"' && *ptr) - { - if (*ptr!='\\') *ptr2++=*ptr++; - else - { - ptr++; - switch (*ptr) - { - case 'b': *ptr2++='\b'; break; - case 'f': *ptr2++='\f'; break; - case 'n': *ptr2++='\n'; break; - case 'r': *ptr2++='\r'; break; - case 't': *ptr2++='\t'; break; - case 'u': /* transcode utf16 to utf8. */ - uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ - - if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ - - if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ - { - if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ - uc2=parse_hex4(ptr+3);ptr+=6; - if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ - uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); - } - - len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; - - switch (len) { - case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; - case 1: *--ptr2 =(uc | firstByteMark[len]); - } - ptr2+=len; - break; - default: *ptr2++=*ptr; break; - } - ptr++; - } - } - *ptr2=0; - if (*ptr=='\"') ptr++; - item->valuestring=out; - item->type=cJSON_String; - return ptr; -} - -/* Render the cstring provided to an escaped version that can be printed. */ -static char *print_string_ptr(const char *str,printbuffer *p) -{ - const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; - - for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; - if (!flag) - { - len=ptr-str; - if (p) out=ensure(p,len+3); - else out=(char*)cJSON_malloc(len+3); - if (!out) return 0; - ptr2=out;*ptr2++='\"'; - strcpy(ptr2,str); - ptr2[len]='\"'; - ptr2[len+1]=0; - return out; - } - - if (!str) - { - if (p) out=ensure(p,3); - else out=(char*)cJSON_malloc(3); - if (!out) return 0; - strcpy(out,"\"\""); - return out; - } - ptr=str;while (('\0' != (token=*ptr)) && ++len) {if (NULL != strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} - - if (p) out=ensure(p,len+3); - else out=(char*)cJSON_malloc(len+3); - if (!out) return 0; - - ptr2=out;ptr=str; - *ptr2++='\"'; - while (*ptr) - { - if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; - else - { - *ptr2++='\\'; - switch (token=*ptr++) - { - case '\\': *ptr2++='\\'; break; - case '\"': *ptr2++='\"'; break; - case '\b': *ptr2++='b'; break; - case '\f': *ptr2++='f'; break; - case '\n': *ptr2++='n'; break; - case '\r': *ptr2++='r'; break; - case '\t': *ptr2++='t'; break; - default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ - } - } - } - *ptr2++='\"';*ptr2++=0; - return out; -} -/* Invote print_string_ptr (which is useful) on an item. */ -static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} - -/* Predeclare these prototypes. */ -static const char *parse_value(cJSON *item,const char *value); -static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); -static const char *parse_array(cJSON *item,const char *value); -static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); -static const char *parse_object(cJSON *item,const char *value); -static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); - -/* Utility to jump whitespace and cr/lf */ -static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} - -/* Parse an object - create a new root, and populate. */ -cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) -{ - const char *end=0; - cJSON *c=cJSON_New_Item(); - ep=0; - if (!c) return 0; /* memory fail */ - - end=parse_value(c,skip(value)); - if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ - - /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ - if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} - if (return_parse_end) *return_parse_end=end; - return c; -} -/* Default options for cJSON_Parse */ -cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} - -/* Render a cJSON item/entity/structure to text. */ -char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} -char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} - -char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) -{ - printbuffer p; - p.buffer=(char*)cJSON_malloc(prebuffer); - p.length=prebuffer; - p.offset=0; - return print_value(item,0,fmt,&p); - //return p.buffer; -} - - -/* Parser core - when encountering text, process appropriately. */ -static const char *parse_value(cJSON *item,const char *value) -{ - if (!value) return 0; /* Fail on null. */ - if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } - if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } - if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } - if (*value=='\"') { return parse_string(item,value); } - if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } - if (*value=='[') { return parse_array(item,value); } - if (*value=='{') { return parse_object(item,value); } - - ep=value;return 0; /* failure. */ -} - -/* Render a value to text. */ -static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) -{ - char *out=0; - if (!item) return 0; - if (p) - { - switch ((item->type)&255) - { - case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} - case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} - case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} - case cJSON_Number: out=print_number(item,p);break; - case cJSON_String: out=print_string(item,p);break; - case cJSON_Array: out=print_array(item,depth,fmt,p);break; - case cJSON_Object: out=print_object(item,depth,fmt,p);break; - } - } - else - { - switch ((item->type)&255) - { - case cJSON_NULL: out=cJSON_strdup("null"); break; - case cJSON_False: out=cJSON_strdup("false");break; - case cJSON_True: out=cJSON_strdup("true"); break; - case cJSON_Number: out=print_number(item,0);break; - case cJSON_String: out=print_string(item,0);break; - case cJSON_Array: out=print_array(item,depth,fmt,0);break; - case cJSON_Object: out=print_object(item,depth,fmt,0);break; - } - } - return out; -} - -/* Build an array from input text. */ -static const char *parse_array(cJSON *item,const char *value) -{ - cJSON *child; - if (*value!='[') {ep=value;return 0;} /* not an array! */ - - item->type=cJSON_Array; - value=skip(value+1); - if (*value==']') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; /* memory fail */ - value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item; - if ((new_item=cJSON_New_Item()) == NULL) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_value(child,skip(value+1))); - if (!value) return 0; /* memory fail */ - } - - if (*value==']') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an array to text */ -static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) -{ - char **entries; - char *out=0,*ptr,*ret;int len=5; - cJSON *child=item->child; - int numentries=0,i=0,fail=0; - size_t tmplen=0; - - /* How many entries in the array? */ - while (child) numentries++,child=child->next; - /* Explicitly handle numentries==0 */ - if (!numentries) - { - if (p) out=ensure(p,3); - else out=(char*)cJSON_malloc(3); - if (out) strcpy(out,"[]"); - return out; - } - - if (p) - { - /* Compose the output array. */ - i=p->offset; - ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; - child=item->child; - while (child && !fail) - { - print_value(child,depth+1,fmt,p); - p->offset=update(p); - if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} - child=child->next; - } - ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; - out=(p->buffer)+i; - } - else - { - /* Allocate an array to hold the values for each */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - memset(entries,0,numentries*sizeof(char*)); - /* Retrieve all the results: */ - child=item->child; - while (child && !fail) - { - ret=print_value(child,depth+1,fmt,0); - entries[i++]=ret; - if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; - child=child->next; - } - - /* If we didn't fail, try to malloc the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - /* If that fails, we fail. */ - if (!out) fail=1; - - /* Handle failure. */ - if (fail) - { - for (i=0;itype=cJSON_Object; - value=skip(value+1); - if (*value=='}') return value+1; /* empty array. */ - - item->child=child=cJSON_New_Item(); - if (!item->child) return 0; - value=skip(parse_string(child,skip(value))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - - while (*value==',') - { - cJSON *new_item; - if ((new_item=cJSON_New_Item()) == NULL) return 0; /* memory fail */ - child->next=new_item;new_item->prev=child;child=new_item; - value=skip(parse_string(child,skip(value+1))); - if (!value) return 0; - child->string=child->valuestring;child->valuestring=0; - if (*value!=':') {ep=value;return 0;} /* fail! */ - value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ - if (!value) return 0; - } - - if (*value=='}') return value+1; /* end of array */ - ep=value;return 0; /* malformed. */ -} - -/* Render an object to text. */ -static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) -{ - char **entries=0,**names=0; - char *out=0,*ptr,*ret,*str;int len=7,i=0,j; - cJSON *child=item->child; - int numentries=0,fail=0; - size_t tmplen=0; - /* Count the number of entries. */ - while (child) numentries++,child=child->next; - /* Explicitly handle empty object case */ - if (!numentries) - { - if (p) out=ensure(p,fmt?depth+4:3); - else out=(char*)cJSON_malloc(fmt?depth+4:3); - if (!out) return 0; - ptr=out;*ptr++='{'; - if (fmt) {*ptr++='\n';for (i=0;ioffset; - len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; - *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; - child=item->child;depth++; - while (child) - { - if (fmt) - { - ptr=ensure(p,depth); if (!ptr) return 0; - for (j=0;joffset+=depth; - } - print_string_ptr(child->string,p); - p->offset=update(p); - - len=fmt?2:1; - ptr=ensure(p,len); if (!ptr) return 0; - *ptr++=':';if (fmt) *ptr++='\t'; - p->offset+=len; - - print_value(child,depth,fmt,p); - p->offset=update(p); - - len=(fmt?1:0)+(child->next?1:0); - ptr=ensure(p,len+1); if (!ptr) return 0; - if (child->next) *ptr++=','; - if (fmt) *ptr++='\n';*ptr=0; - p->offset+=len; - child=child->next; - } - ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; - if (fmt) for (i=0;ibuffer)+i; - } - else - { - /* Allocate space for the names and the objects */ - entries=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!entries) return 0; - names=(char**)cJSON_malloc(numentries*sizeof(char*)); - if (!names) {cJSON_free(entries);return 0;} - memset(entries,0,sizeof(char*)*numentries); - memset(names,0,sizeof(char*)*numentries); - - /* Collect all the results into our arrays: */ - child=item->child;depth++;if (fmt) len+=depth; - while (child && !fail) - { - names[i]=str=print_string_ptr(child->string,0); - entries[i++]=ret=print_value(child,depth,fmt,0); - if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; - child=child->next; - } - - /* Try to allocate the output string */ - if (!fail) out=(char*)cJSON_malloc(len); - if (!out) fail=1; - - /* Handle failure */ - if (fail) - { - for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} -cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} -cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} -int cJSON_HasObjectItem(cJSON *object,const char *string) { - cJSON *c=object->child; - while (c ) - { - if(cJSON_strcasecmp(c->string,string)==0){ - return 1; - } - c=c->next; - } - return 0; -} - -/* Utility for array list handling. */ -static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} -/* Utility for handling references. */ -static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} - -/* Add item to array/object. */ -void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} -void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} -void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} -void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} -void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} - -cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; - if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} -void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} -cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} -void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} - -/* Replace array/object items with new ones. */ -void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} - newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} -void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; - newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; - if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} -void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} - -/* Create basic types: */ -cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} -cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} -cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} -cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} -cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} -cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} -cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} -cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} - -/* Create Arrays: */ -cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} -cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} - -/* Duplication */ -cJSON *cJSON_Duplicate(cJSON *item,int recurse) -{ - cJSON *newitem,*cptr,*nptr=0,*newchild; - /* Bail on bad ptr */ - if (!item) return 0; - /* Create new item */ - newitem=cJSON_New_Item(); - if (!newitem) return 0; - /* Copy over all vars */ - newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; - if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} - if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} - /* If non-recursive, then we're done! */ - if (!recurse) return newitem; - /* Walk the ->next chain for the child. */ - cptr=item->child; - while (cptr) - { - newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ - if (!newchild) {cJSON_Delete(newitem);return 0;} - if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ - else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ - cptr=cptr->next; - } - return newitem; -} - -void cJSON_Minify(char *json) -{ - char *into=json; - while (*json) - { - if (*json==' ') json++; - else if (*json=='\t') json++; /* Whitespace characters. */ - else if (*json=='\r') json++; - else if (*json=='\n') json++; - else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ - else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ - else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ - else *into++=*json++; /* All other characters. */ - } - *into=0; /* and null-terminate. */ -} diff --git a/easyflash/plugins/types/struct2json/src/s2j.c b/easyflash/plugins/types/struct2json/src/s2j.c deleted file mode 100644 index 32ff16e..0000000 --- a/easyflash/plugins/types/struct2json/src/s2j.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the struct2json Library. - * - * Copyright (c) 2015, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Initialize interface for this library. - * Created on: 2015-10-14 - */ - -#include -#include - -S2jHook s2jHook = { - .malloc_fn = malloc, - .free_fn = free, -}; - -/** - * struct2json library initialize - * @note It will initialize cJSON library hooks. - */ -void s2j_init(S2jHook *hook) { - /* initialize cJSON library */ - cJSON_InitHooks((cJSON_Hooks *)hook); - /* initialize hooks */ - if (hook) { - s2jHook.malloc_fn = (hook->malloc_fn) ? hook->malloc_fn : malloc; - s2jHook.free_fn = (hook->free_fn) ? hook->free_fn : free; - } else { - hook->malloc_fn = malloc; - hook->free_fn = free; - } -} diff --git a/easyflash/port/ef_port.c b/easyflash/port/ef_port.c deleted file mode 100644 index 26dc551..0000000 --- a/easyflash/port/ef_port.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2019, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Portable interface for each platform. - * Created on: 2015-01-16 - */ - -#include -#include - -/* default environment variables set for user */ -static const ef_env default_env_set[] = { - -}; - -/** - * Flash port for hardware initialize. - * - * @param default_env default ENV set for user - * @param default_env_size default ENV size - * - * @return result - */ -EfErrCode ef_port_init(ef_env const **default_env, size_t *default_env_size) { - EfErrCode result = EF_NO_ERR; - - *default_env = default_env_set; - *default_env_size = sizeof(default_env_set) / sizeof(default_env_set[0]); - - return result; -} - -/** - * Read data from flash. - * @note This operation's units is word. - * - * @param addr flash address - * @param buf buffer to store read data - * @param size read bytes size - * - * @return result - */ -EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size) { - EfErrCode result = EF_NO_ERR; - - /* You can add your code under here. */ - - return result; -} - -/** - * Erase data on flash. - * @note This operation is irreversible. - * @note This operation's units is different which on many chips. - * - * @param addr flash address - * @param size erase bytes size - * - * @return result - */ -EfErrCode ef_port_erase(uint32_t addr, size_t size) { - EfErrCode result = EF_NO_ERR; - - /* make sure the start address is a multiple of EF_ERASE_MIN_SIZE */ - EF_ASSERT(addr % EF_ERASE_MIN_SIZE == 0); - - /* You can add your code under here. */ - - return result; -} -/** - * Write data to flash. - * @note This operation's units is word. - * @note This operation must after erase. @see flash_erase. - * - * @param addr flash address - * @param buf the write data buffer - * @param size write bytes size - * - * @return result - */ -EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size) { - EfErrCode result = EF_NO_ERR; - - /* You can add your code under here. */ - - return result; -} - -/** - * lock the ENV ram cache - */ -void ef_port_env_lock(void) { - - /* You can add your code under here. */ - -} - -/** - * unlock the ENV ram cache - */ -void ef_port_env_unlock(void) { - - /* You can add your code under here. */ - -} - - -/** - * This function is print flash debug info. - * - * @param file the file which has call this function - * @param line the line number which has call this function - * @param format output format - * @param ... args - * - */ -void ef_log_debug(const char *file, const long line, const char *format, ...) { - -#ifdef PRINT_DEBUG - - va_list args; - - /* args point to the first variable parameter */ - va_start(args, format); - - /* You can add your code under here. */ - - va_end(args); - -#endif - -} - -/** - * This function is print flash routine info. - * - * @param format output format - * @param ... args - */ -void ef_log_info(const char *format, ...) { - va_list args; - - /* args point to the first variable parameter */ - va_start(args, format); - - /* You can add your code under here. */ - - va_end(args); -} -/** - * This function is print flash non-package info. - * - * @param format output format - * @param ... args - */ -void ef_print(const char *format, ...) { - va_list args; - - /* args point to the first variable parameter */ - va_start(args, format); - - /* You can add your code under here. */ - - va_end(args); -} diff --git a/easyflash/src/easyflash.c b/easyflash/src/easyflash.c deleted file mode 100644 index 7455886..0000000 --- a/easyflash/src/easyflash.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2014-2019, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Initialize interface for this library. - * Created on: 2014-09-09 - */ - -/* - * - * This all Backup Area Flash storage index. All used flash area configure is under here. - * |----------------------------| Storage Size - * | Environment variables area | ENV area size @see ENV_AREA_SIZE - * |----------------------------| - * | Saved log area | Log area size @see LOG_AREA_SIZE - * |----------------------------| - * |(IAP)Downloaded application | IAP already downloaded application, unfixed size - * |----------------------------| - * - * @note all area sizes must be aligned with EF_ERASE_MIN_SIZE - * - * The EasyFlash add the NG (Next Generation) mode start from V4.0. All old mode before V4.0, called LEGACY mode. - * - * - NG (Next Generation) mode is default mode from V4.0. It's easy to settings, only defined the ENV_AREA_SIZE. - * - The LEGACY mode has been DEPRECATED. It is NOT RECOMMENDED to continue using. - * Beacuse it will use ram to buffer the ENV and spend more flash erase times. - * If you want use it please using the V3.X version. - */ - -#include - -#if !defined(EF_START_ADDR) -#error "Please configure backup area start address (in ef_cfg.h)" -#endif - -#if !defined(EF_ERASE_MIN_SIZE) -#error "Please configure minimum size of flash erasure (in ef_cfg.h)" -#endif - -/** - * EasyFlash system initialize. - * - * @return result - */ -EfErrCode easyflash_init(void) { - extern EfErrCode ef_port_init(ef_env const **default_env, size_t *default_env_size); - extern EfErrCode ef_env_init(ef_env const *default_env, size_t default_env_size); - extern EfErrCode ef_iap_init(void); - extern EfErrCode ef_log_init(void); - - size_t default_env_set_size = 0; - const ef_env *default_env_set; - EfErrCode result = EF_NO_ERR; - static bool init_ok = false; - - if (init_ok) { - return EF_NO_ERR; - } - - result = ef_port_init(&default_env_set, &default_env_set_size); - -#ifdef EF_USING_ENV - if (result == EF_NO_ERR) { - result = ef_env_init(default_env_set, default_env_set_size); - } -#endif - -#ifdef EF_USING_IAP - if (result == EF_NO_ERR) { - result = ef_iap_init(); - } -#endif - -#ifdef EF_USING_LOG - if (result == EF_NO_ERR) { - result = ef_log_init(); - } -#endif - - if (result == EF_NO_ERR) { - init_ok = true; - EF_INFO("EasyFlash V%s is initialize success.\n", EF_SW_VERSION); - } else { - EF_INFO("EasyFlash V%s is initialize fail.\n", EF_SW_VERSION); - } - EF_INFO("You can get the latest version on https://github.com/armink/EasyFlash .\n"); - - return result; -} diff --git a/easyflash/src/ef_env.c b/easyflash/src/ef_env.c deleted file mode 100644 index a3a4c31..0000000 --- a/easyflash/src/ef_env.c +++ /dev/null @@ -1,1841 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2019, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Environment variables operating interface. This is the Next Generation version. - * Created on: 2019-02-02 - */ - -#include -#include - -#if defined(EF_USING_ENV) && !defined(EF_ENV_USING_LEGACY_MODE) - -#ifndef EF_WRITE_GRAN -#error "Please configure flash write granularity (in ef_cfg.h)" -#endif - -#if EF_WRITE_GRAN != 1 && EF_WRITE_GRAN != 8 && EF_WRITE_GRAN != 32 && EF_WRITE_GRAN != 64 -#error "the write gran can be only setting as 1, 8, 32 and 64" -#endif - -/* magic word(`E`, `F`, `4`, `0`) */ -#define SECTOR_MAGIC_WORD 0x30344645 -/* magic word(`K`, `V`, `4`, `0`) */ -#define ENV_MAGIC_WORD 0x3034564B - -/* the using status sector table length */ -#ifndef USING_SECTOR_TABLE_LEN -#define USING_SECTOR_TABLE_LEN 4 -#endif - -/* the string ENV value buffer size for legacy ef_get_env() function */ -#ifndef EF_STR_ENV_VALUE_MAX_SIZE -#define EF_STR_ENV_VALUE_MAX_SIZE 128 -#endif - -/* the sector remain threshold before full status */ -#ifndef EF_SEC_REMAIN_THRESHOLD -#define EF_SEC_REMAIN_THRESHOLD (ENV_HDR_DATA_SIZE + EF_ENV_NAME_MAX) -#endif - -/* the total remain empty sector threshold before GC */ -#ifndef EF_GC_EMPTY_SEC_THRESHOLD -#define EF_GC_EMPTY_SEC_THRESHOLD 1 -#endif - -/* the ENV cache table size, it will improve ENV search speed when using cache */ -#ifndef EF_ENV_CACHE_TABLE_SIZE -#define EF_ENV_CACHE_TABLE_SIZE 16 -#endif - -/* the sector cache table size, it will improve ENV save speed when using cache */ -#ifndef EF_SECTOR_CACHE_TABLE_SIZE -#define EF_SECTOR_CACHE_TABLE_SIZE 4 -#endif - -#if EF_ENV_CACHE_TABLE_SIZE > 0xFFFF -#error "The ENV cache table size must less than 0xFFFF" -#endif - -#if (EF_ENV_CACHE_TABLE_SIZE > 0) && (EF_SECTOR_CACHE_TABLE_SIZE > 0) -#define EF_ENV_USING_CACHE -#endif - -/* the sector is not combined value */ -#define SECTOR_NOT_COMBINED 0xFFFFFFFF -/* the next address is get failed */ -#define FAILED_ADDR 0xFFFFFFFF - -/* Return the most contiguous size aligned at specified width. RT_ALIGN(13, 4) - * would return 16. - */ -#define EF_ALIGN(size, align) (((size) + (align) - 1) & ~((align) - 1)) -/* align by write granularity */ -#define EF_WG_ALIGN(size) (EF_ALIGN(size, (EF_WRITE_GRAN + 7)/8)) -/** - * Return the down number of aligned at specified width. RT_ALIGN_DOWN(13, 4) - * would return 12. - */ -#define EF_ALIGN_DOWN(size, align) ((size) & ~((align) - 1)) -/* align down by write granularity */ -#define EF_WG_ALIGN_DOWN(size) (EF_ALIGN_DOWN(size, (EF_WRITE_GRAN + 7)/8)) - -#if (EF_WRITE_GRAN == 1) -#define STATUS_TABLE_SIZE(status_number) ((status_number * EF_WRITE_GRAN + 7)/8) -#else -#define STATUS_TABLE_SIZE(status_number) (((status_number - 1) * EF_WRITE_GRAN + 7)/8) -#endif - -#define STORE_STATUS_TABLE_SIZE STATUS_TABLE_SIZE(SECTOR_STORE_STATUS_NUM) -#define DIRTY_STATUS_TABLE_SIZE STATUS_TABLE_SIZE(SECTOR_DIRTY_STATUS_NUM) -#define ENV_STATUS_TABLE_SIZE STATUS_TABLE_SIZE(ENV_STATUS_NUM) - -#define SECTOR_SIZE EF_ERASE_MIN_SIZE -#define SECTOR_NUM (ENV_AREA_SIZE / (EF_ERASE_MIN_SIZE)) - -#if (SECTOR_NUM < 2) -#error "The sector number must lager then or equal to 2" -#endif - -#if (EF_GC_EMPTY_SEC_THRESHOLD == 0 || EF_GC_EMPTY_SEC_THRESHOLD >= SECTOR_NUM) -#error "There is at least one empty sector for GC." -#endif - -#define SECTOR_HDR_DATA_SIZE (EF_WG_ALIGN(sizeof(struct sector_hdr_data))) -#define SECTOR_DIRTY_OFFSET ((unsigned long)(&((struct sector_hdr_data *)0)->status_table.dirty)) -#define ENV_HDR_DATA_SIZE (EF_WG_ALIGN(sizeof(struct env_hdr_data))) -#define ENV_MAGIC_OFFSET ((unsigned long)(&((struct env_hdr_data *)0)->magic)) -#define ENV_LEN_OFFSET ((unsigned long)(&((struct env_hdr_data *)0)->len)) -#define ENV_NAME_LEN_OFFSET ((unsigned long)(&((struct env_hdr_data *)0)->name_len)) - -#define VER_NUM_ENV_NAME "__ver_num__" - -enum sector_store_status { - SECTOR_STORE_UNUSED, - SECTOR_STORE_EMPTY, - SECTOR_STORE_USING, - SECTOR_STORE_FULL, - SECTOR_STORE_STATUS_NUM, -}; -typedef enum sector_store_status sector_store_status_t; - -enum sector_dirty_status { - SECTOR_DIRTY_UNUSED, - SECTOR_DIRTY_FALSE, - SECTOR_DIRTY_TRUE, - SECTOR_DIRTY_GC, - SECTOR_DIRTY_STATUS_NUM, -}; -typedef enum sector_dirty_status sector_dirty_status_t; - -struct sector_hdr_data { - struct { - uint8_t store[STORE_STATUS_TABLE_SIZE]; /**< sector store status @see sector_store_status_t */ - uint8_t dirty[DIRTY_STATUS_TABLE_SIZE]; /**< sector dirty status @see sector_dirty_status_t */ - } status_table; - uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */ - uint32_t combined; /**< the combined next sector number, 0xFFFFFFFF: not combined */ - uint32_t reserved; -}; -typedef struct sector_hdr_data *sector_hdr_data_t; - -struct sector_meta_data { - bool check_ok; /**< sector header check is OK */ - struct { - sector_store_status_t store; /**< sector store status @see sector_store_status_t */ - sector_dirty_status_t dirty; /**< sector dirty status @see sector_dirty_status_t */ - } status; - uint32_t addr; /**< sector start address */ - uint32_t magic; /**< magic word(`E`, `F`, `4`, `0`) */ - uint32_t combined; /**< the combined next sector number, 0xFFFFFFFF: not combined */ - size_t remain; /**< remain size */ - uint32_t empty_env; /**< the next empty ENV node start address */ -}; -typedef struct sector_meta_data *sector_meta_data_t; - -struct env_hdr_data { - uint8_t status_table[ENV_STATUS_TABLE_SIZE]; /**< ENV node status, @see node_status_t */ - uint32_t magic; /**< magic word(`K`, `V`, `4`, `0`) */ - uint32_t len; /**< ENV node total length (header + name + value), must align by EF_WRITE_GRAN */ - uint32_t crc32; /**< ENV node crc32(name_len + data_len + name + value) */ - uint8_t name_len; /**< name length */ - uint32_t value_len; /**< value length */ -}; -typedef struct env_hdr_data *env_hdr_data_t; - -struct env_cache_node { - uint16_t name_crc; /**< ENV name's CRC32 low 16bit value */ - uint16_t active; /**< ENV node access active degree */ - uint32_t addr; /**< ENV node address */ -}; -typedef struct env_cache_node *env_cache_node_t; - -struct sector_cache_node { - uint32_t addr; /**< sector start address */ - uint32_t empty_addr; /**< sector empty address */ -}; -typedef struct sector_cache_node *sector_cache_node_t; - -static void gc_collect(void); - -/* ENV start address in flash */ -static uint32_t env_start_addr = 0; -/* default ENV set, must be initialized by user */ -static ef_env const *default_env_set; -/* default ENV set size, must be initialized by user */ -static size_t default_env_set_size = 0; -/* initialize OK flag */ -static bool init_ok = false; -/* request a GC check */ -static bool gc_request = false; -/* is in recovery check status when first reboot */ -static bool in_recovery_check = false; - -#ifdef EF_ENV_USING_CACHE -/* ENV cache table */ -struct env_cache_node env_cache_table[EF_ENV_CACHE_TABLE_SIZE] = { 0 }; -/* sector cache table, it caching the sector info which status is current using */ -struct sector_cache_node sector_cache_table[EF_SECTOR_CACHE_TABLE_SIZE] = { 0 }; -#endif /* EF_ENV_USING_CACHE */ - -static size_t set_status(uint8_t status_table[], size_t status_num, size_t status_index) -{ - size_t byte_index = ~0UL; - /* - * | write garn | status0 | status1 | status2 | - * --------------------------------------------------------------------------------- - * | 1bit | 0xFF | 0x7F | 0x3F | - * | 8bit | 0xFFFF | 0x00FF | 0x0000 | - * | 32bit | 0xFFFFFFFF FFFFFFFF | 0x00FFFFFF FFFFFFFF | 0x00FFFFFF 00FFFFFF | - */ - memset(status_table, 0xFF, STATUS_TABLE_SIZE(status_num)); - if (status_index > 0) { -#if (EF_WRITE_GRAN == 1) - byte_index = (status_index - 1) / 8; - status_table[byte_index] &= ~(0x80 >> ((status_index - 1) % 8)); -#else - byte_index = (status_index - 1) * (EF_WRITE_GRAN / 8); - status_table[byte_index] = 0x00; -#endif /* EF_WRITE_GRAN == 1 */ - } - - return byte_index; -} - -static size_t get_status(uint8_t status_table[], size_t status_num) -{ - size_t i = 0, status_num_bak = --status_num; - - while (status_num --) { - /* get the first 0 position from end address to start address */ -#if (EF_WRITE_GRAN == 1) - if ((status_table[status_num / 8] & (0x80 >> (status_num % 8))) == 0x00) { - break; - } -#else /* (EF_WRITE_GRAN == 8) || (EF_WRITE_GRAN == 32) || (EF_WRITE_GRAN == 64) */ - if (status_table[status_num * EF_WRITE_GRAN / 8] == 0x00) { - break; - } -#endif /* EF_WRITE_GRAN == 1 */ - i++; - } - - return status_num_bak - i; -} - -static EfErrCode write_status(uint32_t addr, uint8_t status_table[], size_t status_num, size_t status_index) -{ - EfErrCode result = EF_NO_ERR; - size_t byte_index; - - EF_ASSERT(status_index < status_num); - EF_ASSERT(status_table); - - /* set the status first */ - byte_index = set_status(status_table, status_num, status_index); - - /* the first status table value is all 1, so no need to write flash */ - if (byte_index == ~0UL) { - return EF_NO_ERR; - } -#if (EF_WRITE_GRAN == 1) - result = ef_port_write(addr + byte_index, (uint32_t *)&status_table[byte_index], 1); -#else /* (EF_WRITE_GRAN == 8) || (EF_WRITE_GRAN == 32) || (EF_WRITE_GRAN == 64) */ - /* write the status by write granularity - * some flash (like stm32 onchip) NOT supported repeated write before erase */ - result = ef_port_write(addr + byte_index, (uint32_t *) &status_table[byte_index], EF_WRITE_GRAN / 8); -#endif /* EF_WRITE_GRAN == 1 */ - - return result; -} - -static size_t read_status(uint32_t addr, uint8_t status_table[], size_t total_num) -{ - EF_ASSERT(status_table); - - ef_port_read(addr, (uint32_t *) status_table, STATUS_TABLE_SIZE(total_num)); - - return get_status(status_table, total_num); -} - -#ifdef EF_ENV_USING_CACHE -/* - * It's only caching the current using status sector's empty_addr - */ -static void update_sector_cache(uint32_t sec_addr, uint32_t empty_addr) -{ - size_t i, empty_index = EF_SECTOR_CACHE_TABLE_SIZE; - - for (i = 0; i < EF_SECTOR_CACHE_TABLE_SIZE; i++) { - if ((empty_addr > sec_addr) && (empty_addr < sec_addr + SECTOR_SIZE)) { - /* update the sector empty_addr in cache */ - if (sector_cache_table[i].addr == sec_addr) { - sector_cache_table[i].addr = sec_addr; - sector_cache_table[i].empty_addr = empty_addr; - return; - } else if ((sector_cache_table[i].addr == FAILED_ADDR) && (empty_index == EF_SECTOR_CACHE_TABLE_SIZE)) { - empty_index = i; - } - } else if (sector_cache_table[i].addr == sec_addr) { - /* delete the sector which status is not current using */ - sector_cache_table[i].addr = FAILED_ADDR; - return; - } - } - /* add the sector empty_addr to cache */ - if (empty_index < EF_SECTOR_CACHE_TABLE_SIZE) { - sector_cache_table[empty_index].addr = sec_addr; - sector_cache_table[empty_index].empty_addr = empty_addr; - } -} - -/* - * Get sector info from cache. It's return true when cache is hit. - */ -static bool get_sector_from_cache(uint32_t sec_addr, uint32_t *empty_addr) -{ - size_t i; - - for (i = 0; i < EF_SECTOR_CACHE_TABLE_SIZE; i++) { - if (sector_cache_table[i].addr == sec_addr) { - if (empty_addr) { - *empty_addr = sector_cache_table[i].empty_addr; - } - return true; - } - } - - return false; -} - -static void update_env_cache(const char *name, size_t name_len, uint32_t addr) -{ - size_t i, empty_index = EF_ENV_CACHE_TABLE_SIZE, min_activity_index = EF_ENV_CACHE_TABLE_SIZE; - uint16_t name_crc = (uint16_t) (ef_calc_crc32(0, name, name_len) >> 16), min_activity = 0xFFFF; - - for (i = 0; i < EF_ENV_CACHE_TABLE_SIZE; i++) { - if (addr != FAILED_ADDR) { - /* update the ENV address in cache */ - if (env_cache_table[i].name_crc == name_crc) { - env_cache_table[i].addr = addr; - return; - } else if ((env_cache_table[i].addr == FAILED_ADDR) && (empty_index == EF_ENV_CACHE_TABLE_SIZE)) { - empty_index = i; - } else if (env_cache_table[i].addr != FAILED_ADDR) { - if (env_cache_table[i].active > 0) { - env_cache_table[i].active--; - } - if (env_cache_table[i].active < min_activity) { - min_activity_index = i; - min_activity = env_cache_table[i].active; - } - } - } else if (env_cache_table[i].name_crc == name_crc) { - /* delete the ENV */ - env_cache_table[i].addr = FAILED_ADDR; - env_cache_table[i].active = 0; - return; - } - } - /* add the ENV to cache, using LRU (Least Recently Used) like algorithm */ - if (empty_index < EF_ENV_CACHE_TABLE_SIZE) { - env_cache_table[empty_index].addr = addr; - env_cache_table[empty_index].name_crc = name_crc; - env_cache_table[empty_index].active = 0; - } else if (min_activity_index < EF_ENV_CACHE_TABLE_SIZE) { - env_cache_table[min_activity_index].addr = addr; - env_cache_table[min_activity_index].name_crc = name_crc; - env_cache_table[min_activity_index].active = 0; - } -} - -/* - * Get ENV info from cache. It's return true when cache is hit. - */ -static bool get_env_from_cache(const char *name, size_t name_len, uint32_t *addr) -{ - size_t i; - uint16_t name_crc = (uint16_t) (ef_calc_crc32(0, name, name_len) >> 16); - - for (i = 0; i < EF_ENV_CACHE_TABLE_SIZE; i++) { - if ((env_cache_table[i].addr != FAILED_ADDR) && (env_cache_table[i].name_crc == name_crc)) { - char saved_name[EF_ENV_NAME_MAX]; - /* read the ENV name in flash */ - ef_port_read(env_cache_table[i].addr + ENV_HDR_DATA_SIZE, (uint32_t *) saved_name, EF_ENV_NAME_MAX); - if (!strncmp(name, saved_name, name_len)) { - *addr = env_cache_table[i].addr; - if (env_cache_table[i].active >= 0xFFFF - EF_ENV_CACHE_TABLE_SIZE) { - env_cache_table[i].active = 0xFFFF; - } else { - env_cache_table[i].active += EF_ENV_CACHE_TABLE_SIZE; - } - return true; - } - } - } - - return false; -} -#endif /* EF_ENV_USING_CACHE */ - -/* - * find the continue 0xFF flash address to end address - */ -static uint32_t continue_ff_addr(uint32_t start, uint32_t end) -{ - uint8_t buf[32], last_data = 0x00; - size_t i, addr = start, read_size; - - for (; start < end; start += sizeof(buf)) { - if (start + sizeof(buf) < end) { - read_size = sizeof(buf); - } else { - read_size = end - start; - } - ef_port_read(start, (uint32_t *) buf, read_size); - for (i = 0; i < read_size; i++) { - if (last_data != 0xFF && buf[i] == 0xFF) { - addr = start + i; - } - last_data = buf[i]; - } - } - - if (last_data == 0xFF) { - return EF_WG_ALIGN(addr); - } else { - return end; - } -} - -/* - * find the next ENV address by magic word on the flash - */ -static uint32_t find_next_env_addr(uint32_t start, uint32_t end) -{ - uint8_t buf[32]; - uint32_t start_bak = start, i; - uint32_t magic; - -#ifdef EF_ENV_USING_CACHE - uint32_t empty_env; - - if (get_sector_from_cache(EF_ALIGN_DOWN(start, SECTOR_SIZE), &empty_env) && start == empty_env) { - return FAILED_ADDR; - } -#endif /* EF_ENV_USING_CACHE */ - - for (; start < end; start += (sizeof(buf) - sizeof(uint32_t))) { - ef_port_read(start, (uint32_t *) buf, sizeof(buf)); - for (i = 0; i < sizeof(buf) - sizeof(uint32_t) && start + i < end; i++) { -#ifndef EF_BIG_ENDIAN /* Little Endian Order */ - magic = buf[i] + (buf[i + 1] << 8) + (buf[i + 2] << 16) + (buf[i + 3] << 24); -#else /* Big Endian Order */ - magic = buf[i + 3] + (buf[i + 2] << 8) + (buf[i + 1] << 16) + (buf[i] << 24); -#endif - if (magic == ENV_MAGIC_WORD && (start + i - ENV_MAGIC_OFFSET) >= start_bak) { - return start + i - ENV_MAGIC_OFFSET; - } - } - } - - return FAILED_ADDR; -} - -static uint32_t get_next_env_addr(sector_meta_data_t sector, env_node_obj_t pre_env) -{ - uint32_t addr = FAILED_ADDR; - - if (sector->status.store == SECTOR_STORE_EMPTY) { - return FAILED_ADDR; - } - - if (pre_env->addr.start == FAILED_ADDR) { - /* the first ENV address */ - addr = sector->addr + SECTOR_HDR_DATA_SIZE; - } else { - if (pre_env->addr.start <= sector->addr + SECTOR_SIZE) { - if (pre_env->crc_is_ok) { - addr = pre_env->addr.start + pre_env->len; - } else { - /* when pre_env CRC check failed, maybe the flash has error data - * find_next_env_addr after pre_env address */ - addr = pre_env->addr.start + EF_WG_ALIGN(1); - } - /* check and find next ENV address */ - addr = find_next_env_addr(addr, sector->addr + SECTOR_SIZE - SECTOR_HDR_DATA_SIZE); - - if (addr > sector->addr + SECTOR_SIZE || pre_env->len == 0) { - //TODO 扇区连续模式 - return FAILED_ADDR; - } - } else { - /* no ENV */ - return FAILED_ADDR; - } - } - - return addr; -} - -static EfErrCode read_env(env_node_obj_t env) -{ - struct env_hdr_data env_hdr; - uint8_t buf[32]; - uint32_t calc_crc32 = 0, crc_data_len, env_name_addr; - EfErrCode result = EF_NO_ERR; - size_t len, size; - /* read ENV header raw data */ - ef_port_read(env->addr.start, (uint32_t *)&env_hdr, sizeof(struct env_hdr_data)); - env->status = (env_status_t) get_status(env_hdr.status_table, ENV_STATUS_NUM); - env->len = env_hdr.len; - - if (env->len == ~0UL || env->len > ENV_AREA_SIZE || env->len < ENV_NAME_LEN_OFFSET) { - /* the ENV length was not write, so reserved the meta data for current ENV */ - env->len = ENV_HDR_DATA_SIZE; - if (env->status != ENV_ERR_HDR) { - env->status = ENV_ERR_HDR; - EF_DEBUG("Error: The ENV @0x%08X length has an error.\n", env->addr.start); - write_status(env->addr.start, env_hdr.status_table, ENV_STATUS_NUM, ENV_ERR_HDR); - } - env->crc_is_ok = false; - return EF_READ_ERR; - } else if (env->len > SECTOR_SIZE - SECTOR_HDR_DATA_SIZE && env->len < ENV_AREA_SIZE) { - //TODO 扇区连续模式,或者写入长度没有写入完整 - EF_ASSERT(0); - } - - /* CRC32 data len(header.name_len + header.value_len + name + value) */ - crc_data_len = env->len - ENV_NAME_LEN_OFFSET; - /* calculate the CRC32 value */ - for (len = 0, size = 0; len < crc_data_len; len += size) { - if (len + sizeof(buf) < crc_data_len) { - size = sizeof(buf); - } else { - size = crc_data_len - len; - } - - ef_port_read(env->addr.start + ENV_NAME_LEN_OFFSET + len, (uint32_t *) buf, EF_WG_ALIGN(size)); - calc_crc32 = ef_calc_crc32(calc_crc32, buf, size); - } - /* check CRC32 */ - if (calc_crc32 != env_hdr.crc32) { - env->crc_is_ok = false; - result = EF_READ_ERR; - } else { - env->crc_is_ok = true; - /* the name is behind aligned ENV header */ - env_name_addr = env->addr.start + ENV_HDR_DATA_SIZE; - ef_port_read(env_name_addr, (uint32_t *) env->name, EF_WG_ALIGN(env_hdr.name_len)); - /* the value is behind aligned name */ - env->addr.value = env_name_addr + EF_WG_ALIGN(env_hdr.name_len); - env->value_len = env_hdr.value_len; - env->name_len = env_hdr.name_len; - } - - return result; -} - -static EfErrCode read_sector_meta_data(uint32_t addr, sector_meta_data_t sector, bool traversal) -{ - EfErrCode result = EF_NO_ERR; - struct sector_hdr_data sec_hdr; - - EF_ASSERT(addr % SECTOR_SIZE == 0); - EF_ASSERT(sector); - - /* read sector header raw data */ - ef_port_read(addr, (uint32_t *)&sec_hdr, sizeof(struct sector_hdr_data)); - - sector->addr = addr; - sector->magic = sec_hdr.magic; - /* check magic word */ - if (sector->magic != SECTOR_MAGIC_WORD) { - sector->check_ok = false; - sector->combined = SECTOR_NOT_COMBINED; - return EF_ENV_INIT_FAILED; - } - sector->check_ok = true; - /* get other sector meta data */ - sector->combined = sec_hdr.combined; - sector->status.store = (sector_store_status_t) get_status(sec_hdr.status_table.store, SECTOR_STORE_STATUS_NUM); - sector->status.dirty = (sector_dirty_status_t) get_status(sec_hdr.status_table.dirty, SECTOR_DIRTY_STATUS_NUM); - /* traversal all ENV and calculate the remain space size */ - if (traversal) { - sector->remain = 0; - sector->empty_env = sector->addr + SECTOR_HDR_DATA_SIZE; - if (sector->status.store == SECTOR_STORE_EMPTY) { - sector->remain = SECTOR_SIZE - SECTOR_HDR_DATA_SIZE; - } else if (sector->status.store == SECTOR_STORE_USING) { - struct env_node_obj env_meta; - -#ifdef EF_ENV_USING_CACHE - if (get_sector_from_cache(addr, §or->empty_env)) { - sector->remain = SECTOR_SIZE - (sector->empty_env - sector->addr); - return result; - } -#endif /* EF_ENV_USING_CACHE */ - - sector->remain = SECTOR_SIZE - SECTOR_HDR_DATA_SIZE; - env_meta.addr.start = FAILED_ADDR; - while ((env_meta.addr.start = get_next_env_addr(sector, &env_meta)) != FAILED_ADDR) { - read_env(&env_meta); - if (!env_meta.crc_is_ok) { - if (env_meta.status != ENV_PRE_WRITE && env_meta.status!= ENV_ERR_HDR) { - EF_INFO("Error: The ENV (@0x%08X) CRC32 check failed!\n", env_meta.addr.start); - sector->remain = 0; - result = EF_READ_ERR; - break; - } - } - sector->empty_env += env_meta.len; - sector->remain -= env_meta.len; - } - /* check the empty ENV address by read continue 0xFF on flash */ - { - uint32_t ff_addr; - - ff_addr = continue_ff_addr(sector->empty_env, sector->addr + SECTOR_SIZE); - /* check the flash data is clean */ - if (sector->empty_env != ff_addr) { - /* update the sector information */ - sector->empty_env = ff_addr; - sector->remain = SECTOR_SIZE - (ff_addr - sector->addr); - } - } - -#ifdef EF_ENV_USING_CACHE - update_sector_cache(sector->addr, sector->empty_env); -#endif - } - } - - return result; -} - -static uint32_t get_next_sector_addr(sector_meta_data_t pre_sec) -{ - uint32_t next_addr; - - if (pre_sec->addr == FAILED_ADDR) { - return env_start_addr; - } else { - /* check ENV sector combined */ - if (pre_sec->combined == SECTOR_NOT_COMBINED) { - next_addr = pre_sec->addr + SECTOR_SIZE; - } else { - next_addr = pre_sec->addr + pre_sec->combined * SECTOR_SIZE; - } - /* check range */ - if (next_addr < env_start_addr + ENV_AREA_SIZE) { - return next_addr; - } else { - /* no sector */ - return FAILED_ADDR; - } - } -} - -static void env_iterator(env_node_obj_t env, void *arg1, void *arg2, - bool (*callback)(env_node_obj_t env, void *arg1, void *arg2)) -{ - struct sector_meta_data sector; - uint32_t sec_addr; - - sector.addr = FAILED_ADDR; - /* search all sectors */ - while ((sec_addr = get_next_sector_addr(§or)) != FAILED_ADDR) { - if (read_sector_meta_data(sec_addr, §or, false) != EF_NO_ERR) { - continue; - } - if (callback == NULL) { - continue; - } - /* sector has ENV */ - if (sector.status.store == SECTOR_STORE_USING || sector.status.store == SECTOR_STORE_FULL) { - env->addr.start = FAILED_ADDR; - /* search all ENV */ - while ((env->addr.start = get_next_env_addr(§or, env)) != FAILED_ADDR) { - read_env(env); - /* iterator is interrupted when callback return true */ - if (callback(env, arg1, arg2)) { - return; - } - } - } - } -} - -static bool find_env_cb(env_node_obj_t env, void *arg1, void *arg2) -{ - const char *key = arg1; - bool *find_ok = arg2; - size_t key_len = strlen(key); - - if (key_len != env->name_len) { - return false; - } - /* check ENV */ - if (env->crc_is_ok && env->status == ENV_WRITE && !strncmp(env->name, key, key_len)) { - *find_ok = true; - return true; - } - return false; -} - -static bool find_env_no_cache(const char *key, env_node_obj_t env) -{ - bool find_ok = false; - - env_iterator(env, (void *)key, &find_ok, find_env_cb); - - return find_ok; -} - -static bool find_env(const char *key, env_node_obj_t env) -{ - bool find_ok = false; - -#ifdef EF_ENV_USING_CACHE - size_t key_len = strlen(key); - - if (get_env_from_cache(key, key_len, &env->addr.start)) { - read_env(env); - return true; - } -#endif /* EF_ENV_USING_CACHE */ - - find_ok = find_env_no_cache(key, env); - -#ifdef EF_ENV_USING_CACHE - if (find_ok) { - update_env_cache(key, key_len, env->addr.start); - } -#endif /* EF_ENV_USING_CACHE */ - - return find_ok; -} - -static bool ef_is_str(uint8_t *value, size_t len) -{ -#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ') - size_t i; - - for (i = 0; i < len; i++) { - if (!__is_print(value[i])) { - return false; - } - } - return true; -} - -static size_t get_env(const char *key, void *value_buf, size_t buf_len, size_t *value_len) -{ - struct env_node_obj env; - size_t read_len = 0; - - if (find_env(key, &env)) { - if (value_len) { - *value_len = env.value_len; - } - if (buf_len > env.value_len) { - read_len = env.value_len; - } else { - read_len = buf_len; - } - if (value_buf){ - ef_port_read(env.addr.value, (uint32_t *) value_buf, read_len); - } - } else if (value_len) { - *value_len = 0; - } - - return read_len; -} - -/** - * Get a ENV object by key name - * - * @param key ENV name - * @param env ENV object - * - * @return TRUE: find the ENV is OK, else return false - */ -bool ef_get_env_obj(const char *key, env_node_obj_t env) -{ - bool find_ok = false; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return 0; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - find_ok = find_env(key, env); - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return find_ok; -} - -/** - * Get a blob ENV value by key name. - * - * @param key ENV name - * @param value_buf ENV blob buffer - * @param buf_len ENV blob buffer length - * @param saved_value_len return the length of the value saved on the flash, 0: NOT found - * - * @return the actually get size on successful - */ -size_t ef_get_env_blob(const char *key, void *value_buf, size_t buf_len, size_t *saved_value_len) -{ - size_t read_len = 0; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return 0; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - read_len = get_env(key, value_buf, buf_len, saved_value_len); - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return read_len; -} - -/** - * Get an ENV value by key name. - * - * @note this function is NOT supported reentrant - * @note this function is DEPRECATED - * - * @param key ENV name - * - * @return value - */ -char *ef_get_env(const char *key) -{ - static char value[EF_STR_ENV_VALUE_MAX_SIZE + 1]; - size_t get_size; - - if ((get_size = ef_get_env_blob(key, value, EF_STR_ENV_VALUE_MAX_SIZE, NULL)) > 0) { - /* the return value must be string */ - if (ef_is_str((uint8_t *)value, get_size)) { - value[get_size] = '\0'; - return value; - } else { - EF_INFO("Warning: The ENV value isn't string. Could not be returned\n"); - return NULL; - } - } - - return NULL; -} - -/** - * read the ENV value by ENV object - * - * @param env ENV object - * @param value_buf the buffer for store ENV value - * @param buf_len buffer length - * - * @return the actually read size on successful - */ -size_t ef_read_env_value(env_node_obj_t env, uint8_t *value_buf, size_t buf_len) -{ - size_t read_len = 0; - - EF_ASSERT(env); - EF_ASSERT(value_buf); - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return 0; - } - - if (env->crc_is_ok) { - /* lock the ENV cache */ - ef_port_env_lock(); - - if (buf_len > env->value_len) { - read_len = env->value_len; - } else { - read_len = buf_len; - } - - ef_port_read(env->addr.value, (uint32_t *) value_buf, read_len); - /* unlock the ENV cache */ - ef_port_env_unlock(); - } - - return read_len; -} - -static EfErrCode write_env_hdr(uint32_t addr, env_hdr_data_t env_hdr) { - EfErrCode result = EF_NO_ERR; - /* write the status will by write granularity */ - result = write_status(addr, env_hdr->status_table, ENV_STATUS_NUM, ENV_PRE_WRITE); - if (result != EF_NO_ERR) { - return result; - } - /* write other header data */ - result = ef_port_write(addr + ENV_MAGIC_OFFSET, &env_hdr->magic, sizeof(struct env_hdr_data) - ENV_MAGIC_OFFSET); - - return result; -} - -static EfErrCode format_sector(uint32_t addr, uint32_t combined_value) -{ - EfErrCode result = EF_NO_ERR; - struct sector_hdr_data sec_hdr; - - EF_ASSERT(addr % SECTOR_SIZE == 0); - - result = ef_port_erase(addr, SECTOR_SIZE); - if (result == EF_NO_ERR) { - /* initialize the header data */ - memset(&sec_hdr, 0xFF, sizeof(struct sector_hdr_data)); - set_status(sec_hdr.status_table.store, SECTOR_STORE_STATUS_NUM, SECTOR_STORE_EMPTY); - set_status(sec_hdr.status_table.dirty, SECTOR_DIRTY_STATUS_NUM, SECTOR_DIRTY_FALSE); - sec_hdr.magic = SECTOR_MAGIC_WORD; - sec_hdr.combined = combined_value; - sec_hdr.reserved = 0xFFFFFFFF; - /* save the header */ - result = ef_port_write(addr, (uint32_t *)&sec_hdr, sizeof(struct sector_hdr_data)); - -#ifdef EF_ENV_USING_CACHE - /* delete the sector cache */ - update_sector_cache(addr, addr + SECTOR_SIZE); -#endif /* EF_ENV_USING_CACHE */ - } - - return result; -} - -static EfErrCode update_sec_status(sector_meta_data_t sector, size_t new_env_len, bool *is_full) -{ - uint8_t status_table[STORE_STATUS_TABLE_SIZE]; - EfErrCode result = EF_NO_ERR; - /* change the current sector status */ - if (sector->status.store == SECTOR_STORE_EMPTY) { - /* change the sector status to using */ - result = write_status(sector->addr, status_table, SECTOR_STORE_STATUS_NUM, SECTOR_STORE_USING); - } else if (sector->status.store == SECTOR_STORE_USING) { - /* check remain size */ - if (sector->remain < EF_SEC_REMAIN_THRESHOLD || sector->remain - new_env_len < EF_SEC_REMAIN_THRESHOLD) { - /* change the sector status to full */ - result = write_status(sector->addr, status_table, SECTOR_STORE_STATUS_NUM, SECTOR_STORE_FULL); - -#ifdef EF_ENV_USING_CACHE - /* delete the sector cache */ - update_sector_cache(sector->addr, sector->addr + SECTOR_SIZE); -#endif /* EF_ENV_USING_CACHE */ - - if (is_full) { - *is_full = true; - } - } else if (is_full) { - *is_full = false; - } - } - - return result; -} - -static void sector_iterator(sector_meta_data_t sector, sector_store_status_t status, void *arg1, void *arg2, - bool (*callback)(sector_meta_data_t sector, void *arg1, void *arg2), bool traversal_env) { - uint32_t sec_addr; - - /* search all sectors */ - sector->addr = FAILED_ADDR; - while ((sec_addr = get_next_sector_addr(sector)) != FAILED_ADDR) { - read_sector_meta_data(sec_addr, sector, false); - if (status == SECTOR_STORE_UNUSED || status == sector->status.store) { - if (traversal_env) { - read_sector_meta_data(sec_addr, sector, traversal_env); - } - /* iterator is interrupted when callback return true */ - if (callback && callback(sector, arg1, arg2)) { - return; - } - } - } -} - -static bool sector_statistics_cb(sector_meta_data_t sector, void *arg1, void *arg2) -{ - size_t *empty_sector = arg1, *using_sector = arg2; - - if (sector->check_ok && sector->status.store == SECTOR_STORE_EMPTY) { - (*empty_sector)++; - } else if (sector->check_ok && sector->status.store == SECTOR_STORE_USING) { - (*using_sector)++; - } - - return false; -} - -static bool alloc_env_cb(sector_meta_data_t sector, void *arg1, void *arg2) -{ - size_t *env_size = arg1; - uint32_t *empty_env = arg2; - - /* 1. sector has space - * 2. the NO dirty sector - * 3. the dirty sector only when the gc_request is false */ - if (sector->check_ok && sector->remain > *env_size - && ((sector->status.dirty == SECTOR_DIRTY_FALSE) - || (sector->status.dirty == SECTOR_DIRTY_TRUE && !gc_request))) { - *empty_env = sector->empty_env; - return true; - } - - return false; -} - -static uint32_t alloc_env(sector_meta_data_t sector, size_t env_size) -{ - uint32_t empty_env = FAILED_ADDR; - size_t empty_sector = 0, using_sector = 0; - - /* sector status statistics */ - sector_iterator(sector, SECTOR_STORE_UNUSED, &empty_sector, &using_sector, sector_statistics_cb, false); - if (using_sector > 0) { - /* alloc the ENV from the using status sector first */ - sector_iterator(sector, SECTOR_STORE_USING, &env_size, &empty_env, alloc_env_cb, true); - } - if (empty_sector > 0 && empty_env == FAILED_ADDR) { - if (empty_sector > EF_GC_EMPTY_SEC_THRESHOLD || gc_request) { - sector_iterator(sector, SECTOR_STORE_EMPTY, &env_size, &empty_env, alloc_env_cb, true); - } else { - /* no space for new ENV now will GC and retry */ - EF_DEBUG("Trigger a GC check after alloc ENV failed.\n"); - gc_request = true; - } - } - - return empty_env; -} - -static EfErrCode del_env(const char *key, env_node_obj_t old_env, bool complete_del) { - EfErrCode result = EF_NO_ERR; - uint32_t dirty_status_addr; - static bool last_is_complete_del = false; - -#if (ENV_STATUS_TABLE_SIZE >= DIRTY_STATUS_TABLE_SIZE) - uint8_t status_table[ENV_STATUS_TABLE_SIZE]; -#else - uint8_t status_table[DIRTY_STATUS_TABLE_SIZE]; -#endif - - /* need find ENV */ - if (!old_env) { - struct env_node_obj env; - /* find ENV */ - if (find_env(key, &env)) { - old_env = &env; - } else { - EF_DEBUG("Not found '%s' in ENV.\n", key); - return EF_ENV_NAME_ERR; - } - } - /* change and save the new status */ - if (!complete_del) { - result = write_status(old_env->addr.start, status_table, ENV_STATUS_NUM, ENV_PRE_DELETE); - last_is_complete_del = true; - } else { - result = write_status(old_env->addr.start, status_table, ENV_STATUS_NUM, ENV_DELETED); - - if (!last_is_complete_del && result == EF_NO_ERR) { -#ifdef EF_ENV_USING_CACHE - /* delete the ENV in flash and cache */ - if (key != NULL) { - /* when using del_env(key, NULL, true) or del_env(key, env, true) in ef_del_env() and set_env() */ - update_env_cache(key, strlen(key), FAILED_ADDR); - } else if (old_env != NULL) { - /* when using del_env(NULL, env, true) in move_env() */ - update_env_cache(old_env->name, old_env->name_len, FAILED_ADDR); - } -#endif /* EF_ENV_USING_CACHE */ - } - - last_is_complete_del = false; - } - - dirty_status_addr = EF_ALIGN_DOWN(old_env->addr.start, SECTOR_SIZE) + SECTOR_DIRTY_OFFSET; - /* read and change the sector dirty status */ - if (result == EF_NO_ERR - && read_status(dirty_status_addr, status_table, SECTOR_DIRTY_STATUS_NUM) == SECTOR_DIRTY_FALSE) { - result = write_status(dirty_status_addr, status_table, SECTOR_DIRTY_STATUS_NUM, SECTOR_DIRTY_TRUE); - } - - return result; -} - -/* - * move the ENV to new space - */ -static EfErrCode move_env(env_node_obj_t env) -{ - EfErrCode result = EF_NO_ERR; - uint8_t status_table[ENV_STATUS_TABLE_SIZE]; - uint32_t env_addr; - struct sector_meta_data sector; - - /* prepare to delete the current ENV */ - if (env->status == ENV_WRITE) { - del_env(NULL, env, false); - } - - if ((env_addr = alloc_env(§or, env->len)) != FAILED_ADDR) { - if (in_recovery_check) { - struct env_node_obj env_bak; - char name[EF_ENV_NAME_MAX + 1] = { 0 }; - strncpy(name, env->name, env->name_len); - /* check the ENV in flash is already create success */ - if (find_env_no_cache(name, &env_bak)) { - /* already create success, don't need to duplicate */ - result = EF_NO_ERR; - goto __exit; - } - } - } else { - return EF_ENV_FULL; - } - /* start move the ENV */ - { - uint8_t buf[32]; - size_t len, size, env_len = env->len; - - /* update the new ENV sector status first */ - update_sec_status(§or, env->len, NULL); - - write_status(env_addr, status_table, ENV_STATUS_NUM, ENV_PRE_WRITE); - env_len -= ENV_MAGIC_OFFSET; - for (len = 0, size = 0; len < env_len; len += size) { - if (len + sizeof(buf) < env_len) { - size = sizeof(buf); - } else { - size = env_len - len; - } - ef_port_read(env->addr.start + ENV_MAGIC_OFFSET + len, (uint32_t *) buf, EF_WG_ALIGN(size)); - result = ef_port_write(env_addr + ENV_MAGIC_OFFSET + len, (uint32_t *) buf, size); - } - write_status(env_addr, status_table, ENV_STATUS_NUM, ENV_WRITE); - -#ifdef EF_ENV_USING_CACHE - update_sector_cache(EF_ALIGN_DOWN(env_addr, SECTOR_SIZE), - env_addr + ENV_HDR_DATA_SIZE + EF_WG_ALIGN(env->name_len) + EF_WG_ALIGN(env->value_len)); - update_env_cache(env->name, env->name_len, env_addr); -#endif /* EF_ENV_USING_CACHE */ - } - - EF_DEBUG("Moved the ENV (%.*s) from 0x%08X to 0x%08X.\n", env->name_len, env->name, env->addr.start, env_addr); - -__exit: - del_env(NULL, env, true); - - return result; -} - -static uint32_t new_env(sector_meta_data_t sector, size_t env_size) -{ - bool already_gc = false; - uint32_t empty_env = FAILED_ADDR; - -__retry: - - if ((empty_env = alloc_env(sector, env_size)) == FAILED_ADDR && gc_request && !already_gc) { - EF_DEBUG("Warning: Alloc an ENV (size %d) failed when new ENV. Now will GC then retry.\n", env_size); - gc_collect(); - already_gc = true; - goto __retry; - } - - return empty_env; -} - -static uint32_t new_env_by_kv(sector_meta_data_t sector, size_t key_len, size_t buf_len) -{ - size_t env_len = ENV_HDR_DATA_SIZE + EF_WG_ALIGN(key_len) + EF_WG_ALIGN(buf_len); - - return new_env(sector, env_len); -} - -static bool gc_check_cb(sector_meta_data_t sector, void *arg1, void *arg2) -{ - size_t *empty_sec = arg1; - - if (sector->check_ok) { - *empty_sec = *empty_sec + 1; - } - - return false; - -} - -static bool do_gc(sector_meta_data_t sector, void *arg1, void *arg2) -{ - struct env_node_obj env; - - if (sector->check_ok && (sector->status.dirty == SECTOR_DIRTY_TRUE || sector->status.dirty == SECTOR_DIRTY_GC)) { - uint8_t status_table[DIRTY_STATUS_TABLE_SIZE]; - /* change the sector status to GC */ - write_status(sector->addr + SECTOR_DIRTY_OFFSET, status_table, SECTOR_DIRTY_STATUS_NUM, SECTOR_DIRTY_GC); - /* search all ENV */ - env.addr.start = FAILED_ADDR; - while ((env.addr.start = get_next_env_addr(sector, &env)) != FAILED_ADDR) { - read_env(&env); - if (env.crc_is_ok && (env.status == ENV_WRITE || env.status == ENV_PRE_DELETE)) { - /* move the ENV to new space */ - if (move_env(&env) != EF_NO_ERR) { - EF_DEBUG("Error: Moved the ENV (%.*s) for GC failed.\n", env.name_len, env.name); - } - } - } - format_sector(sector->addr, SECTOR_NOT_COMBINED); - EF_DEBUG("Collect a sector @0x%08X\n", sector->addr); - } - - return false; -} - -/* - * The GC will be triggered on the following scene: - * 1. alloc an ENV when the flash not has enough space - * 2. write an ENV then the flash not has enough space - */ -static void gc_collect(void) -{ - struct sector_meta_data sector; - size_t empty_sec = 0; - - /* GC check the empty sector number */ - sector_iterator(§or, SECTOR_STORE_EMPTY, &empty_sec, NULL, gc_check_cb, false); - - /* do GC collect */ - EF_DEBUG("The remain empty sector is %d, GC threshold is %d.\n", empty_sec, EF_GC_EMPTY_SEC_THRESHOLD); - if (empty_sec <= EF_GC_EMPTY_SEC_THRESHOLD) { - sector_iterator(§or, SECTOR_STORE_UNUSED, NULL, NULL, do_gc, false); - } - - gc_request = false; -} - -static EfErrCode align_write(uint32_t addr, const uint32_t *buf, size_t size) -{ - EfErrCode result = EF_NO_ERR; - size_t align_remain; - -#if (EF_WRITE_GRAN / 8 > 0) - uint8_t align_data[EF_WRITE_GRAN / 8]; - size_t align_data_size = sizeof(align_data); -#else - /* For compatibility with C89 */ - uint8_t align_data_u8, *align_data = &align_data_u8; - size_t align_data_size = 1; -#endif - - memset(align_data, 0xFF, align_data_size); - align_remain = EF_WG_ALIGN_DOWN(size);//use align_remain temporary to save aligned size. - - if(align_remain > 0){//it may be 0 in this function. - result = ef_port_write(addr, buf, align_remain); - } - - align_remain = size - align_remain; - if (result == EF_NO_ERR && align_remain) { - memcpy(align_data, (uint8_t *)buf + EF_WG_ALIGN_DOWN(size), align_remain); - result = ef_port_write(addr + EF_WG_ALIGN_DOWN(size), (uint32_t *) align_data, align_data_size); - } - - return result; -} - -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)); - 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.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; -} - -/** - * Delete an ENV. - * - * @param key ENV name - * - * @return result - */ -EfErrCode ef_del_env(const char *key) -{ - EfErrCode result = EF_NO_ERR; - - if (!init_ok) { - EF_INFO("Error: ENV isn't initialize OK.\n"); - return EF_ENV_INIT_FAILED; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - result = del_env(key, NULL, true); - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * The same to ef_del_env on this mode - * It's compatibility with older versions (less then V4.0). - * - * @note this function is DEPRECATED - * - * @param key ENV name - * - * @return result - */ -EfErrCode ef_del_and_save_env(const char *key) -{ - return ef_del_env(key); -} - -static EfErrCode set_env(const char *key, const void *value_buf, size_t buf_len) -{ - EfErrCode result = EF_NO_ERR; - static struct env_node_obj env; - static struct sector_meta_data sector; - bool env_is_found = false; - - if (value_buf == NULL) { - result = del_env(key, NULL, true); - } else { - /* make sure the flash has enough space */ - if (new_env_by_kv(§or, strlen(key), buf_len) == FAILED_ADDR) { - return EF_ENV_FULL; - } - env_is_found = find_env(key, &env); - /* prepare to delete the old ENV */ - if (env_is_found) { - result = del_env(key, &env, false); - } - /* create the new ENV */ - if (result == EF_NO_ERR) { - result = create_env_blob(§or, key, value_buf, buf_len); - } - /* delete the old ENV */ - if (env_is_found && result == EF_NO_ERR) { - result = del_env(key, &env, true); - } - /* process the GC after set ENV */ - if (gc_request) { - gc_collect(); - } - } - - return result; -} - -/** - * Set a blob ENV. If it value is NULL, delete it. - * If not find it in flash, then create it. - * - * @param key ENV name - * @param value ENV value - * @param len ENV value length - * - * @return result - */ -EfErrCode ef_set_env_blob(const char *key, const void *value_buf, size_t buf_len) -{ - EfErrCode result = EF_NO_ERR; - - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return EF_ENV_INIT_FAILED; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - result = set_env(key, value_buf, buf_len); - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * Set a string ENV. If it value is NULL, delete it. - * If not find it in flash, then create it. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -EfErrCode ef_set_env(const char *key, const char *value) -{ - return ef_set_env_blob(key, value, strlen(value)); -} - -/** - * The same to ef_set_env on this mode. - * It's compatibility with older versions (less then V4.0). - * - * @note this function is DEPRECATED - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -EfErrCode ef_set_and_save_env(const char *key, const char *value) -{ - return ef_set_env_blob(key, value, strlen(value)); -} - -/** - * Save ENV to flash. - * - * @note this function is DEPRECATED - */ -EfErrCode ef_save_env(void) -{ - /* do nothing not cur mode */ - return EF_NO_ERR; -} - -/** - * ENV set default. - * - * @return result - */ -EfErrCode ef_env_set_default(void) -{ - EfErrCode result = EF_NO_ERR; - uint32_t addr, i, value_len; - struct sector_meta_data sector; - - EF_ASSERT(default_env_set); - EF_ASSERT(default_env_set_size); - - /* lock the ENV cache */ - ef_port_env_lock(); - /* format all sectors */ - for (addr = env_start_addr; addr < env_start_addr + ENV_AREA_SIZE; addr += SECTOR_SIZE) { - result = format_sector(addr, SECTOR_NOT_COMBINED); - if (result != EF_NO_ERR) { - goto __exit; - } - } - /* create default ENV */ - for (i = 0; i < default_env_set_size; i++) { - /* It seems to be a string when value length is 0. - * This mechanism is for compatibility with older versions (less then V4.0). */ - if (default_env_set[i].value_len == 0) { - value_len = strlen(default_env_set[i].value); - } else { - value_len = default_env_set[i].value_len; - } - sector.empty_env = FAILED_ADDR; - create_env_blob(§or, default_env_set[i].key, default_env_set[i].value, value_len); - if (result != EF_NO_ERR) { - goto __exit; - } - } - -__exit: - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -static bool print_env_cb(env_node_obj_t env, void *arg1, void *arg2) -{ - bool value_is_str = true, print_value = false; - size_t *using_size = arg1; - - if (env->crc_is_ok) { - /* calculate the total using flash size */ - *using_size += env->len; - /* check ENV */ - if (env->status == ENV_WRITE) { - ef_print("%.*s=", env->name_len, env->name); - - if (env->value_len < EF_STR_ENV_VALUE_MAX_SIZE ) { - uint8_t buf[32]; - size_t len, size; -__reload: - /* check the value is string */ - for (len = 0, size = 0; len < env->value_len; len += size) { - if (len + sizeof(buf) < env->value_len) { - size = sizeof(buf); - } else { - size = env->value_len - len; - } - ef_port_read(env->addr.value + len, (uint32_t *) buf, EF_WG_ALIGN(size)); - if (print_value) { - ef_print("%.*s", size, buf); - } else if (!ef_is_str(buf, size)) { - value_is_str = false; - break; - } - } - } else { - value_is_str = false; - } - if (value_is_str && !print_value) { - print_value = true; - goto __reload; - } else if (!value_is_str) { - ef_print("blob @0x%08X %dbytes", env->addr.value, env->value_len); - } - ef_print("\n"); - } - } - - return false; -} - - -/** - * Print ENV. - */ -void ef_print_env(void) -{ - struct env_node_obj env; - size_t using_size = 0; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - env_iterator(&env, &using_size, NULL, print_env_cb); - - ef_print("\nmode: next generation\n"); - ef_print("size: %lu/%lu bytes.\n", using_size + (SECTOR_NUM - EF_GC_EMPTY_SEC_THRESHOLD) * SECTOR_HDR_DATA_SIZE, - ENV_AREA_SIZE - SECTOR_SIZE * EF_GC_EMPTY_SEC_THRESHOLD); - - /* unlock the ENV cache */ - ef_port_env_unlock(); -} - -#ifdef EF_ENV_AUTO_UPDATE -/* - * Auto update ENV to latest default when current EF_ENV_VER_NUM is changed. - */ -static void env_auto_update(void) -{ - size_t saved_ver_num, setting_ver_num = EF_ENV_VER_NUM; - - if (get_env(VER_NUM_ENV_NAME, &saved_ver_num, sizeof(size_t), NULL) > 0) { - /* check version number */ - if (saved_ver_num != setting_ver_num) { - struct env_node_obj env; - size_t i, value_len; - struct sector_meta_data sector; - EF_DEBUG("Update the ENV from version %d to %d.\n", saved_ver_num, setting_ver_num); - for (i = 0; i < default_env_set_size; i++) { - /* add a new ENV when it's not found */ - if (!find_env(default_env_set[i].key, &env)) { - /* It seems to be a string when value length is 0. - * This mechanism is for compatibility with older versions (less then V4.0). */ - if (default_env_set[i].value_len == 0) { - value_len = strlen(default_env_set[i].value); - } else { - value_len = default_env_set[i].value_len; - } - sector.empty_env = FAILED_ADDR; - create_env_blob(§or, default_env_set[i].key, default_env_set[i].value, value_len); - } - } - } else { - /* version number not changed now return */ - return; - } - } - - set_env(VER_NUM_ENV_NAME, &setting_ver_num, sizeof(size_t)); -} -#endif /* EF_ENV_AUTO_UPDATE */ - -static bool check_sec_hdr_cb(sector_meta_data_t sector, void *arg1, void *arg2) -{ - if (!sector->check_ok) { - size_t *failed_count = arg1; - - EF_INFO("Warning: Sector header check failed. Format this sector (0x%08x).\n", sector->addr); - (*failed_count) ++; - format_sector(sector->addr, SECTOR_NOT_COMBINED); - } - - return false; -} - -static bool check_and_recovery_gc_cb(sector_meta_data_t sector, void *arg1, void *arg2) -{ - if (sector->check_ok && sector->status.dirty == SECTOR_DIRTY_GC) { - /* make sure the GC request flag to true */ - gc_request = true; - /* resume the GC operate */ - gc_collect(); - } - - return false; -} - -static bool check_and_recovery_env_cb(env_node_obj_t env, void *arg1, void *arg2) -{ - /* recovery the prepare deleted ENV */ - if (env->crc_is_ok && env->status == ENV_PRE_DELETE) { - EF_INFO("Found an ENV (%.*s) which has changed value failed. Now will recovery it.\n", env->name_len, env->name); - /* recovery the old ENV */ - if (move_env(env) == EF_NO_ERR) { - EF_DEBUG("Recovery the ENV successful.\n"); - } else { - EF_DEBUG("Warning: Moved an ENV (size %d) failed when recovery. Now will GC then retry.\n", env->len); - return true; - } - } else if (env->status == ENV_PRE_WRITE) { - uint8_t status_table[ENV_STATUS_TABLE_SIZE]; - /* the ENV has not write finish, change the status to error */ - //TODO 绘制异常处理的状态装换图 - write_status(env->addr.start, status_table, ENV_STATUS_NUM, ENV_ERR_HDR); - return true; - } - - return false; -} - -/** - * Check and load the flash ENV meta data. - * - * @return result - */ -EfErrCode ef_load_env(void) -{ - EfErrCode result = EF_NO_ERR; - struct env_node_obj env; - struct sector_meta_data sector; - size_t check_failed_count = 0; - - in_recovery_check = true; - /* check all sector header */ - sector_iterator(§or, SECTOR_STORE_UNUSED, &check_failed_count, NULL, check_sec_hdr_cb, false); - /* all sector header check failed */ - if (check_failed_count == SECTOR_NUM) { - EF_INFO("Warning: All sector header check failed. Set it to default.\n"); - ef_env_set_default(); - } - - /* lock the ENV cache */ - ef_port_env_lock(); - /* check all sector header for recovery GC */ - sector_iterator(§or, SECTOR_STORE_UNUSED, NULL, NULL, check_and_recovery_gc_cb, false); - -__retry: - /* check all ENV for recovery */ - env_iterator(&env, NULL, NULL, check_and_recovery_env_cb); - if (gc_request) { - gc_collect(); - goto __retry; - } - - in_recovery_check = false; - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * Flash ENV initialize. - * - * @param default_env default ENV set for user - * @param default_env_size default ENV set size - * - * @return result - */ -EfErrCode ef_env_init(ef_env const *default_env, size_t default_env_size) { - EfErrCode result = EF_NO_ERR; - -#ifdef EF_ENV_USING_CACHE - size_t i; -#endif - - EF_ASSERT(default_env); - EF_ASSERT(ENV_AREA_SIZE); - /* must be aligned with erase_min_size */ - EF_ASSERT(ENV_AREA_SIZE % EF_ERASE_MIN_SIZE == 0); - /* sector number must be greater than or equal to 2 */ - EF_ASSERT(SECTOR_NUM >= 2); - /* must be aligned with write granularity */ - EF_ASSERT((EF_STR_ENV_VALUE_MAX_SIZE * 8) % EF_WRITE_GRAN == 0); - - if (init_ok) { - return EF_NO_ERR; - } - -#ifdef EF_ENV_USING_CACHE - for (i = 0; i < EF_SECTOR_CACHE_TABLE_SIZE; i++) { - sector_cache_table[i].addr = FAILED_ADDR; - } - for (i = 0; i < EF_ENV_CACHE_TABLE_SIZE; i++) { - env_cache_table[i].addr = FAILED_ADDR; - } -#endif /* EF_ENV_USING_CACHE */ - - env_start_addr = EF_START_ADDR; - default_env_set = default_env; - default_env_set_size = default_env_size; - - EF_DEBUG("ENV start address is 0x%08X, size is %d bytes.\n", EF_START_ADDR, ENV_AREA_SIZE); - - result = ef_load_env(); - -#ifdef EF_ENV_AUTO_UPDATE - if (result == EF_NO_ERR) { - env_auto_update(); - } -#endif - - if (result == EF_NO_ERR) { - init_ok = true; - } - - return result; -} - -#endif /* defined(EF_USING_ENV) && !defined(EF_ENV_USING_LEGACY_MODE) */ diff --git a/easyflash/src/ef_env_legacy.c b/easyflash/src/ef_env_legacy.c deleted file mode 100644 index c71a714..0000000 --- a/easyflash/src/ef_env_legacy.c +++ /dev/null @@ -1,922 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2014-2018, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Environment variables operating interface. (normal mode) - * Created on: 2014-10-06 - */ - -#include -#include -#include - -#if defined(EF_USING_ENV) && defined(EF_ENV_USING_LEGACY_MODE) - -#ifndef EF_ENV_USING_WL_MODE - -#if defined(EF_USING_ENV) && (!defined(ENV_USER_SETTING_SIZE) || !defined(ENV_AREA_SIZE)) -#error "Please configure user setting ENV size or ENV area size (in ef_cfg.h)" -#endif - -/** - * ENV area has 2 sections - * 1. System section - * It storages ENV parameters. (Units: Word) - * 2. Data section - * It storages all ENV. Storage format is key=value\0. - * All ENV must be 4 bytes alignment. The remaining part must fill '\0'. - * - * @note Word = 4 Bytes in this file - * @note When using power fail safeguard mode, it has two ENV areas(Area0, Area1). - */ - -/* flash ENV parameters index and size in system section */ -enum { - /* data section ENV end address index in system section */ - ENV_PARAM_INDEX_END_ADDR = 0, - -#ifdef EF_ENV_USING_PFS_MODE - /* saved count for ENV area */ - ENV_PARAM_INDEX_SAVED_COUNT, -#endif - -#ifdef EF_ENV_AUTO_UPDATE - /* current version number for ENV */ - ENV_PARAM_INDEX_VER_NUM, -#endif - - /* data section CRC32 code index in system section */ - ENV_PARAM_INDEX_DATA_CRC, - /* flash ENV parameters word size */ - ENV_PARAM_WORD_SIZE, - /* flash ENV parameters byte size */ - ENV_PARAM_BYTE_SIZE = ENV_PARAM_WORD_SIZE * 4, -}; - -/* default ENV set, must be initialized by user */ -static ef_env const *default_env_set; -/* default ENV set size, must be initialized by user */ -static size_t default_env_set_size = 0; -/* ENV ram cache */ -static uint32_t env_cache[ENV_USER_SETTING_SIZE / 4] = { 0 }; -/* ENV start address in flash */ -static uint32_t env_start_addr = 0; -/* ENV ram cache has changed when ENV created, deleted and changed value. */ -static bool env_cache_changed = false; -/* initialize OK flag */ -static bool init_ok = false; - -#ifdef EF_ENV_USING_PFS_MODE -/* current load ENV area address */ -static uint32_t cur_load_area_addr = 0; -/* next save ENV area address */ -static uint32_t next_save_area_addr = 0; -#endif - -static uint32_t get_env_system_addr(void); -static uint32_t get_env_data_addr(void); -static uint32_t get_env_end_addr(void); -static void set_env_end_addr(uint32_t end_addr); -static EfErrCode write_env(const char *key, const char *value); -static char *find_env(const char *key); -static EfErrCode del_env(const char *key); -static size_t get_env_data_size(void); -static size_t get_env_user_used_size(void); -static EfErrCode create_env(const char *key, const char *value); -static uint32_t calc_env_crc(void); -static bool env_crc_is_ok(void); -#ifdef EF_ENV_AUTO_UPDATE -static EfErrCode env_auto_update(void); -#endif - -/** - * Flash ENV initialize. - * - * @param default_env default ENV set for user - * @param default_env_size default ENV set size - * - * @note user_size must equal with total_size in normal mode - * - * @return result - */ -EfErrCode ef_env_init(ef_env const *default_env, size_t default_env_size) { - EfErrCode result = EF_NO_ERR; - - EF_ASSERT(ENV_AREA_SIZE); - EF_ASSERT(ENV_USER_SETTING_SIZE); - EF_ASSERT(EF_ERASE_MIN_SIZE); - /* must be word alignment for ENV */ - EF_ASSERT(ENV_USER_SETTING_SIZE % 4 == 0); - EF_ASSERT(ENV_AREA_SIZE % 4 == 0); - EF_ASSERT(default_env); - EF_ASSERT(default_env_size < ENV_USER_SETTING_SIZE); - -#ifndef EF_ENV_USING_PFS_MODE - /* total_size must be aligned with erase_min_size */ - if (ENV_USER_SETTING_SIZE % EF_ERASE_MIN_SIZE == 0) { - EF_ASSERT(ENV_USER_SETTING_SIZE == ENV_AREA_SIZE); - } else { - EF_ASSERT((ENV_USER_SETTING_SIZE / EF_ERASE_MIN_SIZE + 1)*EF_ERASE_MIN_SIZE == ENV_AREA_SIZE); - } -#else - /* total_size must be aligned with erase_min_size */ - if (ENV_USER_SETTING_SIZE % EF_ERASE_MIN_SIZE == 0) { - /* it has double area when used power fail safeguard mode */ - EF_ASSERT(2 * ENV_USER_SETTING_SIZE == ENV_AREA_SIZE); - } else { - /* it has double area when used power fail safeguard mode */ - EF_ASSERT(2 * (ENV_USER_SETTING_SIZE / EF_ERASE_MIN_SIZE + 1)*EF_ERASE_MIN_SIZE == ENV_AREA_SIZE); - } -#endif - - env_start_addr = EF_START_ADDR; - default_env_set = default_env; - default_env_set_size = default_env_size; - - EF_DEBUG("ENV start address is 0x%08X, size is %d bytes.\n", EF_START_ADDR, ENV_AREA_SIZE); - - result = ef_load_env(); - -#ifdef EF_ENV_AUTO_UPDATE - if (result == EF_NO_ERR) { - env_auto_update(); - } -#endif - - if (result == EF_NO_ERR) { - init_ok = true; - } - - - return result; -} - -/** - * ENV set default. - * - * @return result - */ -EfErrCode ef_env_set_default(void) { - extern EfErrCode ef_env_ver_num_set_default(void); - - EfErrCode result = EF_NO_ERR; - size_t i; - - EF_ASSERT(default_env_set); - EF_ASSERT(default_env_set_size); - - /* lock the ENV cache */ - ef_port_env_lock(); - - /* set environment end address is at data section start address */ - set_env_end_addr(get_env_data_addr()); - -#ifdef EF_ENV_USING_PFS_MODE - /* set saved count to default 0 */ - env_cache[ENV_PARAM_INDEX_SAVED_COUNT] = 0; -#endif - -#ifdef EF_ENV_AUTO_UPDATE - /* initialize version number */ - env_cache[ENV_PARAM_INDEX_VER_NUM] = EF_ENV_VER_NUM; -#endif - - /* create default ENV */ - for (i = 0; i < default_env_set_size; i++) { - create_env(default_env_set[i].key, default_env_set[i].value); - } - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - result = ef_save_env(); - -#ifdef EF_ENV_USING_PFS_MODE - /* reset other PFS area's data */ - if (result == EF_NO_ERR) { - env_cache_changed = true; - result = ef_save_env(); - } -#endif - - return result; -} - -/** - * Get ENV system section start address. - * - * @return system section start address - */ -static uint32_t get_env_system_addr(void) { -#ifndef EF_ENV_USING_PFS_MODE - return env_start_addr; -#else - return cur_load_area_addr; -#endif -} - -/** - * Get ENV data section start address. - * - * @return data section start address - */ -static uint32_t get_env_data_addr(void) { - return get_env_system_addr() + ENV_PARAM_BYTE_SIZE; -} - -/** - * Get ENV end address. - * It's the first word in ENV. - * - * @return ENV end address - */ -static uint32_t get_env_end_addr(void) { - /* it is the first word */ - return env_cache[ENV_PARAM_INDEX_END_ADDR]; -} - -/** - * Set ENV end address. - * It's the first word in ENV. - * - * @param end_addr ENV end address - */ -static void set_env_end_addr(uint32_t end_addr) { - env_cache[ENV_PARAM_INDEX_END_ADDR] = end_addr; -} - -/** - * Get current ENV data section size. - * - * @return size - */ -static size_t get_env_data_size(void) { - if (get_env_end_addr() > get_env_data_addr()) { - return get_env_end_addr() - get_env_data_addr(); - } else { - return 0; - } -} - -/** - * Get current user used ENV size. - * - * @return bytes - */ -static size_t get_env_user_used_size(void) { - if (get_env_end_addr() > get_env_system_addr()) { - return get_env_end_addr() - get_env_system_addr(); - } else { - return 0; - } -} - -/** - * Get current ENV already write bytes. - * - * @return write bytes - */ -size_t ef_get_env_write_bytes(void) { -#ifndef EF_ENV_USING_PFS_MODE - return get_env_user_used_size(); -#else - return get_env_user_used_size() * 2; -#endif -} - -/** - * Write an ENV at the end of cache. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -static EfErrCode write_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - size_t key_len = strlen(key), value_len = strlen(value), env_str_len; - char *env_cache_bak = (char *)env_cache; - - /* calculate ENV storage length, contain '=' and '\0'. */ - env_str_len = key_len + value_len + 2; - if (env_str_len % 4 != 0) { - env_str_len = (env_str_len / 4 + 1) * 4; - } - /* check capacity of ENV */ - if (env_str_len + get_env_user_used_size() >= ENV_USER_SETTING_SIZE) { - return EF_ENV_FULL; - } - - /* calculate current ENV ram cache end address */ - env_cache_bak += get_env_user_used_size(); - - /* copy key name */ - memcpy(env_cache_bak, key, key_len); - env_cache_bak += key_len; - /* copy equal sign */ - *env_cache_bak = '='; - env_cache_bak++; - /* copy value */ - memcpy(env_cache_bak, value, value_len); - env_cache_bak += value_len; - /* fill '\0' for string end sign */ - *env_cache_bak = '\0'; - env_cache_bak ++; - /* fill '\0' for word alignment */ - memset(env_cache_bak, 0, env_str_len - (key_len + value_len + 2)); - set_env_end_addr(get_env_end_addr() + env_str_len); - /* ENV ram cache has changed */ - env_cache_changed = true; - - return result; -} - -/** - * Find ENV. - * - * @param key ENV name - * - * @return found ENV in ram cache - */ -static char *find_env(const char *key) { - char *env_start, *env_end, *env, *found_env = NULL; - size_t key_len = strlen(key), env_len; - - if ((key == NULL) || *key == '\0') { - EF_INFO("Flash ENV name must be not empty!\n"); - return NULL; - } - - /* from data section start to data section end */ - env_start = (char *) ((char *) env_cache + ENV_PARAM_BYTE_SIZE); - env_end = (char *) ((char *) env_cache + get_env_user_used_size()); - - /* ENV is null */ - if (env_start == env_end) { - return NULL; - } - - env = env_start; - while (env < env_end) { - /* the key length must be equal */ - if (!strncmp(env, key, key_len) && (env[key_len] == '=')) { - found_env = env; - break; - } else { - /* calculate ENV length, contain '\0'. */ - env_len = strlen(env) + 1; - /* next ENV and word alignment */ - if (env_len % 4 == 0) { - env += env_len; - } else { - env += (env_len / 4 + 1) * 4; - } - } - } - return found_env; -} - -/** - * If the ENV is not exist, create it. - * @see flash_write_env - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -static EfErrCode create_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - - EF_ASSERT(key); - EF_ASSERT(value); - - if ((key == NULL) || *key == '\0') { - EF_INFO("Flash ENV name must be not empty!\n"); - return EF_ENV_NAME_ERR; - } - - if (strchr(key, '=')) { - EF_INFO("Flash ENV name can't contain '='.\n"); - return EF_ENV_NAME_ERR; - } - - /* find ENV */ - if (find_env(key)) { - EF_INFO("The name of \"%s\" is already exist.\n", key); - return EF_ENV_NAME_EXIST; - } - /* write ENV at the end of cache */ - result = write_env(key, value); - - return result; -} - -/** - * Delete an ENV in cache. - * - * @param key ENV name - * - * @return result - */ -static EfErrCode del_env(const char *key) { - EfErrCode result = EF_NO_ERR; - char *del_env = NULL; - size_t del_env_length, remain_env_length; - - EF_ASSERT(key); - - if ((key == NULL) || *key == '\0') { - EF_INFO("Flash ENV name must be not NULL!\n"); - return EF_ENV_NAME_ERR; - } - - if (strchr(key, '=')) { - EF_INFO("Flash ENV name or value can't contain '='.\n"); - return EF_ENV_NAME_ERR; - } - - /* find ENV */ - del_env = find_env(key); - - if (!del_env) { - EF_INFO("Not find \"%s\" in ENV.\n", key); - return EF_ENV_NAME_ERR; - } - del_env_length = strlen(del_env); - /* '\0' also must be as ENV length */ - del_env_length ++; - /* the address must multiple of 4 */ - if (del_env_length % 4 != 0) { - del_env_length = (del_env_length / 4 + 1) * 4; - } - /* calculate remain ENV length */ - remain_env_length = get_env_data_size() - - (((uint32_t) del_env + del_env_length) - ((uint32_t) env_cache + ENV_PARAM_BYTE_SIZE)); - /* remain ENV move forward */ - memcpy(del_env, del_env + del_env_length, remain_env_length); - /* reset ENV end address */ - set_env_end_addr(get_env_end_addr() - del_env_length); - /* ENV ram cache has changed */ - env_cache_changed = true; - - return result; -} - -/** - * Set an ENV.If it value is NULL, delete it. - * If not find it in ENV table, then create it. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -EfErrCode ef_set_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - char *old_env, *old_value; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return EF_ENV_INIT_FAILED; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - /* if ENV value is NULL, delete it */ - if (value == NULL) { - result = del_env(key); - } else { - old_env = find_env(key); - /* If find this ENV, then compare the new value and old value. */ - if (old_env) { - /* find the old value address */ - old_env = strchr(old_env, '='); - old_value = old_env + 1; - /* If it is changed then delete it and recreate it */ - if (strcmp(old_value, value)) { - result = del_env(key); - if (result == EF_NO_ERR) { - result = create_env(key, value); - } - } - } else { - result = create_env(key, value); - } - } - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * Del an ENV. - * - * @param key ENV name - * - * @return result - */ -EfErrCode ef_del_env(const char *key) { - EfErrCode result = EF_NO_ERR; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return EF_ENV_INIT_FAILED; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - result = del_env(key); - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * Get an ENV value by key name. - * - * @param key ENV name - * - * @return value - */ -char *ef_get_env(const char *key) { - char *env = NULL, *value = NULL; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return NULL; - } - - /* find ENV */ - env = find_env(key); - - if (env == NULL) { - return NULL; - } - /* get value address */ - value = strchr(env, '='); - if (value != NULL) { - /* the equal sign next character is value */ - value++; - } - return value; -} -/** - * Print ENV. - */ -void ef_print_env(void) { - uint32_t *env_cache_data_addr = env_cache + ENV_PARAM_WORD_SIZE, - *env_cache_end_addr = - (uint32_t *) (env_cache + ENV_PARAM_WORD_SIZE + get_env_data_size() / 4); - uint8_t j; - char c; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return; - } - - for (; env_cache_data_addr < env_cache_end_addr; env_cache_data_addr += 1) { - for (j = 0; j < 4; j++) { - c = (*env_cache_data_addr) >> (8 * j); - ef_print("%c", c); - if (c == '\0') { - ef_print("\n"); - break; - } - } - } - -#ifndef EF_ENV_USING_PFS_MODE - ef_print("\nmode: normal\n"); - ef_print("size: %ld/%ld bytes.\n", get_env_user_used_size(), ENV_USER_SETTING_SIZE); -#else - ef_print("\nmode: power fail safeguard\n"); - ef_print("size: %ld/%ld bytes, write bytes %ld/%ld.\n", get_env_user_used_size(), - ENV_USER_SETTING_SIZE, ef_get_env_write_bytes(), ENV_AREA_SIZE); - ef_print("saved count: %ld\n", env_cache[ENV_PARAM_INDEX_SAVED_COUNT]); -#endif - -#ifdef EF_ENV_AUTO_UPDATE - ef_print("ver num: %d\n", env_cache[ENV_PARAM_INDEX_VER_NUM]); -#endif -} - -/** - * Load flash ENV to ram. - * - * @return result - */ -#ifndef EF_ENV_USING_PFS_MODE -EfErrCode ef_load_env(void) { - EfErrCode result = EF_NO_ERR; - uint32_t *env_cache_bak, env_end_addr; - - /* read ENV end address from flash */ - ef_port_read(get_env_system_addr() + ENV_PARAM_INDEX_END_ADDR * 4, &env_end_addr, 4); - /* if ENV is not initialize or flash has dirty data, set default for it */ - if ((env_end_addr == 0xFFFFFFFF) || (env_end_addr < env_start_addr) - || (env_end_addr > env_start_addr + ENV_USER_SETTING_SIZE)) { - result = ef_env_set_default(); - } else { - /* set ENV end address */ - set_env_end_addr(env_end_addr); - - env_cache_bak = env_cache + ENV_PARAM_WORD_SIZE; - /* read all ENV from flash */ - ef_port_read(get_env_data_addr(), env_cache_bak, get_env_data_size()); - /* read ENV CRC code from flash */ - ef_port_read(get_env_system_addr() + ENV_PARAM_INDEX_DATA_CRC * 4, - &env_cache[ENV_PARAM_INDEX_DATA_CRC] , 4); - /* if ENV CRC32 check is fault, set default for it */ - if (!env_crc_is_ok()) { - EF_INFO("Warning: ENV CRC check failed. Set it to default.\n"); - result = ef_env_set_default(); - } - } - return result; -} -#else -EfErrCode ef_load_env(void) { - EfErrCode result = EF_NO_ERR; - uint32_t area0_start_address = env_start_addr, area1_start_address = env_start_addr - + ENV_AREA_SIZE / 2; - uint32_t area0_end_addr, area1_end_addr, area0_crc, area1_crc, area0_saved_count, area1_saved_count; - bool area0_is_valid = true, area1_is_valid = true; - /* read ENV area end address from flash */ - ef_port_read(area0_start_address + ENV_PARAM_INDEX_END_ADDR * 4, &area0_end_addr, 4); - ef_port_read(area1_start_address + ENV_PARAM_INDEX_END_ADDR * 4, &area1_end_addr, 4); - if ((area0_end_addr == 0xFFFFFFFF) || (area0_end_addr < area0_start_address) - || (area0_end_addr > area0_start_address + ENV_USER_SETTING_SIZE)) { - area0_is_valid = false; - } - if ((area1_end_addr == 0xFFFFFFFF) || (area1_end_addr < area1_start_address) - || (area1_end_addr > area1_start_address + ENV_USER_SETTING_SIZE)) { - area1_is_valid = false; - } - /* check area0 CRC when it is valid */ - if (area0_is_valid) { - /* read ENV area0 crc32 code from flash */ - ef_port_read(area0_start_address + ENV_PARAM_INDEX_DATA_CRC * 4, &area0_crc, 4); - /* read ENV from ENV area0 */ - ef_port_read(area0_start_address, env_cache, area0_end_addr - area0_start_address); - /* current load ENV area address is area0 start address */ - cur_load_area_addr = area0_start_address; - if (!env_crc_is_ok()) { - area0_is_valid = false; - } - } - /* check area1 CRC when it is valid */ - if (area1_is_valid) { - /* read ENV area1 crc32 code from flash */ - ef_port_read(area1_start_address + ENV_PARAM_INDEX_DATA_CRC * 4, &area1_crc, 4); - /* read ENV from ENV area1 */ - ef_port_read(area1_start_address, env_cache, area1_end_addr - area1_start_address); - /* current load ENV area address is area1 start address */ - cur_load_area_addr = area1_start_address; - if (!env_crc_is_ok()) { - area1_is_valid = false; - } - } - /* all ENV area CRC is OK then compare saved count */ - if (area0_is_valid && area1_is_valid) { - /* read ENV area saved count from flash */ - ef_port_read(area0_start_address + ENV_PARAM_INDEX_SAVED_COUNT * 4, - &area0_saved_count, 4); - ef_port_read(area1_start_address + ENV_PARAM_INDEX_SAVED_COUNT * 4, - &area1_saved_count, 4); - /* the bigger saved count area is valid */ - if ((area0_saved_count > area1_saved_count) || ((area0_saved_count == 0) && (area1_saved_count == 0xFFFFFFFF))) { - area1_is_valid = false; - } else { - area0_is_valid = false; - } - } - if (area0_is_valid) { - /* current load ENV area address is area0 start address */ - cur_load_area_addr = area0_start_address; - /* next save ENV area address is area1 start address */ - next_save_area_addr = area1_start_address; - /* read all ENV from area0 */ - ef_port_read(area0_start_address, env_cache, area0_end_addr - area0_start_address); - } else if (area1_is_valid) { - /* next save ENV area address is area0 start address */ - next_save_area_addr = area0_start_address; - } else { - /* current load ENV area address is area1 start address */ - cur_load_area_addr = area1_start_address; - /* next save ENV area address is area0 start address */ - next_save_area_addr = area0_start_address; - /* set the ENV to default */ - result = ef_env_set_default(); - } - return result; -} -#endif - -/** - * Save ENV to flash. - */ -EfErrCode ef_save_env(void) { - EfErrCode result = EF_NO_ERR; - uint32_t write_addr, write_size; - - /* ENV ram cache has not changed don't need to save */ - if (!env_cache_changed) { - return result; - } - -#ifndef EF_ENV_USING_PFS_MODE - write_addr = get_env_system_addr(); - write_size = get_env_user_used_size(); - /* calculate and cache CRC32 code */ - env_cache[ENV_PARAM_INDEX_DATA_CRC] = calc_env_crc(); -#else - write_addr = next_save_area_addr; - write_size = get_env_user_used_size(); - /* replace next_save_area_addr with cur_load_area_addr */ - next_save_area_addr = cur_load_area_addr; - cur_load_area_addr = write_addr; - /* change the ENV end address to next save area address */ - set_env_end_addr(write_addr + write_size); - /* ENV area saved count +1 */ - env_cache[ENV_PARAM_INDEX_SAVED_COUNT]++; - /* calculate and cache CRC32 code */ - env_cache[ENV_PARAM_INDEX_DATA_CRC] = calc_env_crc(); -#endif - - /* erase ENV */ - result = ef_port_erase(write_addr, write_size); - switch (result) { - case EF_NO_ERR: { - EF_DEBUG("Erased ENV OK.\n"); - break; - } - case EF_ERASE_ERR: { - EF_INFO("Error: Erased ENV fault! Start address is 0x%08X, size is %ld.\n", write_addr, write_size); - /* will return when erase fault */ - return result; - } - } - - /* write ENV to flash */ - result = ef_port_write(write_addr, env_cache, write_size); - switch (result) { - case EF_NO_ERR: { - EF_DEBUG("Saved ENV OK.\n"); - break; - } - case EF_WRITE_ERR: { - EF_INFO("Error: Saved ENV fault! Start address is 0x%08X, size is %ld.\n", write_addr, write_size); - break; - } - } - - env_cache_changed = false; - - return result; -} - -/** - * Calculate the cached ENV CRC32 value. - * - * @return CRC32 value - */ -static uint32_t calc_env_crc(void) { - uint32_t crc32 = 0; - - /* Calculate the ENV end address CRC32. The 4 is ENV end address bytes size. */ - crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_INDEX_END_ADDR], 4); - -#ifdef EF_ENV_USING_PFS_MODE - /* Calculate the ENV area saved count CRC32. */ - crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_INDEX_SAVED_COUNT], 4); -#endif - - /* Calculate the all ENV data CRC32. */ - crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_WORD_SIZE], get_env_data_size()); - - EF_DEBUG("Calculate ENV CRC32 number is 0x%08X.\n", crc32); - - return crc32; -} - -/** - * Check the ENV CRC32 - * - * @return true is ok - */ -static bool env_crc_is_ok(void) { - if (calc_env_crc() == env_cache[ENV_PARAM_INDEX_DATA_CRC]) { - EF_DEBUG("Verify ENV CRC32 result is OK.\n"); - return true; - } else { - return false; - } -} - -/** - * Set and save an ENV. If set ENV is success then will save it. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -EfErrCode ef_set_and_save_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - - result = ef_set_env(key, value); - - if (result == EF_NO_ERR) { - result = ef_save_env(); - } - - return result; -} - -/** - * Del and save an ENV. If del ENV is success then will save it. - * - * @param key ENV name - * - * @return result - */ -EfErrCode ef_del_and_save_env(const char *key) { - EfErrCode result = EF_NO_ERR; - - result = ef_del_env(key); - - if (result == EF_NO_ERR) { - result = ef_save_env(); - } - - return result; -} - -#ifdef EF_ENV_AUTO_UPDATE -/** - * Auto update ENV to latest default when current EF_ENV_VER is changed. - * - * @return result - */ -static EfErrCode env_auto_update(void) -{ - size_t i; - - /* lock the ENV cache */ - ef_port_env_lock(); - - /* read ENV version number from flash*/ - ef_port_read(get_env_system_addr() + ENV_PARAM_INDEX_VER_NUM * 4, - &env_cache[ENV_PARAM_INDEX_VER_NUM] , 4); - - /* check version number */ - if (env_cache[ENV_PARAM_INDEX_VER_NUM] != EF_ENV_VER_NUM) { - env_cache_changed = true; - /* update version number */ - env_cache[ENV_PARAM_INDEX_VER_NUM] = EF_ENV_VER_NUM; - /* add a new ENV when it's not found */ - for (i = 0; i < default_env_set_size; i++) { - if (find_env(default_env_set[i].key) == NULL) { - create_env(default_env_set[i].key, default_env_set[i].value); - } - } - } - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return ef_save_env(); -} -#endif /* EF_ENV_AUTO_UPDATE */ - -#endif /* EF_ENV_USING_WL_MODE */ - -#endif /* defined(EF_USING_ENV) && defined(EF_ENV_USING_LEGACY_MODE) */ diff --git a/easyflash/src/ef_env_legacy_wl.c b/easyflash/src/ef_env_legacy_wl.c deleted file mode 100644 index 1630890..0000000 --- a/easyflash/src/ef_env_legacy_wl.c +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2018, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Environment variables operating interface. (wear leveling mode) - * Created on: 2015-02-11 - */ - -#include -#include -#include - -#if defined(EF_USING_ENV) && defined(EF_ENV_USING_LEGACY_MODE) - -#ifdef EF_ENV_USING_WL_MODE - -#if defined(EF_USING_ENV) && (!defined(ENV_USER_SETTING_SIZE) || !defined(ENV_AREA_SIZE)) -#error "Please configure user setting ENV size or ENV area size (in ef_cfg.h)" -#endif - -/** - * ENV area has 2 sections - * 1. System section - * Storage ENV current using data section address. - * Units: Word. Total size: @see EF_ERASE_MIN_SIZE. - * 2. Data section - * The data section storage ENV's parameters and detail. - * When an exception has occurred on flash erase or write. The current using data section - * address will move to next available position. This position depends on EF_ERASE_MIN_SIZE. - * 2.1 ENV parameters part - * It storage ENV's parameters. - * 2.2 ENV detail part - * It storage all ENV. Storage format is key=value\0. - * All ENV must be 4 bytes alignment. The remaining part must fill '\0'. - * - * @note Word = 4 Bytes in this file - * @note It will has two ENV areas(Area0, Area1) in data section when used power fail safeguard mode. - */ - -/* flash ENV parameters part index and size */ -enum { - /* data section ENV detail part end address index */ - ENV_PARAM_PART_INDEX_END_ADDR = 0, - -#ifdef EF_ENV_USING_PFS_MODE - /* saved count for ENV area */ - ENV_PARAM_PART_INDEX_SAVED_COUNT, -#endif - -#ifdef EF_ENV_AUTO_UPDATE - /* current version number for ENV */ - ENV_PARAM_INDEX_VER_NUM, -#endif - - /* data section CRC32 code index */ - ENV_PARAM_PART_INDEX_DATA_CRC, - /* ENV parameters part word size */ - ENV_PARAM_PART_WORD_SIZE, - /* ENV parameters part byte size */ - ENV_PARAM_PART_BYTE_SIZE = ENV_PARAM_PART_WORD_SIZE * 4, -}; - -/* default ENV set, must be initialized by user */ -static ef_env const *default_env_set; -/* default ENV set size, must be initialized by user */ -static size_t default_env_set_size = 0; -/* flash ENV data section size */ -static size_t env_data_section_size = 0; -/* ENV ram cache */ -static uint32_t env_cache[ENV_USER_SETTING_SIZE / 4] = { 0 }; -/* ENV start address in flash */ -static uint32_t env_start_addr = 0; -/* current using data section address */ -static uint32_t cur_using_data_addr = 0; -/* ENV ram cache has changed when ENV created, deleted and changed value. */ -static bool env_cache_changed = false; -/* initialize OK flag */ -static bool init_ok = false; - -#ifdef EF_ENV_USING_PFS_MODE -/* next save ENV area address */ -static uint32_t next_save_area_addr = 0; -#endif - -static uint32_t get_env_start_addr(void); -static uint32_t get_cur_using_data_addr(void); -static uint32_t get_env_detail_addr(void); -static uint32_t get_env_detail_end_addr(void); -static void set_cur_using_data_addr(uint32_t using_data_addr); -static void set_env_detail_end_addr(uint32_t end_addr); -static EfErrCode write_env(const char *key, const char *value); -static char *find_env(const char *key); -static size_t get_env_detail_size(void); -static size_t get_env_user_used_size(void); -static EfErrCode create_env(const char *key, const char *value); -static EfErrCode del_env(const char *key); -static EfErrCode save_cur_using_data_addr(uint32_t cur_data_addr); -static uint32_t calc_env_crc(void); -static bool env_crc_is_ok(void); -#ifdef EF_ENV_AUTO_UPDATE -static EfErrCode env_auto_update(void); -#endif - -/** - * Flash ENV initialize. - * - * @param default_env default ENV set for user - * @param default_env_size default ENV set size - * - * @return result - */ -EfErrCode ef_env_init(ef_env const *default_env, size_t default_env_size) { - EfErrCode result = EF_NO_ERR; - - EF_ASSERT(ENV_AREA_SIZE); - EF_ASSERT(ENV_USER_SETTING_SIZE); - /* must be word alignment for ENV */ - EF_ASSERT(ENV_USER_SETTING_SIZE % 4 == 0); - EF_ASSERT(ENV_AREA_SIZE % 4 == 0); - EF_ASSERT(default_env); - EF_ASSERT(default_env_size < ENV_USER_SETTING_SIZE); - -#ifndef EF_ENV_USING_PFS_MODE - /* system section size is erase_min_size, so last part is data section */ - env_data_section_size = ENV_AREA_SIZE - EF_ERASE_MIN_SIZE; -#else - /* system section size is erase_min_size, so last part is data section */ - env_data_section_size = ENV_AREA_SIZE / 2 - EF_ERASE_MIN_SIZE; - EF_ASSERT((ENV_AREA_SIZE / EF_ERASE_MIN_SIZE) % 2 == 0); -#endif - EF_ASSERT(env_data_section_size >= ENV_USER_SETTING_SIZE); - /* the ENV data section size should be an integral multiple of erase minimum size. */ - EF_ASSERT(env_data_section_size % EF_ERASE_MIN_SIZE == 0); - - - env_start_addr = EF_START_ADDR; - default_env_set = default_env; - default_env_set_size = default_env_size; - - EF_DEBUG("ENV start address is 0x%08X, size is %d bytes.\n", EF_START_ADDR, ENV_AREA_SIZE); - - result = ef_load_env(); - -#ifdef EF_ENV_AUTO_UPDATE - if (result == EF_NO_ERR) { - env_auto_update(); - } -#endif - - if (result == EF_NO_ERR) { - init_ok = true; - } - - return result; -} - -/** - * ENV set default. - * - * @return result - */ -EfErrCode ef_env_set_default(void) { - EfErrCode result = EF_NO_ERR; - size_t i; - - EF_ASSERT(default_env_set); - EF_ASSERT(default_env_set_size); - - /* lock the ENV cache */ - ef_port_env_lock(); - - /* set ENV detail part end address is at ENV detail part start address */ - set_env_detail_end_addr(get_env_detail_addr()); - -#ifdef EF_ENV_USING_PFS_MODE - /* set saved count to default 0 */ - env_cache[ENV_PARAM_PART_INDEX_SAVED_COUNT] = 0; -#endif - -#ifdef EF_ENV_AUTO_UPDATE - /* initialize version number */ - env_cache[ENV_PARAM_INDEX_VER_NUM] = EF_ENV_VER_NUM; -#endif - - /* create default ENV */ - for (i = 0; i < default_env_set_size; i++) { - create_env(default_env_set[i].key, default_env_set[i].value); - } - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - result = ef_save_env(); - -#ifdef EF_ENV_USING_PFS_MODE - /* reset other PFS area's data */ - if (result == EF_NO_ERR) { - env_cache_changed = true; - result = ef_save_env(); - } -#endif - - return result; -} - -/** - * Get ENV start address in flash. - * - * @return ENV start address in flash - */ -static uint32_t get_env_start_addr(void) { - return env_start_addr; -} -/** - * Get current using data section address. - * - * @return current using data section address - */ -static uint32_t get_cur_using_data_addr(void) { - return cur_using_data_addr; -} - -/** - * Set current using data section address. - * - * @param using_data_addr current using data section address - */ -static void set_cur_using_data_addr(uint32_t using_data_addr) { - cur_using_data_addr = using_data_addr; -} - -/** - * Get ENV detail part start address. - * - * @return detail part start address - */ -static uint32_t get_env_detail_addr(void) { - return get_cur_using_data_addr() + ENV_PARAM_PART_BYTE_SIZE; -} - -/** - * Get ENV detail part end address. - * It's the first word in ENV. - * - * @return ENV end address - */ -static uint32_t get_env_detail_end_addr(void) { - /* it is the first word */ - return env_cache[ENV_PARAM_PART_INDEX_END_ADDR]; -} - -/** - * Set ENV detail part end address. - * It's the first word in ENV. - * - * @param end_addr ENV end address - */ -static void set_env_detail_end_addr(uint32_t end_addr) { - env_cache[ENV_PARAM_PART_INDEX_END_ADDR] = end_addr; -} - -/** - * Get current ENV detail part size. - * - * @return size - */ -static size_t get_env_detail_size(void) { - if (get_env_detail_end_addr() > get_env_detail_addr()) { - return get_env_detail_end_addr() - get_env_detail_addr(); - } else { - return 0; - } -} - -/** - * Get current user used ENV size. - * - * @see ENV_USER_SETTING_SIZE - * - * @return size - */ -/* must be initialized */ -static size_t get_env_user_used_size(void) { - if (get_env_detail_end_addr() > get_cur_using_data_addr()) { - return get_env_detail_end_addr() - get_cur_using_data_addr(); - } else { - return 0; - } -} - -/** - * Get current ENV already write bytes. - * - * @return write bytes - */ -size_t ef_get_env_write_bytes(void) { -#ifndef EF_ENV_USING_PFS_MODE - return get_env_detail_end_addr() - get_env_start_addr(); -#else - return EF_ERASE_MIN_SIZE + get_env_detail_end_addr() - get_cur_using_data_addr(); -#endif -} - -/** - * Write an ENV at the end of cache. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -static EfErrCode write_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - size_t ker_len = strlen(key), value_len = strlen(value), env_str_len; - char *env_cache_bak = (char *)env_cache; - - /* calculate ENV storage length, contain '=' and '\0'. */ - env_str_len = ker_len + value_len + 2; - if (env_str_len % 4 != 0) { - env_str_len = (env_str_len / 4 + 1) * 4; - } - /* check capacity of ENV */ - if (env_str_len + get_env_user_used_size() >= ENV_USER_SETTING_SIZE) { - return EF_ENV_FULL; - } - /* calculate current ENV ram cache end address */ - env_cache_bak += ENV_PARAM_PART_BYTE_SIZE + get_env_detail_size(); - /* copy key name */ - memcpy(env_cache_bak, key, ker_len); - env_cache_bak += ker_len; - /* copy equal sign */ - *env_cache_bak = '='; - env_cache_bak++; - /* copy value */ - memcpy(env_cache_bak, value, value_len); - env_cache_bak += value_len; - /* fill '\0' for string end sign */ - *env_cache_bak = '\0'; - env_cache_bak ++; - /* fill '\0' for word alignment */ - memset(env_cache_bak, 0, env_str_len - (ker_len + value_len + 2)); - set_env_detail_end_addr(get_env_detail_end_addr() + env_str_len); - /* ENV ram cache has changed */ - env_cache_changed = true; - - return result; -} - -/** - * Find ENV. - * - * @param key ENV name - * - * @return found ENV in ram cache - */ -static char *find_env(const char *key) { - char *env_start, *env_end, *env, *found_env = NULL; - size_t key_len = strlen(key), env_len; - - if ((key == NULL) || (*key == '\0')) { - EF_INFO("Flash ENV name must be not empty!\n"); - return NULL; - } - - /* from data section start to data section end */ - env_start = (char *) ((char *) env_cache + ENV_PARAM_PART_BYTE_SIZE); - env_end = (char *) ((char *) env_cache + ENV_PARAM_PART_BYTE_SIZE + get_env_detail_size()); - - /* ENV is null */ - if (env_start == env_end) { - return NULL; - } - - env = env_start; - while (env < env_end) { - /* the key length must be equal */ - if (!strncmp(env, key, key_len) && (env[key_len] == '=')) { - found_env = env; - break; - } else { - /* calculate ENV length, contain '\0'. */ - env_len = strlen(env) + 1; - /* next ENV and word alignment */ - if (env_len % 4 == 0) { - env += env_len; - } else { - env += (env_len / 4 + 1) * 4; - } - } - } - - return found_env; -} - -/** - * If the ENV is not exist, create it. - * @see flash_write_env - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -static EfErrCode create_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - - EF_ASSERT(key); - EF_ASSERT(value); - - if ((key == NULL) || (*key == '\0')) { - EF_INFO("Flash ENV name must be not empty!\n"); - return EF_ENV_NAME_ERR; - } - - if (strchr(key, '=')) { - EF_INFO("Flash ENV name can't contain '='.\n"); - return EF_ENV_NAME_ERR; - } - - /* find ENV */ - if (find_env(key)) { - EF_INFO("The name of \"%s\" is already exist.\n", key); - return EF_ENV_NAME_EXIST; - } - /* write ENV at the end of cache */ - result = write_env(key, value); - - return result; -} - -/** - * Delete an ENV in cache. - * - * @param key ENV name - * - * @return result - */ -static EfErrCode del_env(const char *key) { - EfErrCode result = EF_NO_ERR; - char *del_env = NULL; - size_t del_env_length, remain_env_length; - - EF_ASSERT(key); - - if ((key == NULL) || (*key == '\0')) { - EF_INFO("Flash ENV name must be not NULL!\n"); - return EF_ENV_NAME_ERR; - } - - if (strchr(key, '=')) { - EF_INFO("Flash ENV name or value can't contain '='.\n"); - return EF_ENV_NAME_ERR; - } - - /* find ENV */ - del_env = find_env(key); - - if (!del_env) { - EF_INFO("Not find \"%s\" in ENV.\n", key); - return EF_ENV_NAME_ERR; - } - del_env_length = strlen(del_env); - /* '\0' also must be as ENV length */ - del_env_length ++; - /* the address must multiple of 4 */ - if (del_env_length % 4 != 0) { - del_env_length = (del_env_length / 4 + 1) * 4; - } - /* calculate remain ENV length */ - remain_env_length = get_env_detail_size() - - (((uint32_t) del_env + del_env_length) - ((uint32_t) env_cache + ENV_PARAM_PART_BYTE_SIZE)); - /* remain ENV move forward */ - memcpy(del_env, del_env + del_env_length, remain_env_length); - /* reset ENV end address */ - set_env_detail_end_addr(get_env_detail_end_addr() - del_env_length); - /* ENV ram cache has changed */ - env_cache_changed = true; - - return result; -} - -/** - * Set an ENV.If it value is NULL, delete it. - * If not find it in ENV table, then create it. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -EfErrCode ef_set_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - char *old_env, *old_value; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return EF_ENV_INIT_FAILED; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - /* if ENV value is NULL, delete it */ - if (value == NULL) { - result = del_env(key); - } else { - old_env = find_env(key); - /* If find this ENV, then compare the new value and old value. */ - if (old_env) { - /* find the old value address */ - old_env = strchr(old_env, '='); - old_value = old_env + 1; - /* If it is changed then delete it and recreate it */ - if (strcmp(old_value, value)) { - result = del_env(key); - if (result == EF_NO_ERR) { - result = create_env(key, value); - } - } - } else { - result = create_env(key, value); - } - } - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * Del an ENV. - * - * @param key ENV name - * - * @return result - */ -EfErrCode ef_del_env(const char *key) { - EfErrCode result = EF_NO_ERR; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return EF_ENV_INIT_FAILED; - } - - /* lock the ENV cache */ - ef_port_env_lock(); - - result = del_env(key); - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return result; -} - -/** - * Get an ENV value by key name. - * - * @param key ENV name - * - * @return value - */ -char *ef_get_env(const char *key) { - char *env = NULL, *value = NULL; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return NULL; - } - - /* find ENV */ - env = find_env(key); - - if (env == NULL) { - return NULL; - } - /* get value address */ - value = strchr(env, '='); - if (value != NULL) { - /* the equal sign next character is value */ - value++; - } - return value; -} -/** - * Print ENV. - */ -void ef_print_env(void) { - uint32_t *env_cache_detail_addr = env_cache + ENV_PARAM_PART_WORD_SIZE, *env_cache_end_addr = - (uint32_t *) (env_cache + ENV_PARAM_PART_WORD_SIZE + get_env_detail_size() / 4); - uint8_t j; - char c; - - if (!init_ok) { - EF_INFO("ENV isn't initialize OK.\n"); - return; - } - - for (; env_cache_detail_addr < env_cache_end_addr; env_cache_detail_addr += 1) { - for (j = 0; j < 4; j++) { - c = (*env_cache_detail_addr) >> (8 * j); - ef_print("%c", c); - if (c == '\0') { - ef_print("\n"); - break; - } - } - } - -#ifndef EF_ENV_USING_PFS_MODE - ef_print("\nmode: wear leveling\n"); - ef_print("size: %ld/%ld bytes, write bytes %ld/%ld.\n", get_env_user_used_size(), ENV_USER_SETTING_SIZE, - ef_get_env_write_bytes(), ENV_AREA_SIZE); -#else - ef_print("\nmode: wear leveling and power fail safeguard\n"); - ef_print("size: %ld/%ld bytes, write bytes %ld/%ld.\n", get_env_user_used_size(), ENV_USER_SETTING_SIZE, - ef_get_env_write_bytes(), ENV_AREA_SIZE / 2); - ef_print("saved count: %ld\n", env_cache[ENV_PARAM_PART_INDEX_SAVED_COUNT]); -#endif - -#ifdef EF_ENV_AUTO_UPDATE - ef_print("ver num: %d\n", env_cache[ENV_PARAM_INDEX_VER_NUM]); -#endif -} - -/** - * Load flash ENV to ram. - * - * @return result - */ -#ifndef EF_ENV_USING_PFS_MODE -EfErrCode ef_load_env(void) { - EfErrCode result = EF_NO_ERR; - uint32_t *env_cache_bak, env_end_addr, using_data_addr; - - /* read current using data section address */ - ef_port_read(get_env_start_addr(), &using_data_addr, 4); - /* if ENV is not initialize or flash has dirty data, set default for it */ - if ((using_data_addr == 0xFFFFFFFF) - || (using_data_addr > get_env_start_addr() + ENV_AREA_SIZE) - || (using_data_addr < get_env_start_addr() + EF_ERASE_MIN_SIZE)) { - /* initialize current using data section address */ - set_cur_using_data_addr(get_env_start_addr() + EF_ERASE_MIN_SIZE); - /* save current using data section address to flash*/ - if ((result = save_cur_using_data_addr(get_cur_using_data_addr())) == EF_NO_ERR) { - /* set default ENV */ - result = ef_env_set_default(); - } - } else { - /* set current using data section address */ - set_cur_using_data_addr(using_data_addr); - /* read ENV detail part end address from flash */ - ef_port_read(get_cur_using_data_addr() + ENV_PARAM_PART_INDEX_END_ADDR * 4, &env_end_addr, 4); - /* if ENV end address has error, set default for ENV */ - if (env_end_addr > get_env_start_addr() + ENV_AREA_SIZE) { - /* initialize current using data section address */ - set_cur_using_data_addr(get_env_start_addr() + EF_ERASE_MIN_SIZE); - /* save current using data section address to flash*/ - if ((result = save_cur_using_data_addr(get_cur_using_data_addr())) == EF_NO_ERR) { - EF_INFO("Warning: ENV end address has error. Set it to default.\n"); - result = ef_env_set_default(); - } - } else { - /* set ENV detail part end address */ - set_env_detail_end_addr(env_end_addr); - - env_cache_bak = env_cache + ENV_PARAM_PART_WORD_SIZE; - /* read all ENV from flash */ - ef_port_read(get_env_detail_addr(), env_cache_bak, get_env_detail_size()); - /* read ENV CRC code from flash */ - ef_port_read(get_cur_using_data_addr() + ENV_PARAM_PART_INDEX_DATA_CRC * 4, - &env_cache[ENV_PARAM_PART_INDEX_DATA_CRC], 4); - /* if ENV CRC32 check is fault, set default for it */ - if (!env_crc_is_ok()) { - EF_INFO("Warning: ENV CRC check failed. Set it to default.\n"); - result = ef_env_set_default(); - } - } - - } - return result; -} -#else -EfErrCode ef_load_env(void) { - EfErrCode result = EF_NO_ERR; - /* ENV area0 current using address default value */ - uint32_t area0_default_cur_using_addr = get_env_start_addr() + EF_ERASE_MIN_SIZE; - /* ENV area1 current using address default value */ - uint32_t area1_default_cur_using_addr = area0_default_cur_using_addr + ENV_AREA_SIZE / 2; - uint32_t area0_cur_using_addr, area1_cur_using_addr, area0_end_addr, area1_end_addr; - uint32_t area0_crc, area1_crc, area0_saved_count, area1_saved_count; - bool area0_is_valid = true, area1_is_valid = true; - - /* read ENV area0 and area1 current using data section address */ - ef_port_read(get_env_start_addr(), &area0_cur_using_addr, 4); - ef_port_read(get_env_start_addr() + ENV_AREA_SIZE / 2, &area1_cur_using_addr, 4); - /* if ENV is not initialize or flash has dirty data, set it isn't valid */ - if ((area0_cur_using_addr == 0xFFFFFFFF) - || (area0_cur_using_addr > get_env_start_addr() + ENV_AREA_SIZE / 2) - || (area0_cur_using_addr < get_env_start_addr() + EF_ERASE_MIN_SIZE)) { - area0_is_valid = false; - } - if ((area1_cur_using_addr == 0xFFFFFFFF) - || (area1_cur_using_addr > get_env_start_addr() + ENV_AREA_SIZE) - || (area1_cur_using_addr < get_env_start_addr() + ENV_AREA_SIZE / 2 + EF_ERASE_MIN_SIZE)) { - area1_is_valid = false; - } - /* check area0 end address when it is valid */ - if (area0_is_valid) { - /* read ENV area end address from flash */ - ef_port_read(area0_cur_using_addr + ENV_PARAM_PART_INDEX_END_ADDR * 4, &area0_end_addr, 4); - if ((area0_end_addr == 0xFFFFFFFF) || (area0_end_addr < area0_cur_using_addr) - || (area0_end_addr > area0_cur_using_addr + ENV_USER_SETTING_SIZE)) { - area0_is_valid = false; - } - } - /* check area1 end address when it is valid */ - if (area1_is_valid) { - /* read ENV area end address from flash */ - ef_port_read(area1_cur_using_addr + ENV_PARAM_PART_INDEX_END_ADDR * 4, &area1_end_addr, 4); - if ((area1_end_addr == 0xFFFFFFFF) || (area1_end_addr < area1_cur_using_addr) - || (area1_end_addr > area1_cur_using_addr + ENV_USER_SETTING_SIZE)) { - area1_is_valid = false; - } - } - /* check area0 CRC when it is valid */ - if (area0_is_valid) { - /* read ENV area0 crc32 code from flash */ - ef_port_read(area0_cur_using_addr + ENV_PARAM_PART_INDEX_DATA_CRC * 4, &area0_crc, 4); - /* read ENV from ENV area0 */ - ef_port_read(area0_cur_using_addr, env_cache, area0_end_addr - area0_cur_using_addr); - /* current using data section address is area0 current using data section address */ - set_cur_using_data_addr(area0_cur_using_addr); - if (!env_crc_is_ok()) { - area0_is_valid = false; - } - } - /* check area1 CRC when it is valid */ - if (area1_is_valid) { - /* read ENV area1 crc32 code from flash */ - ef_port_read(area1_cur_using_addr + ENV_PARAM_PART_INDEX_DATA_CRC * 4, &area1_crc, 4); - /* read ENV from ENV area1 */ - ef_port_read(area1_cur_using_addr, env_cache, area1_end_addr - area1_cur_using_addr); - /* current using data section address is area1 current using data section address */ - set_cur_using_data_addr(area1_cur_using_addr); - if (!env_crc_is_ok()) { - area1_is_valid = false; - } - } - /* all ENV area CRC is OK then compare saved count */ - if (area0_is_valid && area1_is_valid) { - /* read ENV area saved count from flash */ - ef_port_read(area0_cur_using_addr + ENV_PARAM_PART_INDEX_SAVED_COUNT * 4, - &area0_saved_count, 4); - ef_port_read(area1_cur_using_addr + ENV_PARAM_PART_INDEX_SAVED_COUNT * 4, - &area1_saved_count, 4); - /* the bigger saved count area is valid */ - if ((area0_saved_count > area1_saved_count) || ((area0_saved_count == 0) && (area1_saved_count == 0xFFFFFFFF))) { - area1_is_valid = false; - } else { - area0_is_valid = false; - } - } - if (area0_is_valid) { - /* current using data section address is area0 current using data section address */ - set_cur_using_data_addr(area0_cur_using_addr); - /* next save ENV area address is area1 current using address value */ - next_save_area_addr = area1_cur_using_addr; - /* read all ENV from area0 */ - ef_port_read(area0_cur_using_addr, env_cache, area0_end_addr - area0_cur_using_addr); - } else if (area1_is_valid) { - /* already read data section and set_cur_using_data_addr above current code, - * so just set next save ENV area address is area0 current using address value */ - next_save_area_addr = area0_cur_using_addr; - } else { - /* current using data section address is area1 current using address default value */ - set_cur_using_data_addr(area1_default_cur_using_addr); - /* next save ENV area address default is area0 current using address default value */ - next_save_area_addr = area0_default_cur_using_addr; - /* save current using data section address to flash*/ - if (((result = save_cur_using_data_addr(area0_default_cur_using_addr)) == EF_NO_ERR) - && ((result = save_cur_using_data_addr(area1_default_cur_using_addr)) == EF_NO_ERR)) { - /* set the ENV to default */ - result = ef_env_set_default(); - } - } - return result; -} -#endif - -/** - * Save ENV to flash. - */ -EfErrCode ef_save_env(void) { - EfErrCode result = EF_NO_ERR; - uint32_t cur_using_addr_bak, move_offset_addr; - size_t env_used_size = get_env_user_used_size(); - uint32_t data_sec_end_addr; - - /* ENV ram cache has not changed don't need to save */ - if (!env_cache_changed) { - return result; - } - -#ifndef EF_ENV_USING_PFS_MODE - data_sec_end_addr = get_env_start_addr() + ENV_AREA_SIZE - 4; - cur_using_addr_bak = get_cur_using_data_addr(); -#else - cur_using_addr_bak = next_save_area_addr; - /* replace next_save_area_addr with cur_using_data_addr */ - next_save_area_addr = get_cur_using_data_addr(); - set_cur_using_data_addr(cur_using_addr_bak); - /* change the ENV detail end address to next save area address */ - set_env_detail_end_addr(get_cur_using_data_addr() + env_used_size); - /* area0 or area1 */ - if (get_cur_using_data_addr() < get_env_start_addr() + ENV_AREA_SIZE / 2) { - data_sec_end_addr = get_env_start_addr() + ENV_AREA_SIZE / 2 - 4; - } else { - data_sec_end_addr = get_env_start_addr() + ENV_AREA_SIZE - 4; - } - /* ENV area saved count +1 */ - env_cache[ENV_PARAM_PART_INDEX_SAVED_COUNT]++; -#endif - - /* wear leveling process, automatic move ENV to next available position */ - while (get_cur_using_data_addr() + env_used_size < data_sec_end_addr) { - /* calculate and cache CRC32 code */ - env_cache[ENV_PARAM_PART_INDEX_DATA_CRC] = calc_env_crc(); - /* erase ENV */ - result = ef_port_erase(get_cur_using_data_addr(), env_used_size); - switch (result) { - case EF_NO_ERR: { - EF_DEBUG("Erased ENV OK.\n"); - break; - } - case EF_ERASE_ERR: { - EF_INFO("Warning: Erased ENV fault! Start address is 0x%08X, size is %ld.\n", - get_cur_using_data_addr(), env_used_size); - EF_INFO("Moving ENV to next available position.\n"); - /* Calculate move offset address. - * Current strategy is optimistic. It will offset the flash erasure minimum size. - */ - move_offset_addr = EF_ERASE_MIN_SIZE; - /* calculate and set next available data section address */ - set_cur_using_data_addr(get_cur_using_data_addr() + move_offset_addr); - /* calculate and set next available ENV detail part end address */ - set_env_detail_end_addr(get_env_detail_end_addr() + move_offset_addr); - continue; - } - } - /* write ENV to flash */ - result = ef_port_write(get_cur_using_data_addr(), env_cache, env_used_size); - switch (result) { - case EF_NO_ERR: { - EF_DEBUG("Saved ENV OK.\n"); - break; - } - case EF_WRITE_ERR: { - EF_INFO("Warning: Saved ENV fault! Start address is 0x%08X, size is %ld.\n", - get_cur_using_data_addr(), env_used_size); - EF_INFO("Moving ENV to next available position.\n"); - /* Calculate move offset address. - * Current strategy is optimistic. It will offset the flash erasure minimum size. - */ - move_offset_addr = EF_ERASE_MIN_SIZE; - /* calculate and set next available data section address */ - set_cur_using_data_addr(get_cur_using_data_addr() + move_offset_addr); - /* calculate and set next available ENV detail part end address */ - set_env_detail_end_addr(get_env_detail_end_addr() + move_offset_addr); - continue; - } - } - /* save ENV success */ - if (result == EF_NO_ERR) { - break; - } - } - - if (get_cur_using_data_addr() + env_used_size < data_sec_end_addr) { - /* current using data section address has changed, save it */ - if (get_cur_using_data_addr() != cur_using_addr_bak) { - result = save_cur_using_data_addr(get_cur_using_data_addr()); - } - } else { - result = EF_ENV_FULL; - EF_INFO("Error: The flash has no available space to save ENV.\n"); - } - - env_cache_changed = false; - - return result; -} - -/** - * Calculate the cached ENV CRC32 value. - * - * @return CRC32 value - */ -static uint32_t calc_env_crc(void) { - uint32_t crc32 = 0; - - /* Calculate the ENV end address and all ENV data CRC32. - * The 4 is ENV end address bytes size. */ - crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_PART_INDEX_END_ADDR], 4); - crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_PART_WORD_SIZE], get_env_detail_size()); - EF_DEBUG("Calculate ENV CRC32 number is 0x%08X.\n", crc32); - - return crc32; -} - -/** - * Check the ENV CRC32 - * - * @return true is ok - */ -static bool env_crc_is_ok(void) { - if (calc_env_crc() == env_cache[ENV_PARAM_PART_INDEX_DATA_CRC]) { - EF_DEBUG("Verify ENV CRC32 result is OK.\n"); - return true; - } else { - return false; - } -} - -/** - * Save current using data section address to flash. - * - * @param cur_data_addr current using data section address - * - * @return result - */ -#ifndef EF_ENV_USING_PFS_MODE -static EfErrCode save_cur_using_data_addr(uint32_t cur_data_addr) { - EfErrCode result = EF_NO_ERR; - - /* erase ENV system section */ - result = ef_port_erase(get_env_start_addr(), 4); - if (result == EF_NO_ERR) { - /* write current using data section address to flash */ - result = ef_port_write(get_env_start_addr(), &cur_data_addr, 4); - if (result == EF_WRITE_ERR) { - EF_INFO("Error: Write system section fault! Start address is 0x%08X, size is %ld.\n", - get_env_start_addr(), 4); - EF_INFO("Note: The ENV can not be used.\n"); - } - } else { - EF_INFO("Error: Erased system section fault! Start address is 0x%08X, size is %ld.\n", - get_env_start_addr(), 4); - EF_INFO("Note: The ENV can not be used\n"); - } - return result; -} -#else -static EfErrCode save_cur_using_data_addr(uint32_t cur_data_addr) { - EfErrCode result = EF_NO_ERR; - uint32_t cur_system_sec_addr; - - if (cur_data_addr < get_env_start_addr() + ENV_AREA_SIZE / 2) { - /* current using system section is in ENV area0 */ - cur_system_sec_addr = get_env_start_addr(); - } else { - /* current using system section is in ENV area1 */ - cur_system_sec_addr = get_env_start_addr() + ENV_AREA_SIZE / 2; - } - /* erase ENV system section */ - result = ef_port_erase(cur_system_sec_addr, 4); - if (result == EF_NO_ERR) { - /* write area0 and area1 current using data section address to flash */ - result = ef_port_write(cur_system_sec_addr, &cur_data_addr, 4); - if (result == EF_WRITE_ERR) { - EF_INFO("Error: Write system section fault! Start address is 0x%08X, size is %ld.\n", - cur_system_sec_addr, 4); - EF_INFO("Note: The ENV can not be used.\n"); - } - } else { - EF_INFO("Error: Erased system section fault! Start address is 0x%08X, size is %ld.\n", - cur_system_sec_addr, 4); - EF_INFO("Note: The ENV can not be used\n"); - } - return result; -} -#endif - -/** - * Set and save an ENV. If set ENV is success then will save it. - * - * @param key ENV name - * @param value ENV value - * - * @return result - */ -EfErrCode ef_set_and_save_env(const char *key, const char *value) { - EfErrCode result = EF_NO_ERR; - - result = ef_set_env(key, value); - - if (result == EF_NO_ERR) { - result = ef_save_env(); - } - - return result; -} - -/** - * Del and save an ENV. If del ENV is success then will save it. - * - * @param key ENV name - * - * @return result - */ -EfErrCode ef_del_and_save_env(const char *key) { - EfErrCode result = EF_NO_ERR; - - result = ef_del_env(key); - - if (result == EF_NO_ERR) { - result = ef_save_env(); - } - - return result; -} - -#ifdef EF_ENV_AUTO_UPDATE -/** - * Auto update ENV to latest default when current EF_ENV_VER is changed. - * - * @return result - */ -static EfErrCode env_auto_update(void) -{ - size_t i; - - /* lock the ENV cache */ - ef_port_env_lock(); - - /* read ENV version number from flash*/ - ef_port_read(get_cur_using_data_addr() + ENV_PARAM_INDEX_VER_NUM * 4, - &env_cache[ENV_PARAM_INDEX_VER_NUM] , 4); - - /* check version number */ - if (env_cache[ENV_PARAM_INDEX_VER_NUM] != EF_ENV_VER_NUM) { - env_cache_changed = true; - /* update version number */ - env_cache[ENV_PARAM_INDEX_VER_NUM] = EF_ENV_VER_NUM; - /* add a new ENV when it's not found */ - for (i = 0; i < default_env_set_size; i++) { - if (find_env(default_env_set[i].key) == NULL) { - create_env(default_env_set[i].key, default_env_set[i].value); - } - } - } - - /* unlock the ENV cache */ - ef_port_env_unlock(); - - return ef_save_env(); -} -#endif /* EF_ENV_AUTO_UPDATE */ - -#endif /* EF_ENV_USING_WL_MODE */ - -#endif /* defined(EF_USING_ENV) && defined(EF_ENV_USING_LEGACY_MODE) */ diff --git a/easyflash/src/ef_iap.c b/easyflash/src/ef_iap.c deleted file mode 100644 index b51a483..0000000 --- a/easyflash/src/ef_iap.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2017, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: IAP(In-Application Programming) operating interface. - * Created on: 2015-01-05 - */ - -#include - -#ifdef EF_USING_IAP - -/* IAP section backup application section start address in flash */ -static uint32_t bak_app_start_addr = 0; - -/** - * Flash IAP function initialize. - * - * @return result - */ -EfErrCode ef_iap_init(void) { - EfErrCode result = EF_NO_ERR; - - bak_app_start_addr = EF_START_ADDR ; - -#if defined(EF_USING_ENV) - bak_app_start_addr += ENV_AREA_SIZE; -#endif - -#if defined(EF_USING_LOG) - bak_app_start_addr += LOG_AREA_SIZE; -#endif - - return result; -} - -/** - * Erase backup area application data. - * - * @param app_size application size - * - * @return result - */ -EfErrCode ef_erase_bak_app(size_t app_size) { - EfErrCode result = EF_NO_ERR; - - result = ef_port_erase(ef_get_bak_app_start_addr(), app_size); - switch (result) { - case EF_NO_ERR: { - EF_INFO("Erased backup area application OK.\n"); - break; - } - case EF_ERASE_ERR: { - EF_INFO("Warning: Erase backup area application fault!\n"); - /* will return when erase fault */ - return result; - } - } - - return result; -} - -/** - * Erase user old application by using specified erase function. - * - * @param user_app_addr application entry address - * @param app_size application size - * @param app_erase user specified application erase function - * - * @return result - */ -EfErrCode ef_erase_spec_user_app(uint32_t user_app_addr, size_t app_size, - EfErrCode (*app_erase)(uint32_t addr, size_t size)) { - EfErrCode result = EF_NO_ERR; - - result = app_erase(user_app_addr, app_size); - switch (result) { - case EF_NO_ERR: { - EF_INFO("Erased user application OK.\n"); - break; - } - case EF_ERASE_ERR: { - EF_INFO("Warning: Erase user application fault!\n"); - /* will return when erase fault */ - return result; - } - } - - return result; -} - -/** - * Erase user old application by using default `ef_port_erase` function. - * - * @param user_app_addr application entry address - * @param app_size application size - * - * @return result - */ -EfErrCode ef_erase_user_app(uint32_t user_app_addr, size_t app_size) { - return ef_erase_spec_user_app(user_app_addr, app_size, ef_port_erase); -} - -/** - * Erase old bootloader - * - * @param bl_addr bootloader entry address - * @param bl_size bootloader size - * - * @return result - */ -EfErrCode ef_erase_bl(uint32_t bl_addr, size_t bl_size) { - EfErrCode result = EF_NO_ERR; - - result = ef_port_erase(bl_addr, bl_size); - switch (result) { - case EF_NO_ERR: { - EF_INFO("Erased bootloader OK.\n"); - break; - } - case EF_ERASE_ERR: { - EF_INFO("Warning: Erase bootloader fault!\n"); - /* will return when erase fault */ - return result; - } - } - - return result; -} - -/** - * Write data of application to backup area. - * - * @param data a part of application - * @param size data size - * @param cur_size current write application size - * @param total_size application total size - * - * @return result - */ -EfErrCode ef_write_data_to_bak(uint8_t *data, size_t size, size_t *cur_size, - size_t total_size) { - EfErrCode result = EF_NO_ERR; - - /* make sure don't write excess data */ - if (*cur_size + size > total_size) { - size = total_size - *cur_size; - } - - result = ef_port_write(ef_get_bak_app_start_addr() + *cur_size, (uint32_t *) data, size); - switch (result) { - case EF_NO_ERR: { - *cur_size += size; - EF_DEBUG("Write data to backup area OK.\n"); - break; - } - case EF_WRITE_ERR: { - EF_INFO("Warning: Write data to backup area fault!\n"); - break; - } - } - - return result; -} - -/** - * Copy backup area application to application entry by using specified write function. - * - * @param user_app_addr application entry address - * @param app_size application size - * @param app_write user specified application write function - * - * @return result - */ -EfErrCode ef_copy_spec_app_from_bak(uint32_t user_app_addr, size_t app_size, - EfErrCode (*app_write)(uint32_t addr, const uint32_t *buf, size_t size)) { - size_t cur_size; - uint32_t app_cur_addr, bak_cur_addr; - EfErrCode result = EF_NO_ERR; - /* 32 words size buffer */ - uint32_t buff[32]; - - /* cycle copy data */ - for (cur_size = 0; cur_size < app_size; cur_size += sizeof(buff)) { - app_cur_addr = user_app_addr + cur_size; - bak_cur_addr = ef_get_bak_app_start_addr() + cur_size; - ef_port_read(bak_cur_addr, buff, sizeof(buff)); - result = app_write(app_cur_addr, buff, sizeof(buff)); - if (result != EF_NO_ERR) { - break; - } - } - - switch (result) { - case EF_NO_ERR: { - EF_INFO("Write data to application entry OK.\n"); - break; - } - case EF_WRITE_ERR: { - EF_INFO("Warning: Write data to application entry fault!\n"); - break; - } - } - - return result; -} - -/** - * Copy backup area application to application entry by using default `ef_port_write` function. - * - * @param user_app_addr application entry address - * @param app_size application size - * - * @return result - */ -EfErrCode ef_copy_app_from_bak(uint32_t user_app_addr, size_t app_size) { - return ef_copy_spec_app_from_bak(user_app_addr, app_size, ef_port_write); -} - -/** - * Copy backup area bootloader to bootloader entry. - * - * @param bl_addr bootloader entry address - * @param bl_size bootloader size - * - * @return result - */ -EfErrCode ef_copy_bl_from_bak(uint32_t bl_addr, size_t bl_size) { - size_t cur_size; - uint32_t bl_cur_addr, bak_cur_addr; - EfErrCode result = EF_NO_ERR; - /* 32 words buffer */ - uint32_t buff[32]; - - /* cycle copy data by 32bytes buffer */ - for (cur_size = 0; cur_size < bl_size; cur_size += sizeof(buff)) { - bl_cur_addr = bl_addr + cur_size; - bak_cur_addr = ef_get_bak_app_start_addr() + cur_size; - ef_port_read(bak_cur_addr, buff, sizeof(buff)); - result = ef_port_write(bl_cur_addr, buff, sizeof(buff)); - if (result != EF_NO_ERR) { - break; - } - } - - switch (result) { - case EF_NO_ERR: { - EF_INFO("Write data to bootloader entry OK.\n"); - break; - } - case EF_WRITE_ERR: { - EF_INFO("Warning: Write data to bootloader entry fault!\n"); - break; - } - } - - return result; -} - -/** - * Get IAP section start address in flash. - * - * @return size - */ -uint32_t ef_get_bak_app_start_addr(void) { - return bak_app_start_addr; -} - -#endif /* EF_USING_IAP */ diff --git a/easyflash/src/ef_log.c b/easyflash/src/ef_log.c deleted file mode 100644 index 9d2b8c6..0000000 --- a/easyflash/src/ef_log.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2019, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Save logs to flash. - * Created on: 2015-06-04 - */ - -#include - -#ifdef EF_USING_LOG - -#if defined(EF_USING_LOG) && !defined(LOG_AREA_SIZE) -#error "Please configure log area size (in ef_cfg.h)" -#endif - -/* magic code on every sector header. 'EF' is 0xEF30EF30 */ -#define LOG_SECTOR_MAGIC 0xEF30EF30 -/* sector header size, includes the sector magic code and status magic code */ -#define LOG_SECTOR_HEADER_SIZE 12 -/* sector header word size,what is equivalent to the total number of sectors header index */ -#define LOG_SECTOR_HEADER_WORD_SIZE 3 - -/** - * Sector status magic code - * The sector status is 8B after LOG_SECTOR_MAGIC at every sector header. - * ============================================== - * | header(12B) | status | - * ---------------------------------------------- - * | 0xEF30EF30 0xFFFFFFFF 0xFFFFFFFF | empty | - * | 0xEF30EF30 0xFEFEFEFE 0xFFFFFFFF | using | - * | 0xEF30EF30 0xFEFEFEFE 0xFCFCFCFC | full | - * ============================================== - * - * State transition relationship: empty->using->full - * The FULL status will change to EMPTY after sector clean. - */ -#define SECTOR_STATUS_MAGIC_EMPUT 0xFFFFFFFF -#define SECTOR_STATUS_MAGIC_USING 0xFEFEFEFE -#define SECTOR_STATUS_MAGIC_FULL 0xFCFCFCFC - -typedef enum { - SECTOR_STATUS_EMPUT, - SECTOR_STATUS_USING, - SECTOR_STATUS_FULL, - SECTOR_STATUS_HEADER_ERROR, -} SectorStatus; - -typedef enum { - SECTOR_HEADER_MAGIC_INDEX, - SECTOR_HEADER_USING_INDEX, - SECTOR_HEADER_FULL_INDEX, -} SectorHeaderIndex; - -/* the stored logs start address and end address. It's like a ring buffer implemented on flash. */ -static uint32_t log_start_addr = 0, log_end_addr = 0; -/* saved log area address for flash */ -static uint32_t log_area_start_addr = 0; -/* initialize OK flag */ -static bool init_ok = false; - -static void find_start_and_end_addr(void); -static uint32_t get_next_flash_sec_addr(uint32_t cur_addr); - -/** - * The flash save log function initialize. - * - * @return result - */ -EfErrCode ef_log_init(void) { - EfErrCode result = EF_NO_ERR; - - EF_ASSERT(LOG_AREA_SIZE); - EF_ASSERT(EF_ERASE_MIN_SIZE); - /* the log area size must be an integral multiple of erase minimum size. */ - EF_ASSERT(LOG_AREA_SIZE % EF_ERASE_MIN_SIZE == 0); - /* the log area size must be more than twice of EF_ERASE_MIN_SIZE */ - EF_ASSERT(LOG_AREA_SIZE / EF_ERASE_MIN_SIZE >= 2); - -#ifdef EF_USING_ENV - log_area_start_addr = EF_START_ADDR + ENV_AREA_SIZE; -#else - log_area_start_addr = EF_START_ADDR; -#endif - - /* find the log store start address and end address */ - find_start_and_end_addr(); - /* initialize OK */ - init_ok = true; - - return result; -} - -/** - * Get flash sector current status. - * - * @param addr sector address, this function will auto calculate the sector header address by this address. - * - * @return the flash sector current status - */ -static SectorStatus get_sector_status(uint32_t addr) { - uint32_t header_buf[LOG_SECTOR_HEADER_WORD_SIZE] = {0}, header_addr = 0; - uint32_t sector_header_magic = 0; - uint32_t status_full_magic = 0, status_use_magic = 0; - - /* calculate the sector header address */ - header_addr = addr & (~(EF_ERASE_MIN_SIZE - 1)); - - if (ef_port_read(header_addr, header_buf, sizeof(header_buf)) == EF_NO_ERR) { - sector_header_magic = header_buf[SECTOR_HEADER_MAGIC_INDEX]; - status_use_magic = header_buf[SECTOR_HEADER_USING_INDEX]; - status_full_magic = header_buf[SECTOR_HEADER_FULL_INDEX]; - } else { - EF_DEBUG("Error: Read sector header data error.\n"); - return SECTOR_STATUS_HEADER_ERROR; - } - - /* compare header magic code */ - if(sector_header_magic == LOG_SECTOR_MAGIC){ - if((status_use_magic == SECTOR_STATUS_MAGIC_EMPUT) && (status_full_magic == SECTOR_STATUS_MAGIC_EMPUT)) { - return SECTOR_STATUS_EMPUT; - } else if((status_use_magic == SECTOR_STATUS_MAGIC_USING) && (status_full_magic == SECTOR_STATUS_MAGIC_EMPUT)) { - return SECTOR_STATUS_USING; - } else if((status_use_magic == SECTOR_STATUS_MAGIC_USING) && (status_full_magic == SECTOR_STATUS_MAGIC_FULL)) { - return SECTOR_STATUS_FULL; - } else { - return SECTOR_STATUS_HEADER_ERROR; - } - } else { - return SECTOR_STATUS_HEADER_ERROR; - } - -} - -/** - * Write flash sector current status. - * - * @param addr sector address, this function will auto calculate the sector header address by this address. - * @param status sector cur status - * - * @return result - */ -static EfErrCode write_sector_status(uint32_t addr, SectorStatus status) { - uint32_t header, header_addr = 0; - - /* calculate the sector header address */ - header_addr = addr & (~(EF_ERASE_MIN_SIZE - 1)); - - /* calculate the sector staus magic */ - switch (status) { - case SECTOR_STATUS_EMPUT: { - header = LOG_SECTOR_MAGIC; - return ef_port_write(header_addr, &header, sizeof(header)); - } - case SECTOR_STATUS_USING: { - header = SECTOR_STATUS_MAGIC_USING; - return ef_port_write(header_addr + sizeof(header), &header, sizeof(header)); - } - case SECTOR_STATUS_FULL: { - header = SECTOR_STATUS_MAGIC_FULL; - return ef_port_write(header_addr + sizeof(header) * 2, &header, sizeof(header)); - } - default: - return EF_WRITE_ERR; - } -} - -/** - * Find the current flash sector using end address by continuous 0xFF. - * - * @param addr sector address - * - * @return current flash sector using end address - */ -static uint32_t find_sec_using_end_addr(uint32_t addr) { -/* read section data buffer size */ -#define READ_BUF_SIZE 32 - - uint32_t sector_start = addr, data_start = addr, continue_ff = 0, read_buf_size = 0, i; - uint8_t buf[READ_BUF_SIZE]; - - EF_ASSERT(READ_BUF_SIZE % 4 == 0); - /* calculate the sector start and data start address */ - sector_start = addr & (~(EF_ERASE_MIN_SIZE - 1)); - data_start = sector_start + LOG_SECTOR_HEADER_SIZE; - - /* counts continuous 0xFF which is end of sector */ - while (data_start < sector_start + EF_ERASE_MIN_SIZE) { - if (data_start + READ_BUF_SIZE < sector_start + EF_ERASE_MIN_SIZE) { - read_buf_size = READ_BUF_SIZE; - } else { - read_buf_size = sector_start + EF_ERASE_MIN_SIZE - data_start; - } - ef_port_read(data_start, (uint32_t *)buf, read_buf_size); - for (i = 0; i < read_buf_size; i++) { - if (buf[i] == 0xFF) { - continue_ff++; - } else { - continue_ff = 0; - } - } - data_start += read_buf_size; - } - /* calculate current flash sector using end address */ - if (continue_ff >= EF_ERASE_MIN_SIZE - LOG_SECTOR_HEADER_SIZE) { - /* from 0 to sec_size all sector is 0xFF, so the sector is empty */ - return sector_start + LOG_SECTOR_HEADER_SIZE; - } else if (continue_ff >= 4) { - /* form end_addr - 4 to sec_size length all area is 0xFF, so it's used part of the sector. - * the address must be word alignment. */ - if (continue_ff % 4 != 0) { - continue_ff = (continue_ff / 4 + 1) * 4; - } - return sector_start + EF_ERASE_MIN_SIZE - continue_ff; - } else { - /* all sector not has continuous 0xFF, so the sector is full */ - return sector_start + EF_ERASE_MIN_SIZE; - } -} - -/** - * Find the log store start address and end address. - * It's like a ring buffer implemented on flash. - * The flash log area can be in two states depending on start address and end address: - * state 1 state 2 - * |============| |============| - * log area start--> |############| <-- start address |############| <-- end address - * |############| | empty | - * |------------| |------------| - * |############| |############| <-- start address - * |############| |############| - * |------------| |------------| - * | . | | . | - * | . | | . | - * | . | | . | - * |------------| |------------| - * |############| <-- end address |############| - * | empty | |############| - * log area end --> |============| |============| - * - * LOG_AREA_SIZE = log area end - log area star - * - */ -static void find_start_and_end_addr(void) { - size_t cur_size = 0; - SectorStatus cur_sec_status, last_sec_status; - uint32_t cur_using_sec_addr = 0; - /* all status sector counts */ - size_t empty_sec_counts = 0, using_sec_counts = 0, full_sector_counts = 0; - /* total sector number */ - size_t total_sec_num = LOG_AREA_SIZE / EF_ERASE_MIN_SIZE; - /* see comment of find_start_and_end_addr function */ - uint8_t cur_log_sec_state = 0; - - /* get the first sector status */ - cur_sec_status = get_sector_status(log_area_start_addr); - last_sec_status = cur_sec_status; - - for (cur_size = EF_ERASE_MIN_SIZE; cur_size < LOG_AREA_SIZE; cur_size += EF_ERASE_MIN_SIZE) { - /* get current sector status */ - cur_sec_status = get_sector_status(log_area_start_addr + cur_size); - /* compare last and current status */ - switch (last_sec_status) { - case SECTOR_STATUS_EMPUT: { - switch (cur_sec_status) { - case SECTOR_STATUS_EMPUT: - break; - case SECTOR_STATUS_USING: - EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); - ef_log_clean(); - return; - case SECTOR_STATUS_FULL: - EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); - ef_log_clean(); - return; - } - empty_sec_counts++; - break; - } - case SECTOR_STATUS_USING: { - switch (cur_sec_status) { - case SECTOR_STATUS_EMPUT: - /* like state 1 */ - cur_log_sec_state = 1; - log_start_addr = log_area_start_addr; - cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE; - break; - case SECTOR_STATUS_USING: - EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); - ef_log_clean(); - return; - case SECTOR_STATUS_FULL: - /* like state 2 */ - cur_log_sec_state = 2; - log_start_addr = log_area_start_addr + cur_size; - cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE; - break; - } - using_sec_counts++; - break; - } - case SECTOR_STATUS_FULL: { - switch (cur_sec_status) { - case SECTOR_STATUS_EMPUT: - /* like state 1 */ - if (cur_log_sec_state == 2) { - EF_DEBUG("Error: Log area error! Now will clean all log area.\n"); - ef_log_clean(); - return; - } else { - cur_log_sec_state = 1; - log_start_addr = log_area_start_addr; - log_end_addr = log_area_start_addr + cur_size; - cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE; - } - break; - case SECTOR_STATUS_USING: - if(total_sec_num <= 2) { - /* like state 1 */ - cur_log_sec_state = 1; - log_start_addr = log_area_start_addr; - cur_using_sec_addr = log_area_start_addr + cur_size; - } else { - /* like state 2 when the sector is the last one */ - if (cur_size + EF_ERASE_MIN_SIZE >= LOG_AREA_SIZE) { - cur_log_sec_state = 2; - log_start_addr = get_next_flash_sec_addr(log_area_start_addr + cur_size); - cur_using_sec_addr = log_area_start_addr + cur_size; - } - } - break; - case SECTOR_STATUS_FULL: - break; - } - full_sector_counts++; - break; - } - case SECTOR_STATUS_HEADER_ERROR: - EF_DEBUG("Error: Log sector header error! Now will clean all log area.\n"); - ef_log_clean(); - return; - } - last_sec_status = cur_sec_status; - } - - /* the last sector status counts */ - if (cur_sec_status == SECTOR_STATUS_EMPUT) { - empty_sec_counts++; - } else if (cur_sec_status == SECTOR_STATUS_USING) { - using_sec_counts++; - } else if (cur_sec_status == SECTOR_STATUS_FULL) { - full_sector_counts++; - } else if (cur_sec_status == SECTOR_STATUS_HEADER_ERROR) { - EF_DEBUG("Error: Log sector header error! Now will clean all log area.\n"); - ef_log_clean(); - return; - } - - if (using_sec_counts != 1) { - /* this state is almost impossible */ - EF_DEBUG("Error: There must be only one sector status is USING! Now will clean all log area.\n"); - ef_log_clean(); - } else { - /* find the end address */ - log_end_addr = find_sec_using_end_addr(cur_using_sec_addr); - } - -} - -/** - * Get log used flash total size. - * - * @return log used flash total size. @note NOT contain sector headers - */ -size_t ef_log_get_used_size(void) { - size_t header_total_num = 0, physical_size = 0; - /* must be call this function after initialize OK */ - if (!init_ok) { - return 0; - } - - if (log_start_addr < log_end_addr) { - physical_size = log_end_addr - log_start_addr; - } else { - physical_size = LOG_AREA_SIZE - (log_start_addr - log_end_addr); - } - - header_total_num = physical_size / EF_ERASE_MIN_SIZE + 1; - - return physical_size - header_total_num * LOG_SECTOR_HEADER_SIZE; -} - -/** - * Sequential reading log data. It will ignore sector headers. - * - * @param addr address - * @param log log buffer - * @param size log size, not contain sector headers. - * - * @return result - */ -static EfErrCode log_seq_read(uint32_t addr, uint32_t *log, size_t size) { - EfErrCode result = EF_NO_ERR; - size_t read_size = 0, read_size_temp = 0; - - while (size) { - /* move to sector data address */ - if ((addr + read_size) % EF_ERASE_MIN_SIZE == 0) { - addr += LOG_SECTOR_HEADER_SIZE; - } - /* calculate current sector last data size */ - read_size_temp = EF_ERASE_MIN_SIZE - (addr % EF_ERASE_MIN_SIZE); - if (size < read_size_temp) { - read_size_temp = size; - } - result = ef_port_read(addr + read_size, log + read_size / 4, read_size_temp); - if (result != EF_NO_ERR) { - return result; - } - read_size += read_size_temp; - size -= read_size_temp; - } - - return result; -} - -/** - * Calculate flash physical address by log index. - * - * @param index log index - * - * @return flash physical address - */ -static uint32_t log_index2addr(size_t index) { - size_t header_total_offset = 0; - /* total include sector number */ - size_t sector_num = index / (EF_ERASE_MIN_SIZE - LOG_SECTOR_HEADER_SIZE) + 1; - - header_total_offset = sector_num * LOG_SECTOR_HEADER_SIZE; - if (log_start_addr < log_end_addr) { - return log_start_addr + index + header_total_offset; - } else { - if (log_start_addr + index + header_total_offset < log_area_start_addr + LOG_AREA_SIZE) { - return log_start_addr + index + header_total_offset; - } else { - return log_start_addr + index + header_total_offset - LOG_AREA_SIZE; - - } - } -} - -/** - * Read log from flash. - * - * @param index index for saved log. - * Minimum index is 0. - * Maximum index is ef_log_get_used_size() - 1. - * @param log the log which will read from flash - * @param size read bytes size - * - * @return result - */ -EfErrCode ef_log_read(size_t index, uint32_t *log, size_t size) { - EfErrCode result = EF_NO_ERR; - size_t cur_using_size = ef_log_get_used_size(); - size_t read_size_temp = 0; - size_t header_total_num = 0; - - if (!size) { - return result; - } - - EF_ASSERT(size % 4 == 0); - EF_ASSERT(index < cur_using_size); - - if (index + size > cur_using_size) { - EF_DEBUG("Warning: Log read size out of bound. Cut read size.\n"); - size = cur_using_size - index; - } - /* must be call this function after initialize OK */ - if (!init_ok) { - return EF_ENV_INIT_FAILED; - } - - if (log_start_addr < log_end_addr) { - log_seq_read(log_index2addr(index), log, size); - } else { - if (log_index2addr(index) + size <= log_area_start_addr + LOG_AREA_SIZE) { - /* Flash log area - * |--------------| - * log_area_start_addr --> |##############| - * |##############| - * |##############| - * |--------------| - * |##############| - * |##############| - * |##############| <-- log_end_addr - * |--------------| - * log_start_addr --> |##############| - * read start --> |**************| <-- read end - * |##############| - * |--------------| - * - * read from (log_start_addr + log_index2addr(index)) to (log_start_addr + index + log_index2addr(index)) - */ - result = log_seq_read(log_index2addr(index), log, size); - } else if (log_index2addr(index) < log_area_start_addr + LOG_AREA_SIZE) { - /* Flash log area - * |--------------| - * log_area_start_addr --> |**************| <-- read end - * |##############| - * |##############| - * |--------------| - * |##############| - * |##############| - * |##############| <-- log_end_addr - * |--------------| - * log_start_addr --> |##############| - * read start --> |**************| - * |**************| - * |--------------| - * read will by 2 steps - * step1: read from (log_start_addr + log_index2addr(index)) to flash log area end address - * step2: read from flash log area start address to read size's end address - */ - read_size_temp = (log_area_start_addr + LOG_AREA_SIZE) - log_index2addr(index); - header_total_num = read_size_temp / EF_ERASE_MIN_SIZE; - /* Minus some ignored bytes */ - read_size_temp -= header_total_num * LOG_SECTOR_HEADER_SIZE; - result = log_seq_read(log_index2addr(index), log, read_size_temp); - if (result == EF_NO_ERR) { - result = log_seq_read(log_area_start_addr, log + read_size_temp / 4, size - read_size_temp); - } - } else { - /* Flash log area - * |--------------| - * log_area_start_addr --> |##############| - * read start --> |**************| - * |**************| <-- read end - * |--------------| - * |##############| - * |##############| - * |##############| <-- log_end_addr - * |--------------| - * log_start_addr --> |##############| - * |##############| - * |##############| - * |--------------| - * read from (log_start_addr + log_index2addr(index) - LOG_AREA_SIZE) to read size's end address - */ - result = log_seq_read(log_index2addr(index) - LOG_AREA_SIZE, log, size); - } - } - - return result; -} - -/** - * Write log to flash. - * - * @param log the log which will be write to flash - * @param size write bytes size - * - * @return result - */ -EfErrCode ef_log_write(const uint32_t *log, size_t size) { - EfErrCode result = EF_NO_ERR; - size_t write_size = 0, writable_size = 0; - uint32_t write_addr = log_end_addr, erase_addr; - SectorStatus sector_status; - - EF_ASSERT(size % 4 == 0); - /* must be call this function after initialize OK */ - if (!init_ok) { - return EF_ENV_INIT_FAILED; - } - - if ((sector_status = get_sector_status(write_addr)) == SECTOR_STATUS_HEADER_ERROR) { - return EF_WRITE_ERR; - } - /* write some log when current sector status is USING and EMPTY */ - if ((sector_status == SECTOR_STATUS_USING) || (sector_status == SECTOR_STATUS_EMPUT)) { - /* write the already erased but not used area */ - writable_size = EF_ERASE_MIN_SIZE - ((write_addr - log_area_start_addr) % EF_ERASE_MIN_SIZE); - if (size >= writable_size) { - result = ef_port_write(write_addr, log, writable_size); - if (result != EF_NO_ERR) { - goto exit; - } - /* change the current sector status to FULL */ - result = write_sector_status(write_addr, SECTOR_STATUS_FULL); - if (result != EF_NO_ERR) { - goto exit; - } - write_size += writable_size; - } else { - result = ef_port_write(write_addr, log, size); - log_end_addr = write_addr + size; - goto exit; - } - } - /* erase and write remain log */ - while (true) { - /* calculate next available sector address */ - erase_addr = write_addr = get_next_flash_sec_addr(write_addr - 4); - /* move the flash log start address to next available sector address */ - if (log_start_addr == erase_addr) { - log_start_addr = get_next_flash_sec_addr(log_start_addr); - } - /* erase sector */ - result = ef_port_erase(erase_addr, EF_ERASE_MIN_SIZE); - if (result != EF_NO_ERR) { - goto exit; - } - /* change the sector status to EMPTY and USING when write begin sector start address */ - result = write_sector_status(write_addr, SECTOR_STATUS_EMPUT); - result = write_sector_status(write_addr, SECTOR_STATUS_USING); - if (result == EF_NO_ERR) { - write_addr += LOG_SECTOR_HEADER_SIZE; - } else { - goto exit; - } - /* calculate current sector writable data size */ - writable_size = EF_ERASE_MIN_SIZE - LOG_SECTOR_HEADER_SIZE; - if (size - write_size >= writable_size) { - result = ef_port_write(write_addr, log + write_size / 4, writable_size); - if (result != EF_NO_ERR) { - goto exit; - } - /* change the current sector status to FULL */ - result = write_sector_status(write_addr, SECTOR_STATUS_FULL); - if (result != EF_NO_ERR) { - goto exit; - } - log_end_addr = write_addr + writable_size; - write_size += writable_size; - write_addr += writable_size; - } else { - result = ef_port_write(write_addr, log + write_size / 4, size - write_size); - if (result != EF_NO_ERR) { - goto exit; - } - log_end_addr = write_addr + (size - write_size); - break; - } - } - -exit: - return result; -} - -/** - * Get next flash sector address.The log total sector like ring buffer which implement by flash. - * - * @param cur_addr cur flash address - * - * @return next flash sector address - */ -static uint32_t get_next_flash_sec_addr(uint32_t cur_addr) { - size_t cur_sec_id = (cur_addr - log_area_start_addr) / EF_ERASE_MIN_SIZE; - size_t sec_total_num = LOG_AREA_SIZE / EF_ERASE_MIN_SIZE; - - if (cur_sec_id + 1 >= sec_total_num) { - /* return to ring head */ - return log_area_start_addr; - } else { - return log_area_start_addr + (cur_sec_id + 1) * EF_ERASE_MIN_SIZE; - } -} - -/** - * Clean all log which in flash. - * - * @return result - */ -EfErrCode ef_log_clean(void) { - EfErrCode result = EF_NO_ERR; - uint32_t write_addr = log_area_start_addr; - - /* clean address */ - log_start_addr = log_area_start_addr; - log_end_addr = log_start_addr + LOG_SECTOR_HEADER_SIZE; - /* erase log flash area */ - result = ef_port_erase(log_area_start_addr, LOG_AREA_SIZE); - if (result != EF_NO_ERR) { - goto exit; - } - /* setting first sector is EMPTY to USING */ - write_sector_status(write_addr, SECTOR_STATUS_EMPUT); - write_sector_status(write_addr, SECTOR_STATUS_USING); - if (result != EF_NO_ERR) { - goto exit; - } - write_addr += EF_ERASE_MIN_SIZE; - /* add sector header */ - while (true) { - write_sector_status(write_addr, SECTOR_STATUS_EMPUT); - if (result != EF_NO_ERR) { - goto exit; - } - write_addr += EF_ERASE_MIN_SIZE; - if (write_addr >= log_area_start_addr + LOG_AREA_SIZE) { - break; - } - } - -exit: - return result; -} - -#endif /* EF_USING_LOG */ diff --git a/easyflash/src/ef_utils.c b/easyflash/src/ef_utils.c deleted file mode 100644 index c6c9571..0000000 --- a/easyflash/src/ef_utils.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of the EasyFlash Library. - * - * Copyright (c) 2015-2017, Armink, - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * 'Software'), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Function: Some utils for this library. - * Created on: 2015-01-14 - */ - -#include - -static const uint32_t crc32_table[] = -{ - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d -}; - -/** - * Calculate the CRC32 value of a memory buffer. - * - * @param crc accumulated CRC32 value, must be 0 on first call - * @param buf buffer to calculate CRC32 value for - * @param size bytes in buffer - * - * @return calculated CRC32 value - */ -uint32_t ef_calc_crc32(uint32_t crc, const void *buf, size_t size) -{ - const uint8_t *p; - - p = (const uint8_t *)buf; - crc = crc ^ ~0U; - - while (size--) { - crc = crc32_table[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - } - - return crc ^ ~0U; -}