/**
* @filename PFM_Log.c
* @brief Platform Function Module:日志相关功能
* @details
* 平台和应用的日志记录功能
* @author GT-BU
* @date 2021.02.20
* @version V1.0
* @copyright TCT
* @par 修改日志
* <table>
* <tr><th>Date        <th>Version  <th>Author     <th>Description
* <tr><td>2021.02.01  <td>V1.0     <td>GT-BU      <td>创建初始版本
* </table>
*/
#include "PFM_Log.h"
#include "PFM_RemoteUpdate.h"
#include "stdarg.h"
#include "CM_Time.h"
#include "CM_TCP.h"
#include "CM_Memory.h"
#include "CFM_Net.h"
#include "DFM_DRV.h"
#include "MSCP_APP_Interface.h"
#include "SFM_2x2.h"
#include "SFM_2oo2.h"
#include "CM_Convert.h"
#include <sys/timeb.h>
#include <stdlib.h>
#include "CM_IniFile.h"
#include "CFM_Raw.h"

extern CM_UINT32 g_MSCP_SysCount;
ENUM_INIT_STAGE_FLAG g_InitUpdateFlag = ENUM_ERROR;/*- 初始化阶段标志*/
static CM_UINT8 s_stopflag = 0xaau; /* 全局宕机标志 */
static CM_UINT8 s_AutoRebootCut= 0u;/*自动重启次数*/
CM_UINT8 g_AutoRebootVersion[4]= {0u};/*自动重启版本号*/
static CM_UINT16 stopTimer = TSCP_DARK_NULL;/*暗文日志参数*/
static CM_CHAR s_crashlogBuf[500] = { 0 };

static STRU_2OO2_NET_NO_PACK_T s_2oo2_AutoReboot = {
		.SN = 0u,							/*初始化SN码*/
		.DataSend = CFM_2oo2_DataSend_ASSERT,	/*注册发送函数指针*/
		.DataRecv = CFM_2oo2_DataRecv_ASSERT};	/*注册接收函数指针*/
		
static CM_UINT8 PFM_LOG_SHUTDOWN(CM_UINT32 darkBuf, CM_UINT32 MaintenanceFlag, const CM_CHAR *filename, const CM_CHAR *func, CM_INT32 line);
static void PFM_LOG_MaintenanceMode(ENUM_BOARD_STATE_T boardState, CM_UINT32 MaintenanceFlag);
/* @brief 通用循环日志管理
* @param file_type 文件类型标识
*        0: 宕机日志 (crashlog)
*        1: 跟踪日志 (.kev)
*        2: 线程日志 (threads)
* @return 无
*/
static void PFM_LOG_ManageFiles(CM_UINT8 file_type);
/**
* @brief 设置初始化阶段标志
* @param ENUM_INIT_STAGE_FLAG stage 设置初始化阶段
*/
void PFM_LOG_SET_INIT_STAGE(ENUM_INIT_STAGE_FLAG stage)
{
	/*- 设置初始化阶段 */
	g_InitUpdateFlag = stage;
}
/**
* @brief 获取宕机标志位
* @param 无
* @return 宕机标志位状态
*/
CM_UINT8 PFM_LOG_GET_STOP_FLAG(void)
{
	/*- 返回宕机标志位的值 */
	return s_stopflag;
}
/**
* @brief 获取初始化阶段标志
* @return ENUM_INIT_STAGE_FLAG stage 获取初始化阶段
*/
ENUM_INIT_STAGE_FLAG PFM_LOG_GET_INIT_STAGE(void)
{
	/*- 获取初始化阶段 */
	return g_InitUpdateFlag;
}
/**
* @brief 设置暗文日志阶段参数
* @param value 设置暗文日志阶段参数 取值范围：0~0xffff
*/
void PFM_LOG_SET_STOPTIMER(CM_UINT16 value)
{
	stopTimer = value;
}

/**
* @brief 获取自动重启次数
* @return 重启次数 取值范围:0~0xff
*/
CM_UINT8 MSCP_Get_AutoRbootCut(void)
{
	return s_AutoRebootCut;
}

