DrvBsp_EEPROM文件化管理设计(一)

这次是我本人首次借助AI辅助开发,有较为深刻的使用体会。相较于自主手写代码,初期利用AI编程的工作效率更低,其核心原因在于个人多年编程的习惯与AI辅助开发模式存在一个适配的过程。

一般的嵌入式软件工程师通常采用边设计、边编码、边调整的迭代开发模式,没有完整的需求规范,依托经验完成开发。但AI辅助开发对需求描述的完整性、准确性要求极高,需要提前将架构思路、代码风格、逻辑规则、参数定义等内容清晰、完整地梳理输出,对需求描述的精细化程度有着严格要求。

本人编程还是有一定个人风格,通用AI难以精准匹配个人长期形成的编码风格,想要让AI完全贴合自身开发习惯,存在很大难度。

但不可否认的是,AI辅助编程具备显著优势,生成的代码格式统一、逻辑规范、可读性强,能够规避个人手写代码中不规范、随意性强的问题,有效提升代码的标准化程度与工程质量。

总体而言,若对代码风格、逻辑细节无特殊要求,AI可快速生成规范的程序代码(可用则未必),开发效率极高。但如果对代码编码风格、逻辑细节等有较高定制要求,就需要长期磨合适配,并非短期可以熟练掌握。

0 前言

在嵌入式设备开发中,EEPROM是最常用的用以存储参数、日志的器件。方便起见,开发人员多采用裸地址读写数据。由于裸地址读写方式规范性较弱,极易存在结构混乱、边界无管控、参数无备份校验等诸多问题。因此借用规范的文件管理机制对EEPROM的操作实施管理存在一定的必要性。

在嵌入式设备开发中,EEPROM主要用于存储两类核心数据:参数与日志。

由于参数对可靠性和稳定性要求较高,因此参数存储必须具备校验与备份策略,通常要为参数增加校验和,用于判断参数是否有效。当主参数区校验和异常时,系统应能自动加载备用参数区。

日志数据则以记录时序性数据为核心特征,主要用于记录设备运行状态、故障波形等信息。由于日志数据不允许修改历史内容,因此在存储方式上普遍采用追加写入模式,保证数据按产生顺序不断累积;同时,日志必须携带时间戳或序列号,用于标识记录的先后顺序,支持按时间点、按时间范围进行高效查询,满足设备历史追溯、故障分析、数据回放等业务需求。

1 方案特点以及存储分配说明

结合嵌入式系统资源有限的特点,本方案采用空间连续预分配策略,不考虑碎片机制。该方案逻辑简单、资源占用少,适应资源受限的嵌入式设备。

同时,文件信息表采用顺序存储结构,能保证文件的检索效率。系统还增设数据校验机制,可及时检测数据损坏,进一步提升存储方案的整体可靠性。

EEPROM的地址空间分配如下:

|---|---|----------------------------|
| 0x0000-0x00FF: || 文件系统头 (ST_EFILE_HEADER) |
| 0x0100-0x03FF: || 文件信息表 (最多8个 ST_EFILE_INFO) |
| | 文件0信息 ||
| | ...... ||
| | 文件7信息 ||
| 0x0400-...: || 数据区 |
| | 文件0 ||
| | ...... ||
| | 文件7 ||
| | | |

如上所示,EEPROM的地址空间分为三大部分:其一文件系统头作为整个文件系统的基础信息区,用于判断文件系统是否有效;其二文件信息表作为文件系统的目录与索引区,记录所有已创建文件的基础信息,用户通过检索该表快速定位文件位置;其三数据区作为文件系统的实际内容存储区,用于存放文件的真实数据。

2 文件信息表设计说明

文件信息表是EEPROM文件化管理系统的核心索引载体,承担着存储分区统一管理、文件属性记录、数据合格校验等核心作用。所有EEPROM存储文件均通过该表格统一注册,以替代裸地址读写模式,能有效规范EEPROM的操作管理。

结合参数、日志两类数据类型,文件信息表至少应包括基础属性、参数文件专属属性、日志文件专属属性三大类内容:

2.1 通用基础字段

  1. 文件类型:区分文件属性,标注为参数文件或日志文件
  2. 起始地址:记录文件在EEPROM物理存储中的起始偏移地址。
  3. 文件大小:记录所提供该文件的最大存储空间,用于地址越界检测、防止数据交叉覆盖。

2.2 参数专属字段

  1. 参数校验码:对整段参数进行运算生成校验和,用于确认该参数区是否有效。
  2. 主、备参数区起始地址以及单个参数区的存储空间尺寸;

2.3 日志专属字段

  1. 单条日志尺寸:定义单条日志数据的存储空间大小。
  2. 日志条目数量:定义本日志文件最多能存储的条目数
  3. 当前写入索引:记录最新日志的写入位置,实现断电续写、增量追加写入等操作;
  4. 有效条目数量:记录当前日志文件中已正常写入、可正常查询读取的日志条目数。

3 操作接口设计说明

借鉴文件系统的操作接口,EEPROM文件操作接口至少应该包括:

  1. 通用基础接口:文件打开功能,针对不同存储类型差异化设计业务接口。
  2. 参数类文件接口:提供文件读取、数据写入接口,满足配置参数的调取与更新。
  3. 日志类文件接口:支持数据追加写入,提供时间区间检索、时间起点定长序列检索两种方式。

对于日志类文件的检索机制,由于嵌入式系统内存受限,无法一次性返回大批量的数据。系统会采用游标机制管理检索进度。所谓游标机制即是将查询操作与数据读取动作相互拆分,先通过条件检索锁定目标数据范围,生成查询游标。再依托游标逐条分布读取日志条目。该方式无需一次性加载全部查询结果,可规避系统对大容量内存的要求。

