/**
* @file SFM_2x2.h
* @brief Safe Function Module:2x2功能
* @details
* 2x2上电初始化：初始化、上电同步、比较
* 输入阶段和输出阶段的双机热备处理
* @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>
*/
#ifndef SFM_2x2_H
#define SFM_2x2_H
#include "CM_Mutex.h"
#include "MSCP_APP_Interface.h"
#include "CM_Sem.h"
#include "CM_MultiThread.h"
#include "CM_MQ.h"
#include "PFM_Cfg.h"
#ifdef __cplusplus
extern "C"
{
#endif
extern CM_UINT32 g_MSCP_SysCount;
#define SFM_FOLLOW_BUFF_SIZE (1024u*1024u*2u)      /* 主备系间通信通道UDP缓冲区大小 1024k*2，应用许用量为1500k */

/*双机热备参数*/
#define MSCP_2x2_OFFLINE_WAIT (5)    /**< 离线保持时间（单位：ms）在离线状态保持大于等该时间长度之后才会进入预升主状态*/
#define MSCP_2x2_PREMASTER_WAIT (5)  /**< 预升主等待时间（单位：ms）在预升主状态保持大于等于该时间长度之后才会进入主状态*/

#define MSCP_2X2_COM_FAIL_CYC     (1u)  /**< 主备通信中断的判断时间（单位：周期），双网均收不到对系数据的周期数大于等于该值时视为通信中断*/
#define MSCP_2X2_COM_FAIL_DIFF    (2u)  /**< 判断双网同时中断的允许差异（单位：周期），如果双网通信中断的周期数差异小于等于该值，则认为是同时中断*/
#define MSCP_2X2_SYNC_TIMEOUT_CYC (5u)  /**< 同步超时阈值（单位：周期），备系连续未能完成主备同步的周期数大于等于该值时，备系转离线*/

#define MSCP_2X2_COM_THIS_STATE_NUM (2u)	/*本周期状态序号*/

#define MSCP_2X2_SWITCH_3S (3000000000u) 	/*切系按钮持续时间*/
#define MSCP_2X2_THREAD_TIME (40U) 	/*2x线程运行时间*/
#define MSCP_2X2_STATE_OVER_TIME (MSCP_2X2_THREAD_TIME + 25U) 	/*2x线程判断数据超时时间*/
#define MSCP_2X2_STATE_RCV_WITETIME (MSCP_2X2_THREAD_TIME - 20U) 	/*2x线程等待对系数据时间*/
    /** 2x2消息类型 */
    typedef enum
    {
        ENUM_2x2_MSG_ERROR = 0,  /**< 保留 */
        ENUM_2x2_MSG_CH1 = 1,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH2 = 2,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH3 = 3,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH4 = 4,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH5 = 5,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH6 = 6,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH7 = 7,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH8 = 8,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH9 = 9,    /**< 通信数据同步 */
        ENUM_2x2_MSG_CH10 = 10,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH11 = 11,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH12 = 12,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH13 = 13,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH14 = 14,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH15 = 15,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH16 = 16,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH17 = 17,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH18 = 18,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH19 = 19,  /**< 通信数据同步 */
        ENUM_2x2_MSG_CH20 = 20,  /**< 通信数据同步 */
        ENUM_2x2_MSG_SYNC = 21,  /**< 同步报文 */
        ENUM_2x2_MSG_STAT = 22,       /**< 热备状态报文 */
        ENUM_2x2_MSG_BASE_FOLLOW = 23,/**< 平台跟随报文 */
        ENUM_2x2_MSG_APP_FOLLOW = 24, /**< 应用跟随报文 */
        ENUM_2x2_MSG_OUTCHECK = 25,    /**< 输出校验报文 */
		ENUM_2x2_MSG_APP_FOLLOW_CRC = 26 /**< 应用跟随报文 CRC比较 */
    }ENUM_2x2_MSG_T;

    /** 2x2oo2的接收通道 */
    typedef struct
    {
        CM_UINT32 b_2oo2_Enable; /**< 2oo2功能开关 */
        CM_UINT32 b_2x2_Enable;  /**< 2x2功能开关 */

        CM_UINT32 buf_size;      /**< 通道缓冲区大小 */
        CM_UINT32 helpinfo_buf_size;/**< 辅助信息通道缓冲区大小 */
        CM_MUTEX_T app_mutex;   /**< app接口互斥器 */

        CM_UINT32 mine_len;      /**< 本机通道报文长度 */
        CM_UINT8* p_mine_buf;     /**< 本机通道报文缓冲区 */
        CM_UINT32 mine_helpinfo_len;    /**< 本机辅助信息通道报文长度 */
        CM_UINT8* p_mine_helpinfo_buf; /**< 本机辅助信息通道报文缓冲区 */

        CM_UINT32 peer_len;      /**< 邻机通道报文长度 */
        CM_UINT8* p_peer_buf;     /**< 邻机通道报文缓冲区 */
        CM_UINT32 peer_helpinfo_len;   /**< 邻机辅助信息通道报文长度 */
        CM_UINT8* p_peer_helpinfo_buf;/**< 邻机辅助信息通道报文缓冲区 */

        CM_UINT32 rmt_mine_len;  /**< 本机对系通道报文长度 */
        CM_UINT8* p_rmt_mine_buf; /**< 本机对系通道报文缓冲区 */
        CM_UINT32 rmt_mine_helpinfo_len;   /**< 本机对系辅助信息通道报文长度 */
        CM_UINT8* p_rmt_mine_helpinfo_buf;/**< 本机对系辅助信息通道报文缓冲区 */

        CM_UINT32 rmt_peer_len;  /**< 邻机对系通道报文长度 */
        CM_UINT8* p_rmt_peer_buf; /**< 邻机对系通道报文缓冲区*/
        CM_UINT32 rmt_peer_helpinfo_len;   /**< 邻机对系辅助信息通道报文长度 */
        CM_UINT8* p_rmt_peer_helpinfo_buf;/**< 邻机对系辅助信息通道报文缓冲区*/

        CM_UINT32 app_index_log;/*应用调用次数*/
    }STRU_2x2oo2_rx_T;

    /** 2x2oo2的发送通道 */
    typedef struct
    {
        CM_UINT32 b_2oo2_Enable; /**< 2oo2功能开关 */
        CM_UINT32 b_2x2_Enable;  /**< 2x2功能开关 */
        CM_MUTEX_T mutex;  /* app接口互斥锁 */
        CM_UINT32 buf_size; /* 通道缓冲区大小 */
        CM_INT32 buf_len;  /* 报文长度 */
        CM_UINT8 *p_buf;     /* 报文缓冲区 */
    }STRU_2x2oo2_tx_T;

    /** 2x2消息类型 */
	typedef enum
	{
		ENUM_2x2_SWITCH_CLOSE = 0,  /**< 切系状态为不需要主动切系 */
		ENUM_2x2_SWITCH_OPEN = 1    /**< 切系状态为需要主动切系 */
	}ENUM_2x2_SWITCH_STATE;
    /** 2x2AID切系消息类型 */
	typedef enum
	{
		ENUM_2x2_AIDSWITCH_OVER = 0,  /**< AID切系完成状态*/
		ENUM_2x2_AIDSWITCH_ENABLE = 1,    /**< AID切系允许状态 */
		ENUM_2x2_AIDSWITCH_DISABLE = 2    /**< AID切系禁止状态 */
	}ENUM_2x2_AID_SWITCH_STATE;
	/*记录通信状态*/
	typedef struct
	{
		CM_UINT8 MicroCyc;		/**< 微周期号 */
		CM_UINT32 SysCyc;		/**< 系统周期号 */
	}STRU_2X2_COM_STATE_RECORD_T;
	/** 2x2控制 */
	typedef struct
	{
	    /*
	    2oo2双机的与对系通信通道互为冗余，
	    所以对于通信数据，需要通过2oo2交换使双CPU取得全部一致的接收数据
	    但对于热备运算，所有运算结果需要通过2oo2比较以确保双机工作状态一致
	    */
	    CM_UINT32 LocalID;   /**< 本系ID */
	    CM_UINT32 PartnerID; /**< 对系ID */
	    CM_UINT32 TxSN;      /**< 发送序列号 */
	    CM_UINT32 RxSN;      /**< 接收序列号 */
	    CM_UINT32 SysCycSync;/**< 系统周期号 */

	    ENUM_2x2_STATE_T LocalState;  /**< 本系热备状态，2oo2比较 */
	    ENUM_2x2_STATE_T PartnerState;    /**< 收到的对系热备状态，2oo2交换 */
	    ENUM_2x2_STATE_T LastLocalState;  	  /**< 本系上一周期的热备状态，2oo2比较 */
	    ENUM_2x2_STATE_T LastPartnerState;    /**< 收到的对系上一周期热备状态，2oo2交换 */
		/*通信状态  */
		CM_BOOL MineComState;   /**< 本机通信状态，2oo2交换 */
		CM_BOOL PeerComState;   /**< 邻机通信状态，2oo2交换 */
		CM_BOOL MineUartState;  /**< 本机串口通信状态，2oo2交换 */
		CM_BOOL PeerUartState;  /**< 邻机串口通信状态，2oo2交换 */

	    /*输入数据*/
	    CM_UINT32 RxInputSysCyc;        /**< 收到的对系输入数据的周期号，2oo2交换 */
	    CM_UINT32 InputMineSysCyc;		/**< 当周期从对系收到的本cpu输入数据标志 */
	    CM_UINT32 InputPeerSysCyc;		/**< 当周期从对系收到的邻cpu输入数据标志 */
		CM_UINT32 InPutDoublePassLen[MSCP_DOUBLE_PASS_ALL_NUM][2];	/**< 当周期从对系收到同步数据长度 */

	    /*主备IO同步放在平台跟随阶段去做*/
	    CM_UINT8  MineInputIoState[10];		/*IO数据同步*/
	    CM_UINT8  PeerInputIoState[10];		/*IO数据同步*/
	    CM_UINT8  RmtMineInputIoState[10];	/*IO数据同步*/
	    CM_UINT8  RmtPeerInputIoState[10];	/*IO数据同步*/

	    /*跟随数据*/
	    CM_UINT32 RxBaseFollowSysCyc; /**< 收到的对系跟随数据的周期号，2oo2交换 */
	    CM_UINT32 RxAppFollowSysCyc;  /**< 收到的对系应用跟随数据的周期号，2oo2交换 */
	    CM_UINT32 LastFollowCyc;      /**< 上次进行平台跟随的时间，2oo2比较，*/

	    /*输出比较信息*/
	    CM_UINT32 LastCheckOKCount;     /**< 上次输出比较成功(跟随成功)的本地时间，2oo2比较  (这个标志用来判断如果未收到主系的数据,则停止更新,后将为离线)*/
	    CM_UINT32 OutPutCheckFailFlag;  /**< 上次输出比较成功(跟随成功)的本地时间，2oo2比较  (这个标志用来判断收到输出数据后是否比较成功, 比较失败则降级)*/
	    CM_UINT32 AppFollowCmpFlag; /**< 上次应用跟随数据比较结果，只有备系使用 (这个标志用来判断备系和主系应用跟随数据是否比较成功, 比较失败则降级)*/
	    CM_UINT32 RxCheckSysCyc;        /**< 收到的输出校验帧的周期号，2oo2交换 */
	    CM_INT32 RxCheckLen;            /**< 收到的输出校验帧长度，2oo2交换 */
	    CM_UINT8 RxCheckFrame[100];     /**< 收到的输出校验帧报文，2oo2交换 */
	    ENUM_2x2_AID_SWITCH_STATE AIDSwitchState;/**< aid切系控制标志 */
		CM_UINT8 TimeSyncFlag;			/**< 时间同步完成标志 */
	}STRU_2X2_CTRL_T;

	/*2x状态切换线程参数*/
	typedef struct
	{
	    CM_UINT32 LocalID;   	/**< 本系ID */
	    CM_UINT32 PartnerID; 	/**< 对系ID */
	    CM_UINT32 SysCyc;		/**< 系统周期号 */
	    CM_UINT8  MicroCyc;		/**< 微周期号 */
	    CM_UINT32 TxSN;      	/**< 发送序列号 */
	    CM_UINT32 RxSN;      	/**< 接收序列号 */

	    /*双系热备状态*/
	    ENUM_2x2_STATE_T LocalState;  	   /**< 本系热备状态，2oo2比较 */
		ENUM_2x2_STATE_T PartnerState;     /**< 收到的对系热备状态，2oo2交换 */
		ENUM_2x2_STATE_T LastLocalState;   /**< 本系上一周期的热备状态，2oo2比较 */
		ENUM_2x2_STATE_T LastPartnerState; /**< 收到的对系上一周期热备状态，2oo2交换 */

		CM_UINT32 offLineCounter;   	   /**< 离线计时器，2oo2比较 */
		CM_UINT32 preMasterCounter; 	   /**< 预升主计时器，2oo2比较 */
		/*通信状态        ABS((B-A)*5-ABS(b-a)),大小周期计算,考虑结构体数组*/
		STRU_2X2_COM_STATE_RECORD_T MineComOKCount[3u];   /**< 本机通信状态计数，2oo2交换 */
		STRU_2X2_COM_STATE_RECORD_T PeerComOKCount[3u];   /**< 邻机通信状态计数，2oo2交换 */
		STRU_2X2_COM_STATE_RECORD_T MineUartOKCount[3u];   /**< 本机串口通信状态计数，2oo2交换 */
		STRU_2X2_COM_STATE_RECORD_T PeerUartOKCount[3u];   /**< 邻机串口通信状态计数，2oo2交换 */

	    CM_UINT8  MineInputIoState[10];		/*IO数据同步*/
	    CM_UINT8  PeerInputIoState[10];		/*IO数据同步*/
	    CM_UINT8  RmtMineInputIoState[10];	/*IO数据同步*/
	    CM_UINT8  RmtPeerInputIoState[10];	/*IO数据同步*/

		 /*状态信息*/
		CM_UINT32 LastStateCount;       /**< 上次收到对系状态的时间，2oo2交换 */
		CM_UINT32 RxStateSysCyc;        /**< 收到的状态帧的周期号，2oo2交换 */
		CM_UINT32 RxStateMicroCyc;        /**< 收到的状态帧的周期号，2oo2交换 */

	    /*输入数据*/
	    CM_UINT32 LastRxInputSysCyc;  /**< 收到的对系输入数据的周期号，2oo2交换 */
	    /*跟随数据*/
	    CM_UINT32 LastFollowCyc;      /**< 上次进行平台跟随的时间，2oo2比较，*/
	    CM_UINT32 AppFollowCmpFlag; /**< 上次应用跟随数据比较结果，只有备系使用 (这个标志用来判断备系和主系应用跟随数据是否比较成功, 比较失败则降级)*/

	    /*输出比较信息*/
		CM_UINT32 LastCheckOKCount;     /**< 上次输出比较成功(跟随成功)的本地时间，2oo2比较  (这个标志用来判断如果未收到主系的数据,则停止更新,后将为离线)*/
		CM_UINT32 OutPutCheckFailFlag;     /**< 上次输出比较成功(跟随成功)的本地时间，2oo2比较  (这个标志用来判断收到输出数据后是否比较成功, 比较失败则降级)*/

		/*时间同步完成标志*/
		CM_UINT8 TimeSyncFlag;
	    /*主动切系状态*/
	    ENUM_2x2_SWITCH_STATE  LocalSwitchState; /**< 自己的主动切系按钮状态 */
	    ENUM_2x2_SWITCH_STATE  PeerSwitchState; /**< 邻机的主动切系按钮状态 */
	    ENUM_2x2_SWITCH_STATE  PartnerSwitchState; /**< 对系的主动切系按钮状态 */
	    ENUM_2x2_SWITCH_STATE  PartPeerSwitchState; /**< 对系的邻机的主动切系按钮状态 */
	    CM_UINT8 ctrSwitchFlag; /**< 按钮切系控制标志 */
	    ENUM_2x2_AID_SWITCH_STATE  LocalAIDSwitchState; /**< 自己的AID切系状态 */
	    ENUM_2x2_AID_SWITCH_STATE  PeerAIDSwitchState; /**< 邻机的AID切系状态 */
	    ENUM_2x2_AID_SWITCH_STATE  PartnerAIDSwitchState; /**< 对系的主动切系按钮状态 */
	    ENUM_2x2_AID_SWITCH_STATE  PartPeerAIDSwitchState; /**< 对系的邻机的主动切系按钮状态 */
	    CM_UINT8 aidSwitchFlag; /**< aid切系控制标志 */
		/* 离线是否允许升预升主*/
		CM_BOOL preMasterAllowed;
	}STRU_2X2_STATE_CTRL_T;
	/*2x状态切换线程参数*/
	typedef struct
	{
		CM_SEM_T m_Start;  	 /* 2x状态切换开始信号量 */
		CM_SEM_T m_Stop;   	 /* 2x状态切换结束信号量 */
		CM_MUTEX_T mutex;    /**< 互斥信号量 */
		CM_UINT8  number_Cyc;/*周期次数*/
		CM_MQ_Struct_T LogMsgQ; /**< 日志消息队列 */
	}STRU_2X2_STATE_THRRAD_T;


    extern CM_INT32 g_2x2oo2_base;
    extern CM_INT32 g_2x2oo2_data_num;
    extern STRU_2x2oo2_rx_T g_2x2oo2_rx[2][24];
    extern STRU_2x2oo2_tx_T g_2x2oo2_tx[2][24];
    extern CM_UINT8 g_2x2RcvMaxNum[2];	 /**< 2x2双缓冲区接收最大序号*/

    extern CM_INT32 g_TxAppFollow_len;
    extern CM_UINT8 g_TxAppFollow[MSCP_FOLLOW_BUFF_SIZE*2];

    /*日志转换*/
    void SFM_2x2_LOG_Transition(void);
    /* 2x2上电初始化 */
    void SFM_2x2_Init(IN const CM_UINT8* VitalBuf, IN CM_UINT16 VitalLen, INOUT CM_UINT64* pCycTick);
    /* 输入阶段2x2处理 */
    void SFM_2x2_InputProc(void);
    /* 输出阶段2x2处理 */
    void SFM_2x2_OutputProc(IN const CM_UINT8 *CheckBuf, CM_INT32 CheckLen);
    /* 周期末2x2处理 */
    void SFM_2x2_EndProc(void);
    /* 2x2数据发送 */
    void SFM_2x2_Send(IN const CM_UINT8 *Data, IN CM_UINT32 DataLen, IN ENUM_2x2_MSG_T msgType);
    /**
    * 2x2串口发送
    */
    void SFM_2x2_UartSend(IN const CM_UINT8 *Data, IN CM_UINT32 DataLen, IN ENUM_2x2_MSG_T msgType);

    /* 2x2周期同步 */
    void SFM_2x2_Sync(IN CM_UINT64 cycTick, OUT CM_INT64* pOffset);
	/**
	* @brief 获取本系热备状态
	* @return 本系热备状态
	* - ENUM_2x2_OFFLINE 离线
	* - ENUM_2x2_PRE_MASTER 预升主
	* - ENUM_2x2_MASTER 主系
	* - ENUM_2x2_SLAVE 备系
	* @note
	* 宕机状态下应用逻辑不会被执行，
	* 所以应用本函数不可能返回“宕机”。
	* 其它状态下周期应用逻辑都会被执行，
	* 但只有“主系”状态下本机的输出才会被真实输出，
	* 在“离线”和“备系”状态下且本周期收到有效跟随数据时，
	* 将在周期应用逻辑执行之前进行跟随数据覆盖。
	*/
	ENUM_2x2_STATE_T SFM_2x2_GetLocal2x2State(void);
	/**
	* @brief 获取对系热备状态
	* @return 对系热备状态
	* - ENUM_2x2_SHUTDOWN 宕机
	* - ENUM_2x2_OFFLINE 离线
	* - ENUM_2x2_PRE_MASTER 预升主
	* - ENUM_2x2_MASTER 主系
	* - ENUM_2x2_SLAVE 备系
	* @note
	* 与对系通信中断时默认对系状态为“宕机”
	*/
	ENUM_2x2_STATE_T SFM_2x2_GetPartner2x2State(void);

	/*
	* @brief 获取上一周期的本系热备状态
	* @return 本系热备状态
	* - ENUM_2x2_OFFLINE 离线
	* - ENUM_2x2_PRE_MASTER 预升主
	* - ENUM_2x2_MASTER 主系
	* - ENUM_2x2_SLAVE 备系
	* @note
	* 宕机状态下应用逻辑不会被执行，
	* 所以应用本函数不可能返回“宕机”。
	* 其它状态下周期应用逻辑都会被执行，
	* 但只有“主系”状态下本机的输出才会被真实输出，
	* 在“离线”和“备系”状态下且本周期收到有效跟随数据时，
	* 将在周期应用逻辑执行之前进行跟随数据覆盖。
	*/
	ENUM_2x2_STATE_T SFM_2x2_GetLastLocal2x2State(void);
	/**
	* @brief 获取对系上一周期的热备状态
	* @return 对系热备状态
	* - ENUM_2x2_SHUTDOWN 宕机
	* - ENUM_2x2_OFFLINE 离线
	* - ENUM_2x2_PRE_MASTER 预升主
	* - ENUM_2x2_MASTER 主系
	* - ENUM_2x2_SLAVE 备系
	* @note
	* 与对系通信中断时默认对系状态为“宕机”
	*/
	ENUM_2x2_STATE_T SFM_2x2_GetLastPartner2x2State(void);

	/**
	* @brief 设置跟随数据
	* @param[in] Data[] 跟随数据数组
	* @param[in] Len 跟随数据长度
	* @return 函数执行结果
	* - 1 成功
	* - 0 失败(输入非法)
	* @note
	* 无论本系是否为主，应用都应当每周期设置一次跟随数据；
	* 本系非主时平台不会发送该数据，但会用于双系一致性的校验。
	* 跟随数据量最大为1024*1000字节。
	* @see :: APP_API_FollowUp
	*/
	CM_UINT8 SFM_2x2_SetFollowData(IN const CM_UINT8 Data[], IN CM_UINT32 Len);
	/**
	* @brief 获取系统周期号
	* @return 当前的系统周期号
	* @note
	* 一个固定周期自增的周期号；
	* 对于2x2系统，2x2双系的周期号会被自动同步到与主系一致。
	*/
	CM_UINT32 SFM_2x2_GetSysCount(void);
	/**
    * @brief 获取通信断开次数通用函数
    * @param ComOKCountBuf 更新状态通信ok次数数组
    * @param BeforeCycNum 查询前几个周期序号，例如：0代表本周期，
    * @return 通信断开的次数
    * @details
    * 可向前查询通信正常次数周期号
    */
	CM_UINT32 MSCP_Get_2X_DisCom_Count(STRU_2X2_COM_STATE_RECORD_T *ComOKCount,CM_UINT8 BeforeCycNum);
    /**
    * @brief 获取通信状态
    * @param ComOKCountBuf 更新状态通信ok次数数组
    * @param BeforeCycNum 查询前几个周期序号，例如：0代表本周期，
    * @return ENUM_CM_TRUE = 0x55 成功
    		  ENUM_CM_FALSE = 0xAA 失败
    * @details
    *可向前查询通信状态
    */
	ENUM_CM_RETURN MSCP_Get_2X_Com_State(STRU_2X2_COM_STATE_RECORD_T *ComOKCount,CM_UINT8 BeforeCycNum);
	/**
	* @brief 获取模糊通信状态
	* @param ComOKCountBuf 更新状态通信ok次数数组
	* @return CM_TRUE 成功
			  CM_FALSE 失败
	*/
	CM_BOOL MSCP_Get_2X_VagueCom_State(STRU_2X2_COM_STATE_RECORD_T *ComOKCount);
    /**
    * @brief 更新本周期通信状态通用函数
    * @param ComOKCountBuf 更新状态通信ok次数数组
    * @param ComOKCount 通信OK次数
    * @return 无
    * @details
    * 更新本周期通信状态，将历史状态信息移位保存
    */
    void MSCP_UpData_2X_This_ComState(STRU_2X2_COM_STATE_RECORD_T *ComOKCount,CM_UINT32 SysCyc,CM_UINT8 MicroCyc);

    /**
    * @brief 获取本系切系按钮状态
    * @return 本系切系按钮状态
    * - ENUM_2x2_SWITCH_CLOSE = 0 未连续按下
    * - ENUM_2x2_SWITCH_OPEN = 1 连续按下
    */
    ENUM_2x2_SWITCH_STATE SFM_2x2_GetLocalSwitchState(void);

    /**
    * @brief 设置本系切系按钮状态
    * @param switchState 设置的值
    * @return 无
    */
    void SFM_2x2_SettLocalSwitchState(ENUM_2x2_SWITCH_STATE switchState);

    /**
    * @brief 获得是否为在因为切系后,主系降为离线的3周期内的标志。
    * @return 是否为切系后的3周期
    * - 0 不在切系后的3周期内
    * - 1 在切系后的3周期内
    */
    CM_UINT8 SFM_2x2_GetSwitchFlag(void);

    /* 设置本系热备状态 */
    void SFM_2x2_SetLocal2x2State(ENUM_2x2_STATE_T localState);

    /**
    * @brief 获取2x切系标志位
    * @return s_2x2_Ctrl.ctrSwitchFlag 切系标志位  取值范围：1正在切系 0不在切系
    */
    CM_UINT8 SFM_2x2_GetCtrSwitchFlag(void);

    /*判断当前周期是否与对系通信中断，中断返回1，正常返回0*/
    CM_UINT8 SFM_2x2_GetWithPeer_Com_State(void);
    /*判断当前周期是否与对系通信中断,间接判断交换机状态*/
    CM_UINT8 SFM_2x2_GetWithESB_Mine_Com_State(void);
    /*判断当前周期是否与对系通信中断,间接判断交换机状态*/
    CM_UINT8 SFM_2x2_GetWithESB_Peer_Com_State(void);
    /*判断当前是否满足至少一个以太网和任一通道的条件*/
    CM_UINT8 SFM_2x2_Get_LeastDoubleCom_State(void);
    /*主线程同步到应用的两系输入io状态*/
    ENUM_CM_RETURN SFM_2x2_SyncIoInput(OUT CM_UINT8* ioInput,CM_UINT16 size);
    /*获取两系输入io状态*/
    ENUM_CM_RETURN SFM_2x2_GetLastIoInput(OUT CM_UINT8* ioInput,CM_UINT16 size);
    /*发送2x起始信号*/
    void SFM_2x2_Thread_PostStart(void);
    /*使能AID切系开关*/
    void SFM_2x2_Enable_AIDSwitchStart(void);
    /*获取AID切系状态*/
    ENUM_2x2_AID_SWITCH_STATE SFM_2x2_Get_AIDSwitchStart(void);
    /*输出处理与发送阶段之前的等待2x逻辑结束的最后处理函数*/
    void SFM_2x2_ChangeState(void);
    /*时间同步失败清空消息队列*/
    void SFM_2x2_ClearRcvMsgQ(void);

    void SFM_2x2_SemPost(void);
#ifdef __cplusplus
}
#endif

#endif