/**
* @brief 重置自动重启次数
* @param Cut 重启次数
* @return 重启次数 取值范围:0~ff
*/
CM_UINT8 MSCP_Reset_AutoRbootCut(CM_UINT8 Cut)
{
	/*- 设置重启参数 */
	s_AutoRebootCut = Cut;
	/*- 返回结果 */
	return s_AutoRebootCut;
}
/**
* @brief 平台记录格式化字符串日志
* @param filename 文件路径
* @param func 函数名
* @param line 行号
* @param fmt 格式化字符串
*/
void MSCP_PFM_LOG_MSG(IN const CM_CHAR *filename, IN CM_INT32 line, IN const CM_CHAR* fmt, ...)
{
    /*- 变量初始化 */
    va_list argList;
    CM_CHAR msgBuf[1024 + 256];
    CM_INT32 headLen = 0;
    CM_INT32 msgLen = 0;
    if(NULL == fmt)
    {
    	/* 无处理 */
    }
    else
    {
        /*- 记录文件名、函数名、行号 */
        headLen = snprintf(msgBuf, sizeof(msgBuf), "ps:%s:%d:", filename, line);
        va_start(argList, (fmt));
        /*- 记录日志内容 */
        msgLen += vsnprintf(msgBuf + headLen, sizeof(msgBuf) - (CM_SIZE_T)headLen, fmt, argList);
        va_end(argList);
#ifdef WIN32
        Bootprintf("%s", msgBuf + headLen);
#endif
        /* printf("%s", msgBuf + headLen);*/
        /*- 输出日志信息 */
        (void)CFM_BaseLog_Send((CM_UINT8*)msgBuf, headLen + msgLen);
    }
}
/**
* @brief 平台记录二进制日志
* @param filename 文件路径
* @param func 函数名
* @param line 行号
* @param Buf 二进制数组指针
* @param Len 二进制数组长度
*/
void MSCP_PFM_LOG_BIN(IN const CM_CHAR *filename, IN const CM_CHAR *func, IN CM_INT32 line, IN const CM_UINT8 *Buf, IN CM_UINT32 Len)
{
    /*- 变量初始化 */
    CM_UINT32 i = 0u;
    CM_UINT32 cut = (Len/CFM_INNET_LOG_BIN_SIZE) + (((Len%CFM_INNET_LOG_BIN_SIZE) > 0u)?(1u):(0u));
    CM_CHAR tmepBuf[CFM_INNET_LOG_SIZE];
    CM_UINT32 msgLen = 0u;
    if(NULL == Buf)
    {
    	/* 无处理 */
    }
    else
    {
        for(i = 0u;i < cut;i++)
        {
        	(void)snprintf(tmepBuf, sizeof(tmepBuf), "pb:");
        	msgLen = ((cut-i)>1u)?CFM_INNET_LOG_BIN_SIZE:(Len%CFM_INNET_LOG_BIN_SIZE);
        	(void)CM_Memcpy(&tmepBuf[3],CFM_INNET_LOG_BIN_SIZE,&Buf[i*CFM_INNET_LOG_BIN_SIZE],(CM_SIZE_T)msgLen);
        	/*- 输出日志信息 */
        	(void)CFM_BaseLog_Send((CM_UINT8*)tmepBuf, msgLen+3u);
        }
    }
}


/**
* @brief 平台记录二进制日志/仅用于测试
* @param filename 文件路径
* @param func 函数名
* @param line 行号
* @param Buf 二进制数组指针
* @param Len 二进制数组长度
*/
void MSCP_PFM_LOG_BIN_TEST(IN const CM_CHAR *filename, IN const CM_CHAR *func, IN CM_INT32 line, IN const CM_UINT8 *Buf, IN CM_UINT32 Len)
{

        /*- 变量初始化 */
        CM_UINT32 i = 0u;
        CM_UINT32 i_cut = 0u;
        CM_UINT32 j = 0u;
        CM_UINT32 cut = (Len/CFM_INNET_LOG_BIN_TEST_SIZE) + (((Len % CFM_INNET_LOG_BIN_TEST_SIZE) > 0u)?1:0);
        CM_UINT8 tmepBuf[CFM_INNET_LOG_SIZE];
        CM_UINT8 str[10u] = {0u};
        CM_UINT32 msgLen = 0u;
        for(j = 0u;j < cut;j++)
        {
                msgLen = snprintf(tmepBuf, sizeof(tmepBuf), "pb:%d:",j);
                i_cut = ((cut-j) > 1u)?CFM_INNET_LOG_BIN_TEST_SIZE:(Len%CFM_INNET_LOG_BIN_TEST_SIZE);
                for(i = 0u;i < i_cut;i++)
                {
                        msgLen += sprintf(str,"0x%x.",Buf[j*CFM_INNET_LOG_BIN_TEST_SIZE+i]);
                        strcat(tmepBuf,str);
                }
                //printf("%s", tmepBuf);
                /*- 输出日志信息 */
                (void)CFM_BaseLog_Send((CM_UINT8*)tmepBuf, msgLen);
        }
}

/**
* @brief 平台\应用记录暗文日志
* @param infoType 数据类型
* 取值范围：0x55：info为字符串数据方式
* 		   0xAA：info为十六进制数据方式
* 		   0xFF：info为十进制数据方式
* @param code 信息编码/信息类型   取值范围：0~0xffff
* @param infoLen 数据长度  取值范围：0~0xffff
* @param info 数据/信息 取值范围：任意类型指针
*/
void MSCP_PFM_LOG_DARK(IN const CM_UINT8 infoType, IN const CM_UINT16 code, IN const CM_UINT32 infoLen, IN const void *info)
{
	(void)CFM_DarkLog_Storage(infoType, code, infoLen, info);
}

void MSCP_ASSERT_TraceLog(void)
{
	CM_CHAR trace_cmd[256] = {0};
	CM_CHAR pidin_cmd[256] = {0};
	CM_INT32 ret = 0;
    (void)sprintf(trace_cmd, 
             "tracelogger -c -n %d -s%d -f %s &", PFM_RECORD_BUF, PFM_RECORD_TIME_S, PFM_LATEST_TRACE_NAME);
	ret = system(trace_cmd);
	if (-1 == ret) 
	{
        (void)printf("ERROR: Failed to start tracelogger: %s\n", strerror(errno));
		MSCP_LOG_MSG("assert's tracelogger or threads_log system fail\n");
    }
	else
	{
		;
	}
	(void)sprintf(pidin_cmd, 
             "pidin -p %d threads >> %s &", getpid(),PFM_LATEST_THREADS_NAME);
	ret = system(pidin_cmd);   
    if (-1 == ret) 
	{
        (void)printf("ERROR: Failed to start pidin: %s\n", strerror(errno));
		MSCP_LOG_MSG("assert's pidin or threads_log system fail\n");
    }
	else
	{
		;
	}
    CM_Sleep(PFM_RECORD_TIME_S + 1u);
}