4 文件系统初始化

cpp 复制代码
typedef struct  _ ST_EFILE _HEADER {
	unsigned long	 ulMagic;
    unsigned long   ulVersion;    
    unsigned long	 ulSum;			
} ST_EFILE _HEADER;
ST_EFILE _HEADER	m_stEFileheader;

void eFile_Init(STDRVB_E2P_MAP stE2PMap)
{    
    DrvB_E2P_Map(stE2PMap);
    
    if (eFile_ReadHeader() != true)  { 
        eFile_Format(); 
        return; 
    }
    if (m_stEFileheader.ulMagic != EEP_FILE_MAGIC) { 
        eFile_Format(); 
        return; 
    }
    if (eFile_GetEFileHeaderChkSum(&m_stEFileheader) != m_stEFileheader.ulSum) {
        eFile_Format(); 
        return;
    }
}

文件系统初始化是启动运行的首要步骤,主要包含两项核心任务:

其一是完成物理层的绑定,指定本文件系统所依附的EEPROM操作接口;

其二是执行文件系统合法性检测,通过读取EEPROM预定区域的检验魔数、校验文件系统基础信息表(ST_EFILE _HEADER)有效性等,判断芯片内是否已经存在合法有效的文件系统。如未能检测到有效文件系统,则需将其格式化。

所谓格式化,将其内容全部清成FFH后,将文件系统基础信息表初始化后写入EEPROM。

5 文件打开

文件打开操作的核心是检索文件信息表,匹配目标文件名。若查询到对应文件且配置相符则直接返回成功,反之返回失败。

5.1 文件信息表

文件信息表紧接于文件系统基础信息表之后,最多可存8个文件,文件信息表格式如下:

cpp 复制代码
typedef struct {
    unsigned char   ucName[EEP_FILE_MAX_NAME_LEN];      /* 文件名 */
    unsigned long   ulStartAddr;                        /* 文件起始地址 */
    unsigned short  usId;                              /* 在文件信息表中的序号 */
    unsigned long   ulSize;                            /* 文件总大小(字节) */
    
    EN_EFILE_TYPE   enType;                      /* 文件类型:参数/日志 */    
    union {
        struct {
            unsigned long   ulBackupAddr;             /* 备份区起始地址(参数文件) */
            unsigned char   ucParamChecksum;          /* 参数校验和 */
        } stPara;
        struct {
            unsigned long   ulItemSize;                /* 单条日志大小 */
            unsigned long   ulItemCount;               /* 日志条目总数 */
            unsigned long   ulNxtWrItem;              /* 下一写入条目 */
            unsigned long   ulAvailItem;               /* 有效条目数量 */          
        } stLog;
    } u;
    
    unsigned char   ucChecksum;                       /* 文件信息校验和 */
}ST_EFILE_INFO;

5.2 文件打开流程

文件句柄是应用程序与存储文件之间的操作索引,用于关联、定位、管理指定文件的全部信息。它的作用是让上层操作无需关心底层物理地址,只需通过句柄即可实现安全读写,系统也可通过句柄快速定位,从而实现地址管理、越界保护等。

在本设计中,直接将文件信息作为文件句柄使用。文件打开流程,即是创建文件句柄的过程:

  1. 当根据文件名在文件信息表内查找有没有对应的文件,有则获取stInfo,并将ulCurrentAddr、ulCurrentItem清0,返回RET_SUCCESS;
  2. 无则返回RET_ERROR;
cpp 复制代码
_Bool eFile_Open(const char *pucName , ST_EFILE_INFO *pstInfo)
{   
    unsigned long ulAddr;
    if (eFile_FindFile(pucName, &ulAddr) != RET_SUCCESS) 	
    { //搜索文件信息表
        return RET_ERROR;
    }
    if (eFile_ReadFileInfo(ulAddr, pstInfo) != RET_SUCCESS) 
    { //读取文件信息
        return RET_ERROR;
    }
    //文件大小合法性判断
    if (pstInfo->ulStartAddr + pstInfo->ulSize > DrvB_E2P_GetSize()) 
        return RET_ERROR;
    return RET_SUCCESS;
}
相关推荐
故渊at8 小时前
第七板块:Android 存储体系与文件系统 | 第二十一篇:Vold 与 FUSE 存储架构
android·架构·文件系统·fuse·vold·存储体系
艾莉丝努力练剑13 天前
【Linux:文件】Ext系列文件系统进阶
linux·运维·服务器·c++·文件系统·文件io·ext
atomicmaker13 天前
操作系统 — 文件管理
操作系统·文件管理·文件系统·计算机系统
j7~21 天前
【Linux操作系统】基础IO文件系统(理解硬件,理解文件系统,Inode,软硬链接)
linux·运维·服务器·磁盘·文件系统·inode·软硬件链接
sulikey25 天前
Linux ext2文件系统结构
linux·操作系统·文件系统·linux文件系统·ext2·ext2文件系统
sulikey25 天前
ext2 GDT 块组描述符表 详细技术拆解
linux·操作系统·文件系统·ext2·gdt·ext·块组描述符
xcLeigh1 个月前
KES大小写混合路径+国产OS/文件系统兼容实战
linux·数据库·文件系统·兼容性·麒麟·欧拉·kes
程序员老舅1 个月前
Linux:谁把根目录卸载了?
linux·c++·容器·linux内核·文件系统·根目录
IT大白鼠1 个月前
主流Linux文件系统稳定性及性能分析
linux·运维·服务器·文件系统