/****************************************************************************** 版权所有: 文件名称: e2prom_emu.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2012-07-13 功能说明: e2prom仿真程序。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "bspconfig.h" #include "i2c.h" #include "ustimer.h" #include "gpio.h" #include "e2prom.h" #include "rt.h" /*------------------------------- 宏定义 -------------------------------------- */ #if CFG_BSP_DEBUG #define _DEBUG_E2PROM #endif /*------------------------------ 全局变量 ------------------------------------- */ int gf_e2prom; /*------------------------------ 函数声明 ------------------------------------- */ int e2prom_erase(uint32_t offset, uint32_t length); /*------------------------------ 外部函数 ------------------------------------- */ /****************************************************************************** 函数名称: e2prom_init 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-06 函数说明: e2prom初始化。 参数说明: 无 返回值: 成功返回0. 修改记录: */ int e2prom_init(void) { int len; // 创建并打开文件 gf_e2prom = rt_file_open("/app/data/e2prom.bin", O_CREAT | O_RDWR, 0); if (IS_ERR(gf_e2prom)) { printf("e2prom file open err!\r\n"); return -1; } // 检查文件长度是否正确 len = rt_file_getfile_size(gf_e2prom); if (len < 0) { rt_file_close(gf_e2prom, 0); gf_e2prom = -1; return -2; } if (len == CFG_E2PROM_SIZE) { return 0; } // 如果文件长度不为0,说明e2prom被破坏,不修改内容,直接错误返回, // 方便以后问题查找。 if (len != 0) { rt_file_close(gf_e2prom, 0); gf_e2prom = -1; return -3; } // 如果文件长度为0,初始化e2prom 文件 if (e2prom_erase(0, CFG_E2PROM_SIZE) != 0) { rt_file_close(gf_e2prom, 0); gf_e2prom = -1; return -4; } return 0; } int e2prom_reinit(void) { if (gf_e2prom < 0) // 定值文件未打开 { // 创建并打开文件 gf_e2prom = rt_file_open("/app/data/e2prom.bin", O_CREAT | O_RDWR, 0); if (IS_ERR(gf_e2prom)) { return -1; } rt_err_clr(ERR_CODE_INIT_E2PROM, 0); } e2prom_erase(0, CFG_E2PROM_SIZE); return 0; } int e2prom_exit(void) { if (gf_e2prom >= 0) { rt_file_close(gf_e2prom, 0); gf_e2prom = -1; } return 0; } /****************************************************************************** 函数名称: e2prom_read 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-06 函数说明: 从E2PROM中读出数据。 参数说明: offset(in):需要读的数据在E2PROM中的偏移量,和length之和不能大于 CFG_E2PROM_SIZE. buffer(out):读出数据的buffer。 length(in): 需要读出数据的长度,和offset之和不能大于CFG_E2PROM_SIZE。 返回值: 成功返回0. 修改记录: */ int e2prom_read(uint32_t offset, unsigned char *buffer, uint32_t length) { off_t pos; int ret; if (gf_e2prom < 0) { return -1; } // 检查参数 if (buffer == 0 || (offset + length) > CFG_E2PROM_SIZE) { return -1; } if (length == 0) { return 0; } pos = offset; ret = rt_file_read(gf_e2prom, buffer, length, &pos); if (ret != (int)length) { return -2; } return 0; } /****************************************************************************** 函数名称: e2prom_write 函数版本: 01.01 创建作者: sunxi 创建日期: 2008-08-06 函数说明: 将数据写入E2PROM中。注意:E2PROM按页写的速度比按字节写的速度快, 所以如果应用程序将要写入的数据组织成 参数说明: offset(in):需要写入的数据在E2PROM中的偏移量,和length之和不能大于 CFG_E2PROM_SIZE. buffer(in):写入数据的buffer。 length(in): 需要写入数据的长度,和offset之和不能大于CFG_E2PROM_SIZE。 返回值: 成功返回0. 修改记录: */ int e2prom_write(uint32_t offset, unsigned char *buffer, uint32_t length) { off_t pos; int ret; if (gf_e2prom < 0) { return -1; } // 检查参数 if (buffer == 0 || (offset + length) > CFG_E2PROM_SIZE) { return -1; } if (length == 0) { return 0; } pos = offset; ret = rt_file_write(gf_e2prom, buffer, length, &pos); if (ret != (int)length) { return -2; } return 0; } int e2prom_erase(uint32_t offset, uint32_t length) { unsigned char *buf; off_t off; size_t len; int ret; if (gf_e2prom < 0) { return -1; } buf = rt_malloc(CFG_E2PROM_SIZE); if (buf == NULL) { return -2; } memset(buf, -1, CFG_E2PROM_SIZE); off = offset; while (length) { len = length > CFG_E2PROM_SIZE ? CFG_E2PROM_SIZE : length; length -= len; ret = rt_file_write(gf_e2prom, buf, len, &off); if (ret != (int)len) { rt_free(buf); return -3; } } rt_free(buf); return 0; } /*------------------------------ 内部函数 ------------------------------------- */ /*------------------------------ 测试函数 ------------------------------------- */ #ifdef _DEBUG_E2PROM #include "rt.h" #define E2PROM_TEST_SIZE 1044 // 必须是偶数 int e2prom_test(void) { int ret; unsigned long us0, us; unsigned long i, offset, length; static unsigned short buffer[E2PROM_TEST_SIZE / 2]; rt_printf("e2prom_test start...\r\n"); offset = 0; while (offset < CFG_E2PROM_SIZE) { // 写 length = (CFG_E2PROM_SIZE - offset) > E2PROM_TEST_SIZE ? E2PROM_TEST_SIZE : (CFG_E2PROM_SIZE - offset); for (i = 0; i < length / 2; i++) { buffer[i] = (unsigned short)(offset + i + 0x5555); } us0 = ustimer_get_origin(); ret = e2prom_write(offset, (unsigned char *)buffer, length); us = ustimer_get_duration(us0); rt_printf("e2prom_write:(offset=%lu,ret=%d,us=%lu)\r\n", offset, ret, us); if (ret != 0) { break; } offset += length; } offset = 0; while (offset < CFG_E2PROM_SIZE) { // 读 length = (CFG_E2PROM_SIZE - offset) > E2PROM_TEST_SIZE ? E2PROM_TEST_SIZE : (CFG_E2PROM_SIZE - offset); memset(buffer, 0, E2PROM_TEST_SIZE); us0 = ustimer_get_origin(); ret = e2prom_read(offset, (unsigned char *)buffer, length); us = ustimer_get_duration(us0); rt_printf("e2prom_read:(offset=%lu,ret=%d,us=%lu)\r\n", offset, ret, us); if (ret != 0) { break; } // 比较 for (i = 0; i < length / 2; i++) { if (buffer[i] != (unsigned short)(offset + i + 0x5555)) { break; } } if (i == length / 2) { rt_printf("compare ok(offset=%lu,i=%lu)!\r\n", offset, i); } else { rt_printf("compare error(offset=%lu,i=%lu)!\r\n", offset, i); break; } offset += length; } if (offset == CFG_E2PROM_SIZE) { rt_printf("e2prom_test ok!\r\n\n"); } else { rt_printf("e2prom_test fail!\r\n\n"); } return 0; } #endif /*------------------------------ 文件结束 ------------------------------------- */