/**
* @brief 断言
* @param x 断言结果
* @param filename 文件路径
* @param Mode 发生故障函数模块
* @param faultCode 模块内函数顺序
* @param funNum 函数内宕机顺序
* @param func 函数名
* @param line 行号
*/
void MSCP_ASSERT(unsigned int x, unsigned int MaintenanceFlag, unsigned short Mode, unsigned char faultCode, unsigned char funNum, const char *filename, const char *func, int line)
{
	/*- 变量初始化*/
	static CM_UINT8 state = 0xaaU;
	static FILE * fp_crash;
	static FILE * fp_historical;
	static CM_CHAR str_crash[256] = {0};
	static CM_INT16 ret = -1;

	CM_UINT8 lightPs = 0x55;
	CM_UINT8 i = 0u;/*循环计次*/
    CM_UINT8 mybuf[29] = {0};
    CM_UINT8 peerbuf[29] = {0};
    CM_INT32 rxLen = 0;
	/*- 填充暗文故障码*/
    CM_UINT32 darkBuf = (Mode<<16u)|(faultCode<<8u)|funNum;
	ENUM_2x2_STATE_T  localState = ENUM_2x2_SHUTDOWN;
	CM_UINT8 countFalse = 0xff;
	CM_UINT8 tmepIndex = 0u;
	/*- 全局宕机标志是否有效 */
	if(0x55u == s_stopflag)
	{
		/*- 宕机死循环 */
		while(1)
		{
			/*- 休眠500ms */
			CM_Sleep(500u);
		}
	}
    else
	{
		/*- 无处理 */
	}

    /*- 断言是否失效 */
    if (0u == x)
    {
    	/*- 置位全局宕机标志 */
    	s_stopflag = 0x55u;
    	SFM_2x2_LOG_Transition();
		/*- 控制台输出断言失效信息 */
		MSCP_LOG_MSG("ASSERT: %s:%s:%d,version:%d.%d.%d.%d,Cyc = %d,DefaultNum:0x%x\n", filename, func, line,MSCP_SW_VERION[0], MSCP_SW_VERION[1], MSCP_SW_VERION[2], MSCP_SW_VERION[3],g_MSCP_SysCount,darkBuf);
		(void)printf("ASSERT: %s:%s:%d,version:%d.%d.%d.%d,Cyc = %d,DefaultNum:0x%x\n", filename, func, line,MSCP_SW_VERION[0], MSCP_SW_VERION[1], MSCP_SW_VERION[2], MSCP_SW_VERION[3],g_MSCP_SysCount,darkBuf);
		fp_crash = fopen("crashlog.txt", "w+");
		fp_historical = fopen("historicallog.txt", "a");
		for(i = 0; i < 3; i++)
		{
			(1 == g_App_Verson.registerVerson[i].versonName)?tmepIndex = i:tmepIndex;
		}
		(void)sprintf(str_crash,"0x%x\n0x%x\n0x%x\ncrash %u times Num[0x%x]: ASSERT: %s:%s:%d\n",
				countFalse,
				RM_Get_FaultRbootCut(),
				CM_LongFromChar(g_App_Verson.registerVerson[tmepIndex].verson),
				s_AutoRebootCut,darkBuf,filename, func, line);
		ret=fwrite(str_crash,(CM_SIZE_T)1u,strlen(str_crash),fp_crash);
		if (ret != strlen(str_crash))
		{
			MSCP_LOG_MSG("fwrite crashlog.txt fail!\n");
			(void)printf("fwrite crashlog.txt fail!\n");
		}
		else
		{
			/*- 无处理 */
		}
		ret=fwrite(str_crash,(CM_SIZE_T)1u,strlen(str_crash),fp_historical);
		if (ret != strlen(str_crash))
		{
			MSCP_LOG_MSG("fwrite historicallog.txt fail!\n");
			(void)printf("fwrite historicallog.txt fail!\n");
		}
		else
		{
			/*- 无处理 */
		}
		CFM_BaseLog_SaveLocal(fp_crash);
		(void)fclose(fp_crash);
		(void)fclose(fp_historical);
		/*- 关闭所有TCP连接 */
		(void)CM_TCP_Socket_Close_shutdown();
		CM_Sleep(500u);
		/*- 安全关断*/
		DFM_saftyOff();

		MSCP_ASSERT_TraceLog();
		/*- 设置LED指示灯*/
		if(ENUM_INIT_DRV <= PFM_LOG_GET_INIT_STAGE())
		{
			/*- 设置LED指示灯*/
			DFM_ledError();
			DFM_ledMS(0u);
			DFM_ledMonitor(2);
			/*IO输出导向安全*/
			CM_Sleep(10u);
			(void)DFM_SetIO_OutPut(0x00);
		}
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_PSLIGHT, 1U, &lightPs);
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, stopTimer, 1u, &state);
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_INFO_ERR_TYPE, 4u, &darkBuf);/*发送暗文故障编码*/
		/*- 更改热备状态为宕机,通过暗文再次发送热备状态帧(要保证这个帧是该暗文日志最后一个热备状态帧) */
		SFM_2x2_SetLocal2x2State(localState);
		localState = SFM_2x2_GetLocal2x2State();
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_LOCAL, 1U, &localState);
		/*- 暗文标志位至为发送 */
		if(ENUM_INIT_MAIN_NET <= PFM_LOG_GET_INIT_STAGE())
		{
			CFM_LogCiphertextSend();
		}

		/*- 退出运营故障码*/
		if(darkBuf == 0x0D0404)
		{
			/*- 退出运营模式*/
			PFM_SetBoardState(ENUM_BOARDSTATE_EXIT);
		}
		else
		{
			/*- 设置故障模式*/
			if((ENUM_INIT_2OO2_DATA <= g_InitUpdateFlag) && (ENUM_INIT_2X2 >= g_InitUpdateFlag))
			{
				PFM_SetBoardState(ENUM_BOARDSTATE_UPDATE);
			}
			else
			{
				PFM_SetBoardState(ENUM_BOARDSTATE_DEFAULT);
			}
			/*- 二取发送重启命令*/
			if((0x55u == g_PFM_Cfg.M_2oo2_Enable) && (ENUM_INIT_2OO2_DATA <= PFM_LOG_GET_INIT_STAGE()))
			{
				/*- 交互类型*/
				CM_LongToChar(6u,&mybuf[0]);
				/*通信次数*/
				mybuf[4] = 0x01u;
				/*禁止重启*/
				mybuf[5] = 0xFFu;
				/*维护模式*/
				mybuf[6] = MaintenanceFlag;
				/*2取-主线程2取数据最小为23字节*/
				rxLen = CFM_2oo2_Currency_NoSplit(&s_2oo2_AutoReboot,mybuf,13,peerbuf,29);
				if(rxLen >= 13)
				{
					(void)printf("MSCP_ASSERT:rcv success Type:0x%x,ReBoot:0x%x,MF:0x%x\n",peerbuf[3],peerbuf[5],peerbuf[6]);
				}
				else
				{
					(void)printf("MSCP_ASSERT:rcv fail\n");
				}
			}
		}
		/*- 维护模式*/
		PFM_LOG_MaintenanceMode(MaintenanceFlag, darkBuf);
    }
}
/**
* @brief 自动重启断言
* @param x 断言结果
* @param filename 文件路径
* @param Mode 发生故障函数模块
* @param faultCode 模块内函数顺序
* @param funNum 函数内宕机顺序
* @param func 函数名
* @param line 行号
*/
void MSCP_REBOOT_ASSERT(unsigned int x, unsigned int MaintenanceFlag,unsigned short Mode, unsigned char faultCode, unsigned char funNum, const char *filename, const char *func, int line)
{
	/*- 变量初始化*/
	static CM_UINT8 state = 0xaaU;
	CM_UINT8 AutoReboot_Flag = 0u;
	/*- 填充暗文故障码*/
    CM_UINT32 darkBuf = (Mode<<16u)|(faultCode<<8u)|funNum;
	ENUM_2x2_STATE_T  localState = ENUM_2x2_SHUTDOWN;
	CM_UINT8 lightPs = 0x55;
	/*- 全局宕机标志是否有效 */
	if(0x55u == s_stopflag)
	{
		/*- 宕机死循环 */
		while(1)
		{
			/*- 休眠500ms */
			CM_Sleep(500u);
		}
	}
    else
	{
		/*- 无处理 */
	}

    /*- 断言是否失效 */
    if (0u == x)
    {
    	/*- 置位全局宕机标志 */
    	s_stopflag = 0x55u;
    	SFM_2x2_LOG_Transition();
		/*- 控制台输出断言失效信息 */
		MSCP_LOG_MSG("MSCP_REBOOT_ASSERT: %s:%s:%d,version:%d.%d.%d.%d,Cyc = %d,DefaultNum:0x%x\n", filename, func, line,MSCP_SW_VERION[0], MSCP_SW_VERION[1], MSCP_SW_VERION[2], MSCP_SW_VERION[3],g_MSCP_SysCount,darkBuf);
		(void)printf("MSCP_REBOOT_ASSERT: %s:%s:%d,version:%d.%d.%d.%d,Cyc = %d,DefaultNum:0x%x\n", filename, func, line,MSCP_SW_VERION[0], MSCP_SW_VERION[1], MSCP_SW_VERION[2], MSCP_SW_VERION[3],g_MSCP_SysCount,darkBuf);
		AutoReboot_Flag = PFM_LOG_SHUTDOWN(darkBuf, MaintenanceFlag, filename, func, line);
		/*- 关闭所有TCP连接 */
		(void)CM_TCP_Socket_Close_shutdown();
		CM_Sleep(500u);
		/*- 安全关断*/
		DFM_saftyOff();
		if(ENUM_INIT_DRV <= PFM_LOG_GET_INIT_STAGE())
		{
			/*- 设置LED指示灯*/
			DFM_ledError();
			DFM_ledMS(0u);
			DFM_ledMonitor(2);
			/*IO输出导向安全*/
			CM_Sleep(10u);
			(void)DFM_SetIO_OutPut(0x00);
		}
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, stopTimer, 1u, &state);
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_INFO_ERR_TYPE, 4u, &darkBuf);/*发送暗文故障编码*/
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_PSLIGHT, 1U, &lightPs);
		/*- 更改热备状态为宕机,通过暗文再次发送热备状态帧(要保证这个帧是该暗文日志最后一个热备状态帧) */
		SFM_2x2_SetLocal2x2State(localState);
		localState = SFM_2x2_GetLocal2x2State();
		(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_LOCAL, 1U, &localState);
		/*- 暗文标志位至为发送 */
		if(ENUM_INIT_MAIN_NET <= PFM_LOG_GET_INIT_STAGE())
		{
			CFM_LogCiphertextSend();
		}
		MSCP_ASSERT_TraceLog();
		/*- 是否执行重启命令*/
		if(AutoReboot_Flag == 0x55u)
		{
			(void)printf("See You Later!!!\n");
			CM_Sleep(2000u);
			(void)system("shutdown");
			/*- 休眠等待重启 */
			CM_Sleep(CM_UINT32_MAX);
		}
		else
		{
			(void)printf("Please check err!!!\n");
		}

		/*- 设置故障模式*/
		PFM_SetBoardState(ENUM_BOARDSTATE_DEFAULT);

		/*- 维护模式*/
		PFM_LOG_MaintenanceMode(MaintenanceFlag, darkBuf);
    }
}
/**
* @brief 断言(维护模式下使用的断言函数)
* @param x 断言结果
* @param filename 文件路径
* @param func 函数名
* @param line 行号
*/
void MSCP_ASSERT_MAINTAIN(unsigned int x, const char *filename, const char *func, int line)
{
    static CM_UINT8 count = 0;
    if (0u == x)
    {
		MSCP_LOG_MSG("MSCP_ASSERT_MAINTAIN ASSERT(MAINTAIN): %s:%s:%d ,count = %u\n, Cyc = %u\n", filename, func, line, count, g_MSCP_SysCount);
		count ++;
    }
}
/**
* @brief 上电读取和删除本地日志文件
* @return 无
*/
void MSCP_Read_Del_Logfile(void)
{
	/*- 变量初始化 */
	CM_CHAR buf_i[100] = { 0 }; /* 临时变量：字符串缓冲区 */
	CM_CHAR buf_o[100] = { 0 }; /* 临时变量：字符串缓冲区 */
	CM_CHAR historyBuf[2048];
	CM_CHAR tempBuf[2048];
	CM_UINT32 fileCurrentSize = 0;
	CM_UINT32 i  = 0;
	CM_UINT8 tempdata = 0u;
	CM_UINT32 tempversion  = 0u;
	FILE *fp_historical = fopen("historicallog.txt", "r+");
	FILE *pfile = fopen("crashlog.txt", "r");/* 文件指针 */
	FILE *p_rebootfile = fopen("rebootlog.txt", "r");/* 文件指针 */
	/*- 如果描述符不为空*/
	if (pfile != NULL)
	{
		/*- @alias 读取重启次数 */
		if(NULL != fgets(buf_i, 100, pfile))
		{
			(void)printf("crashlog:%s",buf_i);
			/*- 删除空格*/
			a_trim(buf_o, buf_i);
			/*- 提取重启次数*/
			(void)sscanf(buf_o, "%x", &s_AutoRebootCut);
			(void)printf("crashlog:s_AutoRebootCut = 0x%x\n",s_AutoRebootCut);
			/*- 禁止重启后清零*/
			if(0xFF == s_AutoRebootCut)
			{
				/*- 清零*/
				s_AutoRebootCut = 0u;
				(void)printf("crashlog:RebootCut = 0x%x\n",s_AutoRebootCut);
			}
			else
			{
				/*- nothing to do*/
			}
		}
		else
		{
			(void)printf("crashlog1:read fail!!!\n");
		}
		/*- @alias 读取故障软重启次数 */
		if((!feof(pfile)) && (NULL != fgets(buf_i, 100, pfile)))
		{
			(void)printf("crashlog:%s",buf_i);
			/*- 删除空格*/
			a_trim(buf_o, buf_i);
			/*- 提取重启次数*/
			(void)sscanf(buf_o, "%x", &tempdata);
			(void)printf("crashlog:FaultRebootCut = 0x%x\n",tempdata);
			RM_Reset_FaultRbootCut(tempdata);
		}
		else
		{
			(void)printf("crashlog2:read fail!!!\n");
		}
		/*- @alias 读取版本号 */
		if((!feof(pfile)) && (NULL != fgets(buf_i, 100, pfile)))
		{
			(void)printf("crashlog:%s",buf_i);
			/*- 删除空格*/
			a_trim(buf_o, buf_i);
			/*- 提取版本号*/
			(void)sscanf(buf_o, "%x", &tempversion);
			CM_LongToChar(tempversion,g_AutoRebootVersion);
			(void)printf("crashlog:Ver:%d,%d,%d,%d,\n",g_AutoRebootVersion[0],g_AutoRebootVersion[1],g_AutoRebootVersion[2],g_AutoRebootVersion[3]);
		}
		else
		{
			(void)printf("crashlog3:read fail!!!\n");
		}
		/*- 读取上一次宕机原因写入缓冲区s_crashlogBuf */
		if((!feof(pfile)) && (NULL != fgets(s_crashlogBuf, 450, pfile)))
		{
			(void)printf("crashlog:%s",buf_i);
		}
		else
		{
			(void)printf("crashlog4:read fail!!!\n");
		}
		/*- 关闭文件描述符 */
		(void)fclose(pfile);
		PFM_LOG_ManageFiles(0u);
		PFM_LOG_ManageFiles(1u);
		PFM_LOG_ManageFiles(2u);
	}
	else
	{
		/*- 文件不存在空指针为正常情况*/
	}

	if(p_rebootfile != NULL)
	{
		/*- @alias 读取重启次数 */
		if(NULL != fgets(buf_i, 100, p_rebootfile))
		{
			(void)printf("rebootlog:%s",buf_i);
			/*- 删除空格*/
			a_trim(buf_o, buf_i);
			/*- 提取重启次数*/
			(void)sscanf(buf_o, "%x", &tempdata);
			(void)printf("rebootlog:FaultRebootCut = 0x%x\n",tempdata);
			/*- 清零*/
			RM_Reset_FaultRbootCut(tempdata);
			(void)printf("rebootlog:FaultRebootCut = 0x%x\n",RM_Get_FaultRbootCut());
		}
		else
		{
			/*- 读取失败*/
			(void)printf("rebootlog:read fail!!!\n");
		}
		/*- 关闭文件描述符 */
		(void)fclose(p_rebootfile);
	}
	else
	{
		/*- 无处理 */
	}
	(void)remove("crashlog.txt");
	(void)remove("signallog.txt");
	(void)remove("RmUpSucess.txt");
	(void)remove("rebootlog.txt");

	/*- @alias 更新historicallog.txt文件  */
	if (fp_historical != NULL)
	{
		fseek(fp_historical, 0, SEEK_END);
		/*- 获取当前文件字节数 */
		fileCurrentSize = ftell(fp_historical);
		printf("fileCurrentSize = %d\n",fileCurrentSize);
		/*- 文件超过20kb,则更新historicallog.txt(大概能记录305条左右宕机信息) */
		if(fileCurrentSize >= 20480)
		{
			fseek(fp_historical, fileCurrentSize-1024, SEEK_SET);
			fileCurrentSize = fread(historyBuf, 1024, 1, fp_historical);
			(void)fclose(fp_historical);
			/*- 处理字符串 */
			for(i = 0; i < 1024; i++)
			{
				if(('\n' == historyBuf[i]) && ('0' == historyBuf[i+1]))
				{
					(void)CM_Memcpy(tempBuf,1024,&historyBuf[i+1],1024-i);
					break;
				}
			}

			fp_historical = fopen("historicallog.txt", "w");
			fileCurrentSize = fwrite(tempBuf, 1024-i, 1, fp_historical);
		}
		else
		{
			/*- 无处理 */
		}
		(void)fclose(fp_historical);
	}
	else
	{
		/*- 文件不存在空指针为正常情况*/
	}
}

