《嵌入式系统日志记录的简易方法.docx》由会员分享,可在线阅读,更多相关《嵌入式系统日志记录的简易方法.docx(36页珍藏版)》请在优知文库上搜索。
1、很多场景都需要记录日志,在战入式系统中,特别是雎片机这种存储资源有限的环境下,就需要一种轻Sc级的存储方法。系统日志在嵌入式设备应用场景中,系统日志时常可以监控设备软件的运行状态,及时记录问题点以及关键信息,方便开发人先后期定位以及解决问题.本文将讲述一种简易的系统日志记录方法,用下保存设备的系统日志,视具体嵌入式设备情况而定,可存储在MCU内部FIaSh、外部F1.aSh、EEPRoM等,本文采用外部F1.ash作为示例展开介绍“思路分析对于系统日志可以当成文件系统,可以划分为三个重要部分:目录区、参数区、日志区。目录区:根据日期进行归类,记录当天的日志的存储地址、日志索引、日志大小,通过目
2、录可以获取整个日志文件的概况;参数区:存储记录日志写位设、目录项个数、写状态等参数:日志区:这是我们主要的存储区,记录系统的日志,支持环写。这:个区域都需要占用部分内存,可以自行分配大小。实现的效果如卜图所示,设置通过指令可查询到整个日志目录区的概况。查询系统日志目录:AT+CATA1.0G?1.oGD:存储日志按日期分类,该ID用于查询对应日期日志,从1开始计数:1.OGDATE:系统日志存储日期:1.oG_ADDR:系统日志存储外部F1.ASH地址:1.0GFFSET:系统日志存储偏移垃(各日期日志大小,单位:字节).图片查询指定日期系统日志:AT+CATA1.OG=1.OGD:在查询系统
3、日志目录时获取,当1.oGD为0时,为查询推个系统日志。图片另外提供移除系统日志(消除日志目录)指令:AT+RM1.OG.后面将讲述具体实现。F1.ASH内存划分F1.ASH内存需要看具体设备进行合理划分,目录区、参数区与日志区实现环形存储,延长擦写寿命。defineF1._ASH_SECTOR_SIZE(uint32-t)0x001000)SdefineF1.ASH_B1.OCK_32K_SIZE(Uint32_t)OXOo8000)defineF1._ASH_B1.OCK_64K_SIZE(Uint32_t)OXo1.OoOO)WdefineSECTORMASK(F1.ASH_SECTOR
4、_SIZE-1)扇区掩码一7defineSECTOR_BASE(addr)扇区的基地址-*/WdefineSECTOR_OFFSET(addr)扇区内的偏移-*/defineB1.OCK_32K_BASE(addr)WdefineB1.OCK_64K_BASE(addr)typedefenumF1.ASH_B1.OCK_4K=0,F1.ASH_B1.OCK_32K=1,F1.ASH_B1.OCK_64K=2f1.ash_b1.ock_t;addr&(-SECTOR,MASK)(addr&SECTOR_MASK)(addr&(F1.ASH_B1.OCK_32K_SIZE)(addr&(F1.AS
5、H_B1.OCK_64K_SIZE)*f1.asheraseb1.ocksize4k/f1.asheraseb1.ocksize32k/*f1.asheraseb1.ocksize64k*/*f1.ash空间索引*/typedefenumF1.ASH_CATA1.OG_ZONE=0,F1.ASH_SYS1.OG_PARA_ZONE,F1.ASH_SYS1.OG_ZONE,F1.ASH_ZONEX,f1.ash_zone_e;tpedefstructf1.ash_zone_ezone;uint32_tstart-address;uint32_tend_address;f1.ash_tab1.e_
6、t;*地址划分7staticconstf1.ash_tab1.e_tf1.ash_tab1.e=.zone=F1.ASH_CATA1.OG_ZONE,.startaddress0x03200000,.end-address=OxO32FFFFF,.zone=F1.ASH_SYS1.OG_PARA_ZONE,.startaddress0x03300000,.end-address=OxO33FFFFF,.zone=F1.ASH_SYS1.OG_ZONE,.startaddress0x03400000,.end,address=OxO3FFFFFF),FIaSh底层实现擦除、读写操作接口,由读者自
7、行实现。f1.ash_tab1.e_tget_f1.ash_tab1.e(f1.ash_zone_ezone)inti=O;for(i0;if1.ash_ZOne_count;i+)if(zone=f1.ashjab1.e(i.zone)return(f1.ash_tab1.e_t*)&f1.ash_tab1.ei;)returnNU1.1.;)intf1.ash_erasef1.ash_zone_ezone,uint32-taddress,f1.ash_b1.ock_tb1.ock_type)(f1.ash_tab1.e_t*f1.ash_tab1.e_tmp=get_f1.ash_tab1
8、.e(zone);if(f1.ash_tab1.e_tmp=NU1.1.)return-1;if(addressstart_address11addressf1.ash_tab1.e_tmp-end_address)return-1;returnbsp_spi_f1.ash_eraseaddress,b1.ockjype);intf1.ash_write(f1.ash_zone_ezone,uint32-taddress,constuint8-t*data,uint32-t1.ength)(f1.ash_tab1.e_t*f1.ash_tab1.e_tmp=get_f1.ash_tab1.e(
9、zone);if(f1.ashIab1.e_tmp=NU1.1.)return-1;if(addressstart_address)!(address+1.ength)f1.ash_tab1.e_tmp-end_address)return-1;returnbsp_spi_f1.ash_buffer_writeaddress,(uint8_t*)data,1.ength);intf1.ash_read(f1.ash_zone_ezone,uint32-taddress,uint8j*buffer,uint32-t1.ength)(f1.ash_tab1.e_t*f1.ash_tab1.e_tm
10、p=get_f1.ash_tab1.e(zone);if(f1.ash_tab1.e_tmp=NU1.1.)return-1;if(addressstart_address)!(address+1.ength)f1.ash_tab1.e_tmp-end_address)return-1;bsp_spi_f1.a$h_buffer_read(buffer,address,1.ength);returnO;参数与结构体定义日志数据存储时间戳,便丁问题定位,需要实现RTC接口调用.typedefstructuint1.6-tYear;年份:YYYY/uint8-tMonth;*月份:MM*/uint
11、8tDay;*日:DDuint8-tHour;*小时:HH/uint8-tMinute;/分钟:MM/uint8-tSecond;/*杪:SS*/intbsp_rtc_get_timetime_t*date);参数区应当保证数据的正确性,应加入参数校眩存储,定义校验结构体。#defineSYSTEM_1.OG_MAGIC_PARAM0x87654321*日志参数标识符7typedefstructuint32jmagic;/*参数标识符/uint1.6_tcrc;/*校验值*/uint1.6jIen;/参数长度7sing1.e_sav_t;参数区需记录当前日志记录的写位置,以及目录项个数,还有日
12、志区和目录区环写状态,并且存储最新时间等等./*日志区参数*/tpedefstructuint32-tWrite_pos;写位置*/uint32jcata1.og_num;/目录项个数*/uint8_t1.og_cvc1.ic_status;/*系统日志环形写状态*/uint8_tCataIog_CydiJStatUs;/日志目录环形写状态*/time_t1.og_1.atest_time;/*存储最新时间*/system_1.og_t;/*目录区参数7typedefstructuint32j1.og_id;*日志索引/uint32_t1.og_addr;*日志地址*/uint32j1.og.
13、offset;*日志偏移大小,单位:字节/time_t1.og_time;/*日志存储时间*/system_cata1.og_t;/*系统日志参数*/typedefstructsing1.e_sav_tcrc_va1.;system_1.og_tsystemjog;system_cata1.og_tSYStem.cata1.og;sys_1.og_param_t;typedefstructuint8jsystem_1.og_print_enab1.e;系统日志打印使能/uint1.6_t$vstem_1.og_print_id;*打印指定id系统日志,/uint32jsystem_1.og_p
14、aram_addr;/当前日志写地址*/sys_ram_t;sys_ram_tSysRam;sys_1.og_param_tSys1.ogParam;sys_ram_tegp_sys_ram=SSysRam;sys_1.og_param_t*gp_sys_1.og=&Sys1.ogParam;实现接口说明CRC校验接口,可以自定义实现.16位CRC校监苗位表7staticconstUint8_tauchCRCHi11=0x00,0xc1.,0x81,0x40,0x01,0xc0,0x80,0x41,0x01,OxcO,0x80,0x41,0x00,0xc1.,0x81,0x40,0x01,0xc0,0x80,0x41,0x00,0xc1.,0x81,0x40,0x00,Oxc1.,0x81,0x40,0x01,OxcO,080,0x41f0x01,0xc0,0x80,0x41,0x00,0xc1.,0x81,0x40,0x00,0xc1.,0x81,0x40,0x01,0xc0,0x80,0x41f0x00,0xc1.,0x