单片机日志系统架构
说明: 日志记录系统按照API封装的思想只在接口文件中保留功能性程序,及 init ,set ,get;存储器使用华邦的w25q64,最低擦除的为1个sector(4096Bytes);日志系统主要分为三个部分 1、日志索引 ,2、断电日志存储区,3、日志存储区
1、日志索引:
为了避免对单个地址持续擦写造成块损坏,日志索引使用两个sector作为日志的索引存储区,日志索引每写一次地址增加16字节。当开机初始化的时候按照一定的方法将最新的索引页读取出来,用于对日志记录的地址进行记录。
2、断电日志
为了能够记录断电瞬间设备的运行情况,需要存储数据到断电日志区,等待下次开机后将断电日志记录到日志中。然后将断电日志区的数据擦除。
3、日志存储区
目前设计的是4096条日志数据,每条日志占用空间为64Bytes,考虑到增加器件寿命,每次写sector到的起始地址时将该sector擦除,然后将日志总长度减 64.
代码实现
mod_logSysInfo.h
#ifndef _MOD_LOGSYSINFO_H_
#define _MOD_LOGSYSINFO_H_
#ifdef _cplusplus
extern "C" {
#endif
#include
#include
#include
#define LOG_INDEX_TOTAL (uint32_t)(15)
#define EACH_INDEX_SPACE (uint32_t)(16)
#define LOG_CONTENT_TOTAL (uint32_t)(52)
#define EACH_LOG_SPACE (uint32_t)(64)
#define LOG_INFO_TOTAL_CNT (uint32_t)(4096)
#define LOG_WRITE_FLAG (uint8_t)(0xA5)
typedef enum {
LOG_NOT_USE = 0,
LOG_BE_WRITE = 1,
LOG_BE_READ = 2
}LOG_OPERATE_STATE_ENUM;
typedef enum{
LOG_PROC_SUCCEED = 0,
LOG_PROC_FAILED = 1
}LOG_PROC_STATE_ENUM;
typedef struct{
uint8_t dateArry[LOG_CONTENT_TOTAL];
uint32_t curNum;
uint32_t curTime;
uint16_t length;
uint8_t verifyVal;
uint8_t writeFlag;
}LOG_CONTENT_STRUCT;
typedef union{
LOG_CONTENT_STRUCT ContentStruct;
uint8_t ConentArry[EACH_LOG_SPACE];
}LOG_CONTENT_UNION;
typedef struct{
uint32_t curIndex;
uint32_t cntTotal;
uint32_t rawTotal;
uint8_t useless[3];
uint8_t writeFlag;
}LOG_INDEX_STRUCT;
typedef union{
LOG_INDEX_STRUCT IndexStruct;
uint8_t IndexArry[LOG_INDEX_TOTAL+1];
}LOG_INDEX_UNION;
typedef struct
{
LOG_PROC_STATE_ENUM (*init)(void);
LOG_PROC_STATE_ENUM (*record)(LOG_CONTENT_UNION uLogInfoUnion);
LOG_PROC_STATE_ENUM (*getRecent)(LOG_CONTENT_UNION* pLogInfoUnion, int32_t recentNum);
LOG_PROC_STATE_ENUM (*getSerial)(LOG_CONTENT_UNION* pLogInfoUnion, int32_t serialNum);
}LOG_SYS_CONTENT_STRUCT;
typedef struct
{
LOG_PROC_STATE_ENUM (*clr)(void);
LOG_PROC_STATE_ENUM (*set)(LOG_CONTENT_UNION uLogInfoUnion);
LOG_PROC_STATE_ENUM (*get)(LOG_CONTENT_UNION* pLogInfoUnion);
}LOG_SYS_OUTAGE_STRUCT;
typedef struct
{
LOG_OPERATE_STATE_ENUM LogOperateFlag;
LOG_SYS_OUTAGE_STRUCT OutageStruct;
LOG_SYS_CONTENT_STRUCT ContentStruct;
LOG_PROC_STATE_ENUM (*init)(void);
uint32_t (*getRawTotal)(void);
}LOG_SYS_INFO_STRUCT;
extern LOG_SYS_INFO_STRUCT LogSysInfoStruct;
#ifdef _cplusplus
}
#endif
#endif
mod_logSysInfo.c
#include "mod_logSysInfo.h"
#include "hardware.h"
#define CHIPSET_PAGE (uint32_t)256
#define CHIPSET_SECTOR_SIZE (uint32_t)(CHIPSET_PAGE * 16)
#define CHIPSET_BLOCK_SIZE (uint32_t)(CHIPSET_SECTOR_SIZE * 16)
#define CHIPSET_TOTAL_SIZE (uint32_t)(CHIPSET_BLOCK_SIZE * 128)
#define LOG_SYS_OUTAGE_ADDRESS (uint32_t)(CHIPSET_SECTOR_SIZE * 13)
#define LOG_SYS_INDEX_ADDRESS (uint32_t)(CHIPSET_SECTOR_SIZE * 14)
#define LOG_SYS_INFO_ADDRESS (uint32_t)(CHIPSET_SECTOR_SIZE * 16)
#define LOG_SYS_INFO_TOAL_SIZE (uint32_t)(LOG_INFO_TOTAL_CNT * EACH_LOG_SPACE)
#define LOG_SYS_INDEX_TOAL_SIZE (uint32_t)(CHIPSET_SECTOR_SIZE * 2)
#define LOG_SYS_WRITE W25qxx_writeBuffer
#define LOG_SYS_READ W25qxx_readBuffer
#define LOG_SYS_ERASE W25qxx_eraseOneSector
#define LOG_INDEX_ADDR sLogIndexAddr
static LOG_PROC_STATE_ENUM LogSysInfo_initInfo(void);
static LOG_PROC_STATE_ENUM LogSysInfo_recordInfo(LOG_CONTENT_UNION uLogContentUnion);
static LOG_PROC_STATE_ENUM LogSysInfo_getRecentInfo(LOG_CONTENT_UNION* pLogContentUnion, int32_t recentNum);
static LOG_PROC_STATE_ENUM LogSysInfo_getSerialInfo(LOG_CONTENT_UNION* pLogContentUnion, int32_t serialNum);
static LOG_PROC_STATE_ENUM LogSysInfo_initIndex(void);
static LOG_PROC_STATE_ENUM LogSysInfo_setIndex(LOG_INDEX_UNION uLogIndexUnion);
static LOG_PROC_STATE_ENUM LogSysInfo_getIndex(LOG_INDEX_UNION* pLogIndexUnion);
static LOG_PROC_STATE_ENUM LogSysInfo_clrOutage(void);
static LOG_PROC_STATE_ENUM LogSysInfo_setOutage(LOG_CONTENT_UNION uLogContentUnion);
static LOG_PROC_STATE_ENUM LogSysInfo_getOutage(LOG_CONTENT_UNION* pLogContentUnion);
static LOG_PROC_STATE_ENUM LogSysInfo_init(void);
static uint32_t LogSysInfo_getRawTotal(void);
static uint8_t LogSysInfo_calcXor8(uint8_t *pVarArry, uint8_t len);
const LOG_INDEX_UNION cDefaultLogIndexUnion = {
.IndexStruct.curIndex = (LOG_SYS_INFO_ADDRESS - EACH_LOG_SPACE),
.IndexStruct.cntTotal = 0,
.IndexStruct.rawTotal = 0,
.IndexStruct.writeFlag = LOG_WRITE_FLAG,
};
LOG_INDEX_UNION sLogIndexUnion;
uint32_t sLogIndexAddr;
LOG_SYS_INFO_STRUCT LogSysInfoStruct = {
.ContentStruct.init = LogSysInfo_initInfo,
.ContentStruct.record = LogSysInfo_recordInfo,
.ContentStruct.getRecent = LogSysInfo_getRecentInfo,
.ContentStruct.getSerial = LogSysInfo_getSerialInfo,
.OutageStruct.clr = LogSysInfo_clrOutage,
.OutageStruct.set = LogSysInfo_setOutage,
.OutageStruct.get = LogSysInfo_getOutage,
.init = LogSysInfo_init,
.getRawTotal = LogSysInfo_getRawTotal,
};
LOG_PROC_STATE_ENUM LogSysInfo_init(void)
{
if(LOG_PROC_FAILED == LogSysInfo_initIndex())
return LOG_PROC_FAILED;
else
return LOG_PROC_SUCCEED;
}
uint32_t LogSysInfo_getRawTotal(void)
{
return sLogIndexUnion.IndexStruct.rawTotal;
}
LOG_PROC_STATE_ENUM LogSysInfo_initIndex(void)
{
LOG_PROC_STATE_ENUM rState;
LOG_INDEX_UNION tLogIndexUnion;
int32_t i_reord = -1;
for(int32_t i = 0; i < 256; i++){
LOG_SYS_READ(tLogIndexUnion.IndexArry,LOG_SYS_INDEX_ADDRESS+(i*EACH_INDEX_SPACE),sizeof(LOG_INDEX_UNION));
if(tLogIndexUnion.IndexArry[LOG_INDEX_TOTAL] == LOG_WRITE_FLAG){
i_reord = i;
}else{
break;
}
}
if((i_reord != 255)&&(i_reord != -1)){
LOG_INDEX_ADDR = LOG_SYS_INDEX_ADDRESS + (i_reord * EACH_INDEX_SPACE);
LOG_SYS_READ(tLogIndexUnion.IndexArry,LOG_INDEX_ADDR,sizeof(LOG_INDEX_UNION));
memcpy(sLogIndexUnion.IndexArry,tLogIndexUnion.IndexArry,sizeof(LOG_INDEX_UNION));
LOG_SYS_ERASE(LOG_SYS_INDEX_ADDRESS + CHIPSET_SECTOR_SIZE);
return LOG_PROC_SUCCEED;
}
for(int32_t i = 256; i < 512; i++){
LOG_SYS_READ(tLogIndexUnion.IndexArry,LOG_SYS_INDEX_ADDRESS+(i*EACH_INDEX_SPACE),sizeof(LOG_INDEX_UNION));
if(tLogIndexUnion.IndexArry[LOG_INDEX_TOTAL] == LOG_WRITE_FLAG){
i_reord = i;
}else{
break;
}
}
if((i_reord != 511)&&(i_reord != -1)){
LOG_INDEX_ADDR = LOG_SYS_INDEX_ADDRESS + (i_reord * EACH_INDEX_SPACE);
LOG_SYS_READ(tLogIndexUnion.IndexArry,LOG_INDEX_ADDR,sizeof(LOG_INDEX_UNION));
memcpy(sLogIndexUnion.IndexArry,tLogIndexUnion.IndexArry,sizeof(LOG_INDEX_UNION));
LOG_SYS_ERASE(LOG_SYS_INDEX_ADDRESS);
return LOG_PROC_SUCCEED;
}
if(i_reord == -1){
LOG_SYS_WRITE((uint8_t*)cDefaultLogIndexUnion.IndexArry,LOG_SYS_INDEX_ADDRESS,sizeof(LOG_INDEX_UNION));
rState = LogSysInfo_getIndex(&tLogIndexUnion);
if(rState == LOG_PROC_FAILED){
return LOG_PROC_FAILED;
}else{
memcpy(sLogIndexUnion.IndexArry,tLogIndexUnion.IndexArry,sizeof(LOG_INDEX_UNION));
return LOG_PROC_SUCCEED;
}
}
LOG_INDEX_ADDR = LOG_SYS_INDEX_ADDRESS + (511 * EACH_INDEX_SPACE);
memcpy(sLogIndexUnion.IndexArry,tLogIndexUnion.IndexArry,sizeof(LOG_INDEX_UNION));
LOG_SYS_ERASE(LOG_SYS_INDEX_ADDRESS);
return LOG_PROC_SUCCEED;
}
LOG_PROC_STATE_ENUM LogSysInfo_setIndex(LOG_INDEX_UNION uLogIndexUnion)
{
LOG_INDEX_ADDR = LOG_INDEX_ADDR + EACH_INDEX_SPACE;
if(LOG_INDEX_ADDR >= (LOG_SYS_INDEX_ADDRESS + LOG_SYS_INDEX_TOAL_SIZE)){
LOG_INDEX_ADDR = LOG_SYS_INDEX_ADDRESS;
LOG_SYS_ERASE(LOG_SYS_INDEX_ADDRESS);
LOG_SYS_WRITE(uLogIndexUnion.IndexArry,LOG_INDEX_ADDR,sizeof(LOG_INDEX_UNION));
}else{
LOG_SYS_WRITE(uLogIndexUnion.IndexArry,LOG_INDEX_ADDR,sizeof(LOG_INDEX_UNION));
}
return LOG_PROC_SUCCEED;
}
LOG_PROC_STATE_ENUM LogSysInfo_getIndex(LOG_INDEX_UNION* pLogIndexUnion)
{
LOG_SYS_READ(pLogIndexUnion->IndexArry,LOG_INDEX_ADDR,sizeof(LOG_INDEX_UNION));
if(pLogIndexUnion->IndexArry[LOG_INDEX_TOTAL] != LOG_WRITE_FLAG){
return LOG_PROC_FAILED;
}else{
return LOG_PROC_SUCCEED;
}
}
LOG_PROC_STATE_ENUM LogSysInfo_initInfo(void)
{
LOG_INDEX_UNION tLogIndexUnion;
LOG_CONTENT_UNION tLogOutageUnion;
LogSysInfo_getIndex(&tLogIndexUnion);
LogSysInfo_getOutage(&tLogOutageUnion);
if(tLogOutageUnion.ContentStruct.writeFlag == LOG_WRITE_FLAG){
LogSysInfo_recordInfo(tLogOutageUnion);
}else{
}
LogSysInfo_clrOutage();
return LOG_PROC_SUCCEED;
}
LOG_PROC_STATE_ENUM LogSysInfo_recordInfo(LOG_CONTENT_UNION uLogContentUnion)
{
sLogIndexUnion.IndexStruct.cntTotal += 1;
sLogIndexUnion.IndexStruct.rawTotal = (sLogIndexUnion.IndexStruct.cntTotal >= LOG_INFO_TOTAL_CNT) ?
LOG_INFO_TOTAL_CNT : sLogIndexUnion.IndexStruct.cntTotal;
sLogIndexUnion.IndexStruct.curIndex = (sLogIndexUnion.IndexStruct.cntTotal - 1)%
LOG_INFO_TOTAL_CNT * EACH_LOG_SPACE + LOG_SYS_INFO_ADDRESS;
if(sLogIndexUnion.IndexStruct.curIndex >= (LOG_SYS_INFO_TOAL_SIZE + LOG_SYS_INFO_ADDRESS))
sLogIndexUnion.IndexStruct.curIndex = LOG_SYS_INFO_ADDRESS;
if(0 == (sLogIndexUnion.IndexStruct.curIndex % CHIPSET_SECTOR_SIZE)){
LOG_SYS_ERASE(sLogIndexUnion.IndexStruct.curIndex);
sLogIndexUnion.IndexStruct.rawTotal -= (CHIPSET_SECTOR_SIZE / EACH_LOG_SPACE);
}
sLogIndexUnion.IndexStruct.writeFlag = LOG_WRITE_FLAG;
LogSysInfo_setIndex(sLogIndexUnion);
uLogContentUnion.ContentStruct.curNum = sLogIndexUnion.IndexStruct.cntTotal;
uLogContentUnion.ContentStruct.curTime = RTC_GetCounter();
uLogContentUnion.ContentStruct.verifyVal = LogSysInfo_calcXor8(uLogContentUnion.ConentArry,LOG_CONTENT_TOTAL);
uLogContentUnion.ContentStruct.writeFlag = LOG_WRITE_FLAG;
LOG_SYS_WRITE(uLogContentUnion.ConentArry,sLogIndexUnion.IndexStruct.curIndex,EACH_LOG_SPACE);
return LOG_PROC_SUCCEED;
}
LOG_PROC_STATE_ENUM LogSysInfo_getRecentInfo(LOG_CONTENT_UNION* pLogContentUnion, int32_t recentNum)
{
int32_t tSysLogAddr = 0;
if(sLogIndexUnion.IndexStruct.cntTotal <= recentNum){
return LOG_PROC_FAILED;
}
tSysLogAddr = ((sLogIndexUnion.IndexStruct.cntTotal - recentNum - 1) % LOG_INFO_TOTAL_CNT) *
EACH_LOG_SPACE + LOG_SYS_INFO_ADDRESS;
if(tSysLogAddr < LOG_SYS_INFO_ADDRESS){
tSysLogAddr = LOG_SYS_INFO_TOAL_SIZE + LOG_SYS_INFO_ADDRESS - EACH_LOG_SPACE;
}
LOG_SYS_READ(pLogContentUnion->ConentArry,tSysLogAddr,EACH_LOG_SPACE);
if(pLogContentUnion->ContentStruct.writeFlag == LOG_WRITE_FLAG)
return LOG_PROC_SUCCEED;
else
return LOG_PROC_FAILED;
}
LOG_PROC_STATE_ENUM LogSysInfo_getSerialInfo(LOG_CONTENT_UNION* pLogContentUnion, int32_t serNum)
{
int32_t tSysLogAddr = 0x000000;
int32_t tSysLogNum = 0;
if(serNum <= 0){
return LOG_PROC_FAILED;
}
if(sLogIndexUnion.IndexStruct.cntTotal < serNum){
return LOG_PROC_FAILED;
}
tSysLogNum = serNum % LOG_INFO_TOTAL_CNT;
tSysLogAddr = (tSysLogNum -1) * EACH_LOG_SPACE + LOG_SYS_INFO_ADDRESS;
LOG_SYS_READ(pLogContentUnion->ConentArry,tSysLogAddr,EACH_LOG_SPACE);
if(pLogContentUnion->ContentStruct.writeFlag == LOG_WRITE_FLAG)
return LOG_PROC_SUCCEED;
else
return LOG_PROC_FAILED;
}
LOG_PROC_STATE_ENUM LogSysInfo_clrOutage(void)
{
uint8_t tBytesFill[EACH_LOG_SPACE]= {0};
LOG_SYS_WRITE(tBytesFill,LOG_SYS_OUTAGE_ADDRESS,EACH_LOG_SPACE);
return LOG_PROC_SUCCEED;
}
LOG_PROC_STATE_ENUM LogSysInfo_setOutage(LOG_CONTENT_UNION uLogContentUnion)
{
LOG_SYS_WRITE(uLogContentUnion.ConentArry,LOG_SYS_OUTAGE_ADDRESS,EACH_LOG_SPACE);
return LOG_PROC_SUCCEED;
}
LOG_PROC_STATE_ENUM LogSysInfo_getOutage(LOG_CONTENT_UNION* pLogContentUnion)
{
LOG_SYS_READ(pLogContentUnion->ConentArry,LOG_SYS_OUTAGE_ADDRESS,EACH_LOG_SPACE);
return LOG_PROC_SUCCEED;
}
uint8_t LogSysInfo_calcXor8(uint8_t *pVarArry, uint8_t len)
{
uint8_t rvalue;
rvalue = pVarArry[0];
for(uint8_t i = 1; i < len; i++){
rvalue ^= pVarArry[i];
}
return rvalue;
}