/**
* @brief 打印数据和长度
* @param Buf 存放数据缓冲区 取值范围：非空
* @param Len 缓冲区大小 取值范围：0~0xffffffff
* @param Annotation 注释 取值范围：非空
*/
void MSCP_LOG_DATALEN(IN CM_UINT8 *Buf, IN CM_UINT32 Len, IN char *Annotation)
{
	/*- 入参不为空*/
	if((NULL != Annotation) && (NULL != Buf))
	{
		/*- 发送数据和长度日志 */
		MSCP_LOG_MSG("%s , Len = %d\n", Annotation, Len);
		MSCP_LOG_BIN(Buf, Len);
	}
	else
	{
		/*- 无处理 */
		MSCP_LOG_MSG("MSCP_LOG_DATALEN is NULL\n");
	}

}

/**
* @brief 宕机后自动重启判断
* @param darkBuf 故障码 取值范围：0~0xffffffff
* @param MaintenanceFlag 是否允许远程重启 取值范围：0~0xffffffff
* @param filename 故障码 取值范围：非空
* @param func 故障码 取值范围：非空
* @param line 故障码 取值范围：0~0x7fffffff
* @return AutoReboot_Flag 取值范围：0x55允许重启，0xaa不允许重启
*/
static CM_UINT8 PFM_LOG_SHUTDOWN(CM_UINT32 darkBuf, CM_UINT32 MaintenanceFlag, const CM_CHAR *filename, const CM_CHAR *func, CM_INT32 line)
{
	/*- 变量初始化 */
	CM_UINT8 AutoReboot_Flag = 0u;
	static FILE * fp_crash;
	static FILE * fp_historical;
    CM_UINT8 mybuf[29] = {0};
    CM_UINT8 peerbuf[29] = {0};
    CM_UINT8 i = 0u;
    CM_INT32 rxLen = 0;
	static CM_CHAR str_crash[256] = {0};
	static CM_INT16 ret = -1;
	CM_UINT8 countFalse = 0xff;
	CM_UINT8 tmepIndex = 0u;

	fp_crash = fopen("crashlog.txt", "w+");
	fp_historical = fopen("historicallog.txt", "a");
	/*- 二取是否全部允许重启*/
	if((0x55u == g_PFM_Cfg.M_2oo2_Enable) && (ENUM_INIT_2OO2_DATA <= PFM_LOG_GET_INIT_STAGE()))
	{
		/*- 交互类型*/
		CM_LongToChar(6u,&mybuf[0u]);
		/*- 获取通信次数*/
		mybuf[4u] = 0x01u;
		/*- 如果重启次数是否达到最大值 */
		if(g_PFM_Cfg.M_AutoReboot_Count > s_AutoRebootCut)
		{
			/*- 允许重启*/
			mybuf[5u] = s_AutoRebootCut + 1u;
		}
		else
		{
			/*- 禁止重启*/
			mybuf[5u] = 0xFFu;
		}
		/*维护模式*/
		mybuf[6u] = MaintenanceFlag;
		/*2取-主线程2取数据最小为23字节*/
		rxLen = CFM_2oo2_Currency_NoSplit(&s_2oo2_AutoReboot,mybuf,13,peerbuf,29);
		if(rxLen >= 13)
		{
			(void)printf("MSCP_REBOOT_ASSERT:rcv success Type:0x%x,ReBoot:0x%x,MF:0x%x\n",peerbuf[3],peerbuf[5],peerbuf[6]);
			/*- 判断是否禁止重启 */
			if((0xFFu == mybuf[5u]) || (0xFFu == peerbuf[5u]))
			{
				(void)printf("MSCP_REBOOT_ASSERT:No reboot\n");
				/*- 禁止重启*/
				AutoReboot_Flag = 0xAAu;
			}
			else
			{
				/*- 允许重启*/
				(void)printf("MSCP_REBOOT_ASSERT:Ok reboot\n");
				AutoReboot_Flag = 0x55u;
			}
		}
		else
		{
			(void)printf("MSCP_ASSERT:rcv fail\n");
		}
	}
	else
	{
		/*- 判断重启次数是否达到最大值 */
		if(g_PFM_Cfg.M_AutoReboot_Count > s_AutoRebootCut)
		{
			/*- 允许重启*/
			AutoReboot_Flag = 0x55u;
		}
		else
		{
			/*- 禁止重启*/
			AutoReboot_Flag = 0xAAu;
		}
	}

	for(i = 0; i < 3; i++)
	{
		(1 == g_App_Verson.registerVerson[i].versonName)?tmepIndex = i:tmepIndex;
	}

	/*- 判断重启标志 */
	if(AutoReboot_Flag == 0x55u)
	{
		/*- 允许重启，根据重启条件判断写入文件次数*/
		/*- 1、记录自动重启次数
		 *  2、记录故障软重启次数
		 *  3、记录版本号
		 *  4、记录宕机故障码信息等*/
		(void)sprintf(str_crash,"0x%x\n0x%x\n0x%lx\ncrash %u times Num[0x%x]: ASSERT: %s:%s:%d\n", \
				s_AutoRebootCut + 1,
				RM_Get_FaultRbootCut(),
				CM_LongFromChar(g_App_Verson.registerVerson[tmepIndex].verson),
				s_AutoRebootCut,darkBuf,filename, func, line);
	}
	else
	{
		/*- 禁止重启，根据重启条件判断写入文件次数*/
		(void)sprintf(str_crash,"0x%x\n0x%x\n0x%lx\ncrash %u times Num[0x%x]: ASSERT: %s:%s:%d\n", \
				countFalse,
				RM_Get_FaultRbootCut(),
				CM_LongFromChar(g_App_Verson.registerVerson[tmepIndex].verson),
				s_AutoRebootCut,darkBuf, filename, func, line);
	}
	ret=fwrite(str_crash,(CM_SIZE_T)1u,strlen(str_crash),fp_crash);
	if (ret != strlen(str_crash))
	{
		MSCP_LOG_MSG("fwrite crashlog.txt fail!\n");
		(void)printf("fwrite crashlog.txt fail!\n");
	}
	else
	{
		/*- 无处理 */
	}
	CFM_BaseLog_SaveLocal(fp_crash);
	(void)fclose(fp_crash);
	ret=fwrite(str_crash,(CM_SIZE_T)1u,strlen(str_crash),fp_historical);
	if (ret != strlen(str_crash))
	{
		MSCP_LOG_MSG("fwrite historicallog.txt fail!\n");
		(void)printf("fwrite historicallog.txt fail!\n");
	}
	else
	{
		/*- 无处理 */
	}
	(void)fclose(fp_historical);
	return AutoReboot_Flag;
}

/**
* @brief 维护模式主逻辑
* @param MaintenanceFlag 是否允许远程重启 取值范围：0~0xffffffff
* @param darkBuf 故障码 取值范围：0~0xffffffff
* @return 无
*/
static void PFM_LOG_MaintenanceMode(ENUM_BOARD_STATE_T MaintenanceFlag, CM_UINT32 darkBuf)
{
	/*- 变量初始化 */
	CM_UINT64 sMaintenanceTack = CM_GetTick()/CM_UNSIGNED_MILLION;
	CM_UINT64 cMaintenanceTack = 0u;
	CM_UINT64 eMaintenanceTack = 0u;
	CM_UINT64 leftTime = 0u;    /* 剩余时间 */
	CM_UINT64 u_64temp = g_PFM_Cfg.CYC_TIME;    /*uint64临时变量*/
	CM_UINT64 s_count = 0;
	ENUM_BOARD_STATE_T boardState = PFM_GetBoardState();
	CM_UINT8 lightPs = 0x55;
	ENUM_2x2_STATE_T localState = SFM_2x2_GetLocal2x2State();
	CM_UINT64 costlog[2] = {0};
	/*- 清空2取缓冲区数据 */
	SFM_2oo2_CtrlInit();
	eMaintenanceTack = sMaintenanceTack + u_64temp;
	while (1)
	{
		/*- 远程部署功能开关开启，并且维护id应用已设置不是初始值0 是否允许进入维护模式*/
		if ((0x55u == g_RMUP_Cfg.M_RemoteUpdate_Enable) && (0x00u != g_Maintenance_Id) && (0x55 == MaintenanceFlag) && ((ENUM_BOARDSTATE_EXIT == boardState) || (ENUM_BOARDSTATE_UPDATE == boardState) || (ENUM_BOARDSTATE_DEFAULT == boardState)))
		{
			MSCP_LOG_MSG("----------Maintenance Mode count = %d----------\n",s_count);

			PFM_MaintenanceMode();
			boardState = PFM_GetBoardState();
			s_count ++;
			cMaintenanceTack = CM_GetTick()/CM_UNSIGNED_MILLION;
			if (eMaintenanceTack < cMaintenanceTack)
			{
				MSCP_LOG_MSG("eMaintenanceTack = %llu,cMaintenanceTack = %llu\n",eMaintenanceTack,cMaintenanceTack);
			}
			else
			{

			}
			costlog[0] = CM_GetTick();
			/*- 设置LED指示灯*/
			DFM_ledError();
			DFM_ledMS(0u);
			DFM_ledMonitor(1u);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_PSLIGHT, 1U, &lightPs);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_LOCAL, 1U, &localState);
			(void)CFM_DarkLog_Storage(DARK_LOG_HEX, TSCP_DARK_INFO_ERR_TYPE, 4u, &darkBuf);
			/*发送暗文日志*/
			CFM_LogCiphertextSend();
			costlog[1] = CM_GetTick();
			MSCP_LOG_MSG("7 LedDark cost = %lld us\n", (costlog[1] - costlog[0]) / 1000u);
			if(eMaintenanceTack < cMaintenanceTack)
			{
				leftTime = 0u;
				sMaintenanceTack = cMaintenanceTack;
				MSCP_LOG_MSG("Maintenance mode overtime\n");
			}
			else
			{
				leftTime = eMaintenanceTack - cMaintenanceTack;
				sMaintenanceTack = eMaintenanceTack;
			}
			eMaintenanceTack = eMaintenanceTack + u_64temp;
			MSCP_LOG_MSG("Maintenance leftTime = %d\n",leftTime);
			CM_Sleep((CM_UINT32)leftTime);
		}
		else
		{
			MSCP_LOG_MSG("MaintenanceFlag = %d, g_Maintenance_Id = %d, g_RMUP_Cfg.M_RemoteUpdate_Enable = %d, boardState = %d\n", \
					MaintenanceFlag,g_Maintenance_Id,g_RMUP_Cfg.M_RemoteUpdate_Enable,boardState);
			CM_Sleep(CM_UINT32_MAX);
		}
	}
}

void PFM_SendLastAssertLog(void)
{
	MSCP_LOG_MSG("Last crashlog:%s \n", s_crashlogBuf);
}

/**
* @brief 通用循环日志管理
* @param file_type 文件类型标识
*        0: 宕机日志 (crashlog)
*        1: 跟踪日志 (.kev)
*        2: 线程日志 (threads)
* @return 无
*/
static void PFM_LOG_ManageFiles(CM_UINT8 file_type)
{
	/*- 读宕机文件*/
    FILE *p_file = NULL;
    CM_CHAR str_new_name[256] = {0};
    CM_CHAR str_old_name[256] = {0};
    CM_CHAR final_name[256] = {0};
    CM_CHAR base_name[64] = {0};
    CM_CHAR extension[16] = {0};
    CM_CHAR latest_file[128] = {0};
    CM_UINT32 max_count = 0u;
    CM_UINT32 i = 0u;
	CM_UINT8 typeValid = 1u;
    switch(file_type)
    {
        case 0u: /* 宕机日志 */
            (void)strcpy(base_name, "crashlog_");
            (void)strcpy(extension, ".txt");
            (void)strcpy(latest_file, "crashlog.txt");
            max_count = PFM_MAX_TRACE_COUNT;
            break;
        case 1u: /* 跟踪日志 */
            (void)strcpy(base_name, PFM_BASE_TRACE_NAME);
            (void)strcpy(extension, ".kev");
            (void)strcpy(latest_file, PFM_LATEST_TRACE_NAME);
            max_count = PFM_MAX_TRACE_COUNT;
            break;
        case 2u: /* 线程日志 */
            (void)strcpy(base_name, PFM_BASE_THREADS_NAME);
            (void)strcpy(extension, ".txt");
            (void)strcpy(latest_file, PFM_LATEST_THREADS_NAME);
            max_count = PFM_MAX_TRACE_COUNT;
            break;
        default:
			typeValid = 0u;
            break; /* 无效的文件类型 */
    }
    if(1u == typeValid)
	{
	/*- 查找第一个不存在的文件名 */
		for(i = 1u; i <= max_count; i++)
	{
		/*- 通过打开文件成功检测文件是否存在 */
			(void)sprintf(str_new_name, "%s%d%s", base_name, i, extension);
			p_file = fopen(str_new_name, "r");
		/*- 找到第一个不存在的文件名 */
			if(NULL == p_file)
		{
				(void)strcpy(final_name, str_new_name);
			break;
		}
		else
		{
			/*- 关闭文件 */
				(void)fclose(p_file);
		}
	}

	/*- 如果所有文件名都存在，删除最旧的日志（crashlog_1.txt）*/
		if(i > max_count)
	{
			(void)sprintf(str_old_name,"%s%d%s", base_name, 1u, extension);
			(void)remove(str_old_name);
			for(i = 2u; i <= max_count; i++)
		{
				(void)sprintf(str_new_name, "%s%d%s", base_name, i, extension);
				(void)sprintf(str_old_name, "%s%d%s", base_name, i - 1u, extension);
				(void)rename(str_new_name, str_old_name);
		}
			(void)strcpy(final_name, str_new_name);
	}
	/*- 对文件重新命名 */
		if(final_name[0] != 0)
		{
			(void)rename(latest_file, final_name);
		}
	}
}
/*
 * @brief 暗文日志故障码生成指针函数
 * @param mode 模块（0-0xff) fault 故障码（0-0xff） num 故障位置序号（0-0xff)
 * @return 故障码地址
 */
CM_UINT32 *PFM_DarkLogGenerate(CM_UINT16 mode, CM_UINT16 fault, CM_UINT16 num)
{
	/* 变量初始化*/
	static CM_UINT32 lastcode = 0u;
	/*拼接故障码*/
	lastcode = (mode<<16u)|(fault<<8u)|num;
	/*返回故障码地址*/
	return &lastcode;
}
