#include "Arb.h"
#include "Arb_Net.h"
#include "Arb_Pack.h"
#include "DFM_Time.h"
#include "CM_Memory.h"
#include "CM_CRC32.h"
#include "Area_2oo2.h"
#include "Arb_State.h"
#include "CFM_Sync.h"
#include "Arb_State_Vote.h"
#include "CM_Convert.h"
/*===========↓↓↓↓↓全局变量声明&定义↓↓↓↓↓=============*/

static CM_UINT64 s_area_arb_start_time = 0u;
STRU_AREA_WITH_ARB_CFG_ALL_T g_area_with_arb_cfg = {0}; /**区域控制信息汇总 */
/*===========↑↑↑↑↑全局变量声明&定义↑↑↑↑↑=============*/

/*===========↓↓↓↓↓宏定义↓↓↓↓↓=============*/

#define AREA_ARB_NOW_USED_TIME ((CM_GetTick() - s_area_arb_start_time) / CM_UNSIGNED_MILLION) /**记录区域线程耗时 */
#define AREA_STATE_WAITE_TIME (30u - 7u) /**区域状态请求/应答接收超时时间，30ms减去一次2取耗时 */
#define AREA_ARB_WAITE_TIME (20u) /**仲裁应答时间 */
#define AREA_MULTI_WAITE_TIME (10u) /**组播等待时间 */
/*===========↑↑↑↑↑宏定义↑↑↑↑↑=============*/

/*===========↓↓↓↓↓静态函数声明↓↓↓↓↓=============*/

/**
 * @brief 根据已打包的线路报文计算并同步双CRC
 */
static void s_Area_DoubleCRC_Get(IN const CM_UINT8* buf, IN CM_UINT32 len,
    OUT CM_UINT32* crc1, OUT CM_UINT32* crc2);
/**
 * @brief 地间状态帧组包、计算CRC并发送
 */
static ENUM_CM_RETURN s_Area_State_Pack_Send(INOUT STRU_AREA_WITH_ARB_STATE_PACK_T* state_pack);
/**
 * @brief 区域工作线程(带仲裁)
 */
static CM_THREAD_FUNC_T s_Area_With_Arb_Work_Thread(IN CM_Thread_Arg_Struct_T* arg);
/**
 * @brief 组播发送状态数据的处理
 */
static void s_Area_State_Multi_Process(void);
/**
 * @brief 区域状态的请求发送处理
 */
static void s_Area_State_Req_Send_Process(void);
/**
 * @brief 区域状态请求ACK的处理
 */
static void s_Area_State_Ack_Process(void);
/**
 * @brief 处理校验通过的状态请求帧
 */
static void s_Area_State_Req_Recv_Process(IN const STRU_AREA_WITH_ARB_STATE_PACK_T* state_pack,
    INOUT CM_BOOL ack_flags[5]);
/**
 * @brief 处理校验通过的状态ACK帧
 */
static void s_Area_State_Ack_Recv_Process(IN const STRU_AREA_WITH_ARB_STATE_PACK_T* state_pack,
    IN CM_UINT32 local_sn);
/**
 * @brief 仲裁处理
 */
static void s_Area_Arb_Process(void);
/**
 * @brief 仲裁请求发送处理
 */
static void s_Area_Arb_Send_Process(void);
/**
 * @brief 仲裁请求接收处理
 */
static void s_Area_Arb_Recv_Process(void);
/**
 * @brief 状态转移处理
 */
static void s_Area_Arb_State_Transition(void);
/**
 * @brief 主地主的组播发送状态数据处理
 */
static void s_Area_State_Multi_Send_Process(void);
/**
 * @brief 非主地主接收组播状态数据处理
 */
static void s_Area_State_Multi_Recv_Process(void);
/**
 * @brief 周期运行中的初始化，初始化接收状态和其他板卡状态
 */
static void s_Area_Cycle_Init(void);
/**
 * @brief 对接收到的区域状态请求进行2取同步
 * @param ack_flags 记录是否需要进行ACK回复
 * @param time 记录当前所用时间，2取后双CPU同时退出循环
 * @return 2取另一CPU所用时间
 */
static CM_UINT32 s_Area_2oo2Sync_AfterStateRecv(CM_BOOL ack_flags[5], CM_UINT32 time);
/**
 * @brief 2取同步后，判断本周期是否收到请求，并进行回复组包发送
 * @param ack_partner 是否需要向对系回复ACK
 * @param ack_area_a 是否需要向另一地A系回复ACK
 * @param ack_area_b 是否需要向另一地B系回复ACK
 */
static void s_Area_SendACK_After2oo2(CM_BOOL ack_partner, CM_BOOL ack_area_a, CM_BOOL ack_area_b);
/**
 * @brief 对接收到的仲裁应答进行2取同步
 */
static void s_Area_2oo2Sync_AfterArbRecv();
/*===========↑↑↑↑↑静态函数声明↑↑↑↑↑=============*/


/*===========↓↓↓↓↓函数定义↓↓↓↓↓↓=============*/


/**
 * 区域初始化，包含第三方仲裁的初始化
 */
void Area_With_Arb_Init(void)
{
    /**日志队列初始化 */
    Area_LogMQ_Init();
    AREA_BASIC_CFG_PTR->BoardID = g_PFM_Cfg.BOARD_ID;/**<  板卡ID 插箱id */
    AREA_BASIC_CFG_PTR->Cpuid = g_PFM_Cfg.CPU_ID;/**<  cpu id */
    AREA_BASIC_CFG_PTR->OutnetID = g_PFM_Cfg.OUTNET_ID;/**< 外网ID */
    /* 获取对系、对地板卡id*/
    get_Other_BoardId(AREA_BASIC_CFG_PTR->BoardID, &(AREA_BASIC_CFG_PTR->Partner_BoardID), &(AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID), &(AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID));
    /**获取自身所在地（A地/B地） */
    if((MSCP_AREA_A_BOARD_ID_A == AREA_BASIC_CFG_PTR->BoardID ) || (MSCP_AREA_A_BOARD_ID_B == AREA_BASIC_CFG_PTR->BoardID ))
    {
    	AREA_BASIC_CFG_PTR->AreaID = MSCP_AREA_ID_A;
    }
    else
    {
        AREA_BASIC_CFG_PTR->AreaID = MSCP_AREA_ID_B;
    }
    AREA_LOG_MSG("AREA_ARB:Init config, BoardID:%d CPU:%d OUTNET_ID:%d Area:%d Partner:%d Remote:%d-%d\n",
        AREA_BASIC_CFG_PTR->BoardID, AREA_BASIC_CFG_PTR->Cpuid, AREA_BASIC_CFG_PTR->OutnetID, AREA_BASIC_CFG_PTR->AreaID,
        AREA_BASIC_CFG_PTR->Partner_BoardID, AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID,
        AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID);
    /* 网络初始化*/
    Area_Arb_Net_Init();
    /*信号量初始化*/
    CM_Sem_Init(&(AREA_THREAD_CTRL_PTR->m_AreaWithArbStart));
    CM_Sem_Init(&(AREA_THREAD_CTRL_PTR->m_AreaWithArbStop));

    /**初始化板卡状态 */
    AREA_STATE_CTRL_PTR->StateArea.Local_state = ENUM_AREA_UNKNOW;
    AREA_LOG_MSG("AREA_STATE:Init local state, BoardID:%d Area:%d State:%d\n",
        AREA_BASIC_CFG_PTR->BoardID, AREA_BASIC_CFG_PTR->AreaID,
        AREA_STATE_CTRL_PTR->StateArea.Local_state);
    s_Area_Cycle_Init();

    /**创建区域工作线程 */
    CM_Thread_Create(NULL, (CM_THREAD_FUNC_T)s_Area_With_Arb_Work_Thread, "Area_With_Arb_Work_Thread", 0, CM_TASK_PRIORITY_73, NULL);
}

/**
 * @brief 区域工作线程(带仲裁)
 */
static CM_THREAD_FUNC_T s_Area_With_Arb_Work_Thread(IN CM_Thread_Arg_Struct_T* arg)
{
    /* 绑定内核 */
    void* pmask = NULL;
    CM_UINT64 stage_start = 0u;
    pmask = (void*)(0x01u|0x02u);
    (void)ThreadCtl(_NTO_TCTL_RUNMASK, pmask);
    /* 清空缓冲区 */
    Area_Arb_ClearMsgQ();
    /* 线程循环 */
    while(1)
    {
        Area_Arb_Wait_Start();
        s_area_arb_start_time = CM_GetTick();
        /**清空上周期的接收状态,并获取2乘线程中的最终状态 */
        s_Area_Cycle_Init();
        AREA_LOG_MSG("AREA_ARB:Cycle start, BoardID:%d SN:%u State:%d 2x2:%d, NOW_USED_TIME:%llums\n",
            AREA_BASIC_CFG_PTR->BoardID, DFM_GetBirthCount(),
            AREA_STATE_CTRL_PTR->StateArea.Local_state,
            AREA_STATE_CTRL_PTR->State2x.LocalState,NOW_USED_TIME / 1000u);
        /**主地主组播发送状态帧，其余板卡接收 */
        stage_start = CM_GetTick();
        s_Area_State_Multi_Process();
        AREA_LOG_MSG("AREA_ARB:State multicast stage cost:%llums, AREA_ARB_NOW_USED_TIME:%llums\n",
            (CM_GetTick() - stage_start) / CM_UNSIGNED_MILLION, AREA_ARB_NOW_USED_TIME);
        /**主地双系/初始化阶段发送状态请求帧 */
        stage_start = CM_GetTick();
        s_Area_State_Req_Send_Process();
        AREA_LOG_MSG("AREA_ARB:State request send stage cost:%llums, AREA_ARB_NOW_USED_TIME:%llums\n",
            (CM_GetTick() - stage_start) / CM_UNSIGNED_MILLION, AREA_ARB_NOW_USED_TIME);
        /**对应答帧的处理 */
        stage_start = CM_GetTick();
        s_Area_State_Ack_Process();
        AREA_LOG_MSG("AREA_ARB:State request/ACK stage cost:%llums, AREA_ARB_NOW_USED_TIME:%llums\n",
            (CM_GetTick() - stage_start) / CM_UNSIGNED_MILLION, AREA_ARB_NOW_USED_TIME);
        /**仲裁请求发送/接收的处理 */
        stage_start = CM_GetTick();
        s_Area_Arb_Process();
        AREA_LOG_MSG("AREA_ARB:Arbitration request/ACK stage cost:%llums, AREA_ARB_NOW_USED_TIME:%llums\n",
            (CM_GetTick() - stage_start) / CM_UNSIGNED_MILLION, AREA_ARB_NOW_USED_TIME);
        /**状态转移 */
        s_Area_Arb_State_Transition();

        AREA_LOG_MSG("AREA_ARB:Cycle end, SN:%u State:%d 2x2:%d RcvFlag:%d-%d-%d Arb:%d-0x%x, AREA_ARB_USED_TIME:%llums, NOW_USED_TIME:%llums\n",
            AREA_COMM_STATUS_PTR->LocalSN, AREA_STATE_CTRL_PTR->StateArea.Local_state,
            AREA_STATE_CTRL_PTR->State2x.LocalState,
            AREA_COMM_STATUS_PTR->Patner_RcvFlag, AREA_COMM_STATUS_PTR->Area_A_RcvFlag,
            AREA_COMM_STATUS_PTR->Area_B_RcvFlag, AREA_ARB_CTRL_PTR->Arb_Send_Flag,
            AREA_ARB_CTRL_PTR->Arb_Ack, AREA_ARB_NOW_USED_TIME, NOW_USED_TIME / 1000u);

        Area_Arb_Stop();
    }
    return NULL;
}
/**
 * @brief 区域开始
 * 
 */
void Area_Arb_Start()
{
    /** 区域开始信号量 */
    CM_Sem_Post(AREA_THREAD_CTRL_PTR->m_AreaWithArbStart);
    AREA_LOG_MSG("*** Area Arb thread start \n");
}
/**
 * @brief 等待区域开始
 * 
 */
void Area_Arb_Wait_Start()
{
    /** 区域开始信号量 */
    CM_Sem_Wait(AREA_THREAD_CTRL_PTR->m_AreaWithArbStart);
}

/**
 * @brief 区域停止
 * 
 */
void Area_Arb_Stop()
{
    /** 区域停止信号量 */
    CM_Sem_Post(AREA_THREAD_CTRL_PTR->m_AreaWithArbStop);
}
/**
 * @brief 等待区域停止
 * 
 */
void Area_Arb_Wait_Stop()
{
    /** 区域停止信号量 */
    CM_Sem_Wait(AREA_THREAD_CTRL_PTR->m_AreaWithArbStop);
}
/**
 * @brief 组播发送状态数据的处理
 */
static void s_Area_State_Multi_Process(void)
{
    if(ENUM_AREA_MASTER == AREA_STATE_CTRL_PTR->StateArea.Local_state &&
        ENUM_2x2_MASTER == AREA_STATE_CTRL_PTR->State2x.LocalState)
    {
        /**主地主组播发送状态数据 */
        s_Area_State_Multi_Send_Process();
        CM_Sleep(10u);/*组播发送后等待10ms*/
    }
    else
    {
        /**非主地主接收组播状态数据 */
        s_Area_State_Multi_Recv_Process();
    }

}
/**
 * @brief 区域状态的请求发送处理
 */
static void s_Area_State_Req_Send_Process(void)
{
    STRU_AREA_WITH_ARB_STATE_PACK_T state_pack = {0};
    ENUM_CM_RETURN send_rt = ENUM_CM_FALSE;
    /**发送帧初始化 */
    state_pack.Len = AREA_ARB_STATE_PACK_LEN - 1u;
    state_pack.MsgType = ENUM_AREA_MSG_STATE_REQ;
    state_pack.SN = DFM_GetBirthCount();
    state_pack.TimeSyncFlag = 1u; /**请求中的该字段不使用 */
    state_pack.SrcID = AREA_BASIC_CFG_PTR->BoardID;
    state_pack.StateArea = AREA_STATE_CTRL_PTR->StateArea.Local_state;
    state_pack.State2x = AREA_STATE_CTRL_PTR->State2x.LocalState;
    CM_Memset(&state_pack.Reserver[0], 0, AREA_ARB_RESERVER_LEN, AREA_ARB_RESERVER_LEN);
    AREA_COMM_STATUS_PTR->LocalSN = DFM_GetBirthCount();
    /**判断需要发送至哪一系 */
    if(MSCP_AREA_ID_A == AREA_BASIC_CFG_PTR->AreaID && 
        ENUM_AREA_UNKNOW == AREA_STATE_CTRL_PTR->StateArea.Local_state &&
        ENUM_2x2_MASTER == AREA_STATE_CTRL_PTR->State2x.LocalState)
    {
        /**未知地主系（仅A地），刚上电，向其他三系发送请求 */
        /**发送至本地另一系 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_BoardID;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State request send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt);
        
        /**发送至另一地的A系 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State request send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt);

        /**发送至另一地的B系 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State request send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt);
    }
    else if(ENUM_AREA_MASTER == AREA_STATE_CTRL_PTR->StateArea.Local_state && 
        ((ENUM_2x2_MASTER == AREA_STATE_CTRL_PTR->State2x.LocalState) || (ENUM_2x2_SLAVE == AREA_STATE_CTRL_PTR->State2x.LocalState)))
    {
        /**主地主备系，周期运行阶段，向另一地发送请求 */
        /**发送至另一地的A系 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State request send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt);

        /**发送至另一地的B系 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State request send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt);
    }
    else
    {

    }
}
/**
 * @brief 区域状态请求ACK的处理
 */
static void s_Area_State_Ack_Process(void)
{
    STRU_AREA_WITH_ARB_STATE_PACK_T state_pack = {0};
    CM_UINT8 wire_buf[AREA_ARB_STATE_PACK_LEN] = {0};
    CM_INT32 rcv_len = 0;
    CM_UINT32 crc1 = 0u, crc2 = 0u;
    CM_UINT32 timeStamp = 0u, timeNow = 0u;
    CM_UINT32 start_tick = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION);
    CM_UINT32 used_time = 0u;
    CM_UINT32 localsn = AREA_COMM_STATUS_PTR->LocalSN;
    CM_UINT8 srcID = 0u;
    CM_UINT8 partner_id = AREA_BASIC_CFG_PTR->Partner_BoardID;
    CM_UINT8 area_a_id = AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID;
    CM_UINT8 area_b_id = AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID;
    CM_UINT8 timeSyncFlag = AREA_FLAGS_CTRL_PTR->Time_Sync_Flag;
    CM_BOOL ack_flags[5] = {CM_FALSE, CM_FALSE, CM_FALSE, CM_FALSE, CM_FALSE};
    CM_UINT32 peer_time = 0u;

    CM_UINT32 i = 0u;
    /**持续30ms */
    do
    {
        /**REQ与ACK共用一个FIFO，每条报文只读取一次并按类型分发。 */
        do
        {
            rcv_len = Area_State_Recv(wire_buf, sizeof(wire_buf), &timeStamp);
            timeNow = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION);
            if((AREA_ARB_STATE_PACK_LEN == rcv_len) &&
                ((timeNow - timeStamp) < g_PFM_Cfg.CYC_TIME))
            {
                Area_Arb_State_UnPack(&state_pack, wire_buf, (CM_UINT32)rcv_len);
                crc1 = CM_Crc32_1(&wire_buf[1], (CM_UINT32)rcv_len - 9u);
                crc2 = CM_Crc32_2(&wire_buf[1], (CM_UINT32)rcv_len - 9u);
                srcID = state_pack.SrcID;

                if((crc1 == state_pack.CRC1) && (crc2 == state_pack.CRC2) &&
                    ((AREA_ARB_STATE_PACK_LEN - 1u) == state_pack.Len) &&
                    (state_pack.DstID == AREA_BASIC_CFG_PTR->BoardID))
                {
                    if(ENUM_AREA_MSG_STATE_REQ == state_pack.MsgType)
                    {
                        s_Area_State_Req_Recv_Process(&state_pack, ack_flags);
                    }
                    else if(ENUM_AREA_MSG_STATE_ACK == state_pack.MsgType)
                    {
                        s_Area_State_Ack_Recv_Process(&state_pack, localsn);
                    }
                    else
                    {
                        /**消息类型或序列号不符合当前周期，不更新状态。 */
                    }
                }
            }
        } while(0 < rcv_len);

        /**同步接收状态和本周期ACK目标，再统一回复。 */
        used_time = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION) - start_tick;
        peer_time = s_Area_2oo2Sync_AfterStateRecv(ack_flags, used_time);
        s_Area_SendACK_After2oo2(ack_flags[partner_id], ack_flags[area_a_id], ack_flags[area_b_id]);
        CM_Memset(ack_flags, 0, sizeof(ack_flags), sizeof(ack_flags));

        CM_Sleep(1u);
    }while(AREA_STATE_WAITE_TIME > peer_time && AREA_STATE_WAITE_TIME > used_time);
}

static void s_Area_State_Req_Recv_Process(IN const STRU_AREA_WITH_ARB_STATE_PACK_T* state_pack,
    INOUT CM_BOOL ack_flags[5])
{
    CM_UINT32 last_sn = 0u;

    if((NULL == state_pack) || (NULL == ack_flags))
    {
        return;
    }

    AreaArb_GetCommStatus_byID(state_pack->SrcID, &last_sn, NULL);
    if(state_pack->SN > last_sn)
    {
        ack_flags[state_pack->SrcID] = CM_TRUE;
        AreaArb_SetCommStatus_byID(state_pack->SrcID, state_pack->SN, CM_TRUE);
        AreaArb_SetState_byID(state_pack->SrcID, state_pack->StateArea);
        AreaArb_Set2xState_byID(state_pack->SrcID, state_pack->State2x);
        AREA_LOG_MSG("AREA_ARB:State request received, SrcID:%d SN:%u State:%d 2x2:%d, AREA_ARB_NOW_USED_TIME:%llums\n",
            state_pack->SrcID, state_pack->SN, state_pack->StateArea, state_pack->State2x, AREA_ARB_NOW_USED_TIME);
    }
}

static void s_Area_State_Ack_Recv_Process(IN const STRU_AREA_WITH_ARB_STATE_PACK_T* state_pack,
    IN CM_UINT32 local_sn)
{
    CM_UINT32 sn_diff = 0u;

    if(NULL == state_pack)
    {
        return;
    }

    CM_UINT8 time_sync_flag = state_pack->TimeSyncFlag;

    sn_diff = (local_sn >= state_pack->SN) ?
        (local_sn - state_pack->SN) : (state_pack->SN - local_sn);
    if(((1u == time_sync_flag) && (state_pack->SN == local_sn)) ||
        ((0u == time_sync_flag) && (sn_diff <= 1u)))
    {
        AreaArb_SetCommStatus_byID(state_pack->SrcID, state_pack->SN, CM_TRUE);
        AreaArb_SetState_byID(state_pack->SrcID, state_pack->StateArea);
        AreaArb_Set2xState_byID(state_pack->SrcID, state_pack->State2x);
        AREA_LOG_MSG("AREA_ARB:State ACK received, SrcID:%d SN:%u State:%d 2x2:%d, AREA_ARB_NOW_USED_TIME:%llums\n",
            state_pack->SrcID, state_pack->SN, state_pack->StateArea, state_pack->State2x, AREA_ARB_NOW_USED_TIME);
    }
    else
    {
        AREA_LOG_MSG("AREA_ARB:State ACK recv failed, SrcID:%d SN:%u State:%d 2x2:%d, AREA_ARB_NOW_USED_TIME:%llums\n",
            state_pack->SrcID, state_pack->SN, state_pack->StateArea, state_pack->State2x, AREA_ARB_NOW_USED_TIME);        
    }
}

/**
 * @brief 仲裁处理
 */
static void s_Area_Arb_Process(void)
{
    s_Area_Arb_Send_Process();
    /**等待20ms仲裁回复 */
    s_Area_Arb_Recv_Process();
}
/**
 * @brief 仲裁请求发送处理
 */
static void s_Area_Arb_Send_Process(void)
{
    STRU_AREA_WITH_ARB_PACK_T arb_pack = {0};
    CM_UINT32 tmp_len = 0u;
    CM_UINT8 tmp_buf[1400] = {0u};
    ENUM_AREA_STATE local_area_state = AREA_STATE_CTRL_PTR->StateArea.Local_state;
    static CM_UINT32 tolerate_arb = 0u; /**仲裁请求容忍 */
    ENUM_CM_RETURN send_rt = ENUM_CM_FALSE;
    CM_BOOL flag_comm_mm_status = CM_FALSE;
    /**请求帧帧基础信息组包 */
    arb_pack.Len = AREA_ARB_FRAME_PACK_LEN - 1u;
    arb_pack.MsgType = ENUM_AREA_MSG_ARB_REQ;
    arb_pack.ArbSN = DFM_GetBirthCount();
    arb_pack.OutNet_ID = AREA_BASIC_CFG_PTR->OutnetID;
    arb_pack.Board_ID = AREA_BASIC_CFG_PTR->BoardID;
    arb_pack.CPU_ID = AREA_BASIC_CFG_PTR->Cpuid;
    arb_pack.ArbPayLoad = 0x55u;    /**请求升主 */
    CM_Memset(&arb_pack.Reserver[0], 0, AREA_ARB_RESERVER_LEN, AREA_ARB_RESERVER_LEN);
    /**计算双CRC */
    tmp_len = Area_Arb_Frame_Pack(tmp_buf, sizeof(tmp_buf), &arb_pack);
    CM_ASSERT(AREA_ARB_FRAME_PACK_LEN == tmp_len, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
    s_Area_DoubleCRC_Get(tmp_buf, tmp_len, &arb_pack.CRC1, &arb_pack.CRC2);
    tmp_len = Area_Arb_Frame_Pack(tmp_buf, sizeof(tmp_buf), &arb_pack);
    CM_ASSERT(AREA_ARB_FRAME_PACK_LEN == tmp_len, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
    /**获取对应状态的板卡ID */
    CM_UINT8 id_sm = AreaArb_GetID_byState(ENUM_AREA_SLAVE, ENUM_2x2_MASTER); /**备地主的板卡ID */
    CM_UINT8 id_mm = AreaArb_GetID_byState(ENUM_AREA_MASTER, ENUM_2x2_MASTER); /**主地主的板卡ID */
    /**获取通信中断标志 */
    CM_BOOL flag_comm_all_down = AREA_COMM_STATUS_PTR->Area_A_RcvFlag | AREA_COMM_STATUS_PTR->Area_B_RcvFlag;  /**用于判断通信是否完全中断 */
    CM_BOOL flag_comm_all_up   = AREA_COMM_STATUS_PTR->Area_A_RcvFlag & AREA_COMM_STATUS_PTR->Area_B_RcvFlag;  /**用于判断通信是否完全正常 */
    /**获取主地主通信状态标志 */
    AreaArb_GetCommStatus_byID(id_mm, NULL, &flag_comm_mm_status);
    /**重置仲裁请求发送标志 */
    AREA_ARB_CTRL_PTR->Arb_Send_Flag = 0u;

    /**判断是否发送仲裁请求 */
    if(ENUM_2x2_MASTER == AREA_STATE_CTRL_PTR->State2x.LocalState)
    {
        /**主系判断是否发送仲裁请求 */
        if(ENUM_AREA_MASTER == local_area_state && 0u == id_sm && CM_FALSE == flag_comm_all_up)
        {
            /**本地主地主，与备地通信存在异常，发送仲裁请求 */
            AREA_ARB_CTRL_PTR->Arb_Send_Flag = 1u;
            send_rt = Area_Arb_Req_Send(tmp_buf, tmp_len);
            AREA_LOG_MSG("AREA_ARB:Request arbitration, master lost slave, BoardID:%d SN:%u Result:0x%x\n",
                AREA_BASIC_CFG_PTR->BoardID, arb_pack.ArbSN, send_rt);
        }
        else if(ENUM_AREA_SLAVE == local_area_state && CM_FALSE == flag_comm_mm_status)
        {
            /**本地备地主，与主地主通信中断，容忍一周期发送请求 */
            if(tolerate_arb >= 1u)
            {
                AREA_ARB_CTRL_PTR->Arb_Send_Flag = 1u;
                send_rt = Area_Arb_Req_Send(tmp_buf, tmp_len);
                AREA_LOG_MSG("AREA_ARB:Request arbitration, slave lost master, BoardID:%d SN:%u Result:0x%x\n",
                    AREA_BASIC_CFG_PTR->BoardID, arb_pack.ArbSN, send_rt);
                tolerate_arb = 0u;
            }
            else
            {
                tolerate_arb++;
            }
        }
        else if(ENUM_AREA_UNKNOW == local_area_state && CM_FALSE == flag_comm_all_up)
        {
            /**未知地主系，与另一地通信持续中断10周期，发送仲裁请求 */
            if(tolerate_arb >= 10u)
            {
                AREA_ARB_CTRL_PTR->Arb_Send_Flag = 1u;
                send_rt = Area_Arb_Req_Send(tmp_buf, tmp_len);
                AREA_LOG_MSG("AREA_ARB:Request arbitration, all area links down, BoardID:%d SN:%u Result:0x%x\n",
                    AREA_BASIC_CFG_PTR->BoardID, arb_pack.ArbSN, send_rt);
                tolerate_arb = 0u;
            }
            else
            {
                tolerate_arb++;
            }
        }
        else
        {
            /**不具备发送仲裁请求的条件，清空容忍次数 */
            tolerate_arb = 0u;
        }

    }
    else
    {
        /**非主系不能要仲裁 */
    }
}
/**
 * @brief 仲裁请求接收处理
 */
static void s_Area_Arb_Recv_Process(void)
{
    STRU_AREA_WITH_ARB_PACK_T arb_pack = {0};
    CM_INT32 rcv_len = 0;
    CM_UINT8 tmp_buf[AREA_ARB_FRAME_PACK_LEN] = {0};
    CM_UINT32 crc1 = 0u, crc2 = 0u;
    CM_UINT32 local_sn = DFM_GetBirthCount();
    CM_UINT16 local_outnetid = AREA_BASIC_CFG_PTR->OutnetID;
    CM_UINT8 local_id = AREA_BASIC_CFG_PTR->BoardID;
    CM_UINT8 cpu_id = AREA_BASIC_CFG_PTR->Cpuid;
    CM_UINT32 tick_now = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION);
    CM_UINT32 tick_start = tick_now, used_time = 0u;
    /**清空仲裁状态 */
    AREA_ARB_CTRL_PTR->Arb_Ack = 0x00u;
    /**持续20ms循环接收仲裁应答 */
    do
    {
        rcv_len = Area_Arb_Ack_Recv(tmp_buf, sizeof(tmp_buf));
        /**解包处理 */
        if(AREA_ARB_FRAME_PACK_LEN == rcv_len)
        {
            Area_Arb_Frame_UnPack(&arb_pack, tmp_buf, (CM_UINT32)rcv_len);
            crc1 = CM_Crc32_1(&tmp_buf[1], (CM_UINT32)rcv_len - 9u);
            crc2 = CM_Crc32_2(&tmp_buf[1], (CM_UINT32)rcv_len - 9u);
            if(crc1 == arb_pack.CRC1 && crc2 == arb_pack.CRC2 &&
                ((AREA_ARB_FRAME_PACK_LEN - 1u) == arb_pack.Len) &&
                local_sn == arb_pack.ArbSN && ENUM_AREA_MSG_ARB_ACK == arb_pack.MsgType &&
                local_outnetid == arb_pack.OutNet_ID && local_id == arb_pack.Board_ID &&
                cpu_id == arb_pack.CPU_ID)
            {
                if(0x55 == arb_pack.ArbPayLoad)
                {
                    /**允许升主 */
                    AREA_ARB_CTRL_PTR->Arb_Ack = 0x55u;
                    AREA_LOG_MSG("AREA_ARB:Arbitration ACK accepted, BoardID:%d SN:%d Payload:0x%x\n",
                        local_id, arb_pack.ArbSN, arb_pack.ArbPayLoad);
                }
            }
            else
            {
                AREA_LOG_MSG("AREA_ARB:Invalid arbitration ACK, BoardID:%d SN:%d CRC:%08x-%08x/%08x-%08x\n",
                    arb_pack.Board_ID, arb_pack.ArbSN, crc1, arb_pack.CRC1, crc2, arb_pack.CRC2);
            }
        }
        else
        {
            CM_Sleep(1u);
        }
        tick_now = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION);
        used_time = tick_now - tick_start;
    } while(AREA_ARB_WAITE_TIME > used_time);

    s_Area_2oo2Sync_AfterArbRecv();
}
/**
 * @brief 状态转移处理
 */
static void s_Area_Arb_State_Transition(void)
{
    ENUM_AREA_STATE old_state = AREA_STATE_CTRL_PTR->StateArea.Local_state;

    if(1u == AREA_ARB_CTRL_PTR->Arb_Send_Flag && 0x00u == AREA_ARB_CTRL_PTR->Arb_Ack)
    {
        /**发送了仲裁请求但未收到应答，直接宕机 */
        AREA_LOG_MSG("AREA_ARB:Arbitration request timed out, BoardID:%d State:%d\n",
            AREA_BASIC_CFG_PTR->BoardID, old_state);
        CM_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
    }
    else
    {
        /**进行状态转换 */
        Area_With_Arb_State_Vote();
        if(old_state != AREA_STATE_CTRL_PTR->StateArea.Local_state)
        {
            AREA_LOG_MSG("AREA_STATE:Local transition, BoardID:%d %d>>>>>%d ArbAck:0x%x\n",
                AREA_BASIC_CFG_PTR->BoardID, old_state,
                AREA_STATE_CTRL_PTR->StateArea.Local_state, AREA_ARB_CTRL_PTR->Arb_Ack);
        }
    }
}
/**
 * @brief 主地主的组播发送状态数据处理
 */
static void s_Area_State_Multi_Send_Process(void)
{
    CM_UINT8 tmp_buf[1400];      /**< 临时缓冲区 */
    CM_INT32 tmp_len = 0;       /**< 临时数据长度 */
    ENUM_CM_RETURN send_rt = ENUM_CM_FALSE;
    STRU_AREA_WITH_ARB_STATE_MULTI_PACK_T multi_pack = {0};   /**< 待发送数据结构体 */

    /** 填充结构体 */
    multi_pack.Len = AREA_ARB_STATE_MULTI_PACK_LEN - 1u;
    multi_pack.MsgType = ENUM_AREA_MSG_STATE_MULTI;
    multi_pack.SN = DFM_GetBirthCount();
    multi_pack.SrcID = AREA_BASIC_CFG_PTR->BoardID;
    multi_pack.StateArea = AREA_STATE_CTRL_PTR->StateArea.Local_state;
    multi_pack.State2x = AREA_STATE_CTRL_PTR->State2x.LocalState;
    CM_Memset(&multi_pack.Reserver[0], 0, AREA_ARB_RESERVER_LEN, AREA_ARB_RESERVER_LEN);

    /**计算CRC */
    tmp_len = Area_Arb_State_Multi_Pack(tmp_buf, sizeof(tmp_buf), &multi_pack);
    if(AREA_ARB_STATE_MULTI_PACK_LEN == tmp_len)
    {
        s_Area_DoubleCRC_Get(tmp_buf, (CM_UINT32)tmp_len, &multi_pack.CRC1, &multi_pack.CRC2);
        tmp_len = Area_Arb_State_Multi_Pack(tmp_buf, sizeof(tmp_buf), &multi_pack);
        CM_ASSERT(AREA_ARB_STATE_MULTI_PACK_LEN == tmp_len, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
        /**组播发送 */
        send_rt = Area_State_Multi_Send(tmp_buf, tmp_len);
        AREA_LOG_MSG("AREA_ARB:Multicast state send, SrcID:%d SN:%u State:%d 2x2:%d Result:0x%x\n",
            multi_pack.SrcID, multi_pack.SN, multi_pack.StateArea, multi_pack.State2x, send_rt);
    }
    else
    {
        AREA_LOG_MSG("AREA_ARB:Multicast state pack failed, Len:%d\n", tmp_len);
    }
}
/**
 * @brief 非主地主接收组播状态数据处理
 */
static void s_Area_State_Multi_Recv_Process(void)
{
    CM_UINT32 crc1 = 0u, crc2 = 0u;
    CM_UINT8 wire_buf[AREA_ARB_STATE_MULTI_PACK_LEN] = {0u};
    CM_INT32 rcv_len = 0;
    STRU_AREA_WITH_ARB_STATE_MULTI_PACK_T multi_pack = {0}; /**状态组播帧数据结构体 */
    CM_UINT32 tickNow = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION);
    CM_UINT32 tickStart = tickNow, usedTime = 0u;
    CM_UINT32 tickRcv = 0u;
    STRU_AREA_WITH_ARB_STATE_MULTI_PACK_T peer_pack = {0};
    /*组播接收*/

    /*双CRC校验*/
    do
    {
        rcv_len = Area_State_Multi_Recv(wire_buf, sizeof(wire_buf), &tickRcv);
        tickNow = (CM_UINT32)(CM_GetTick() / CM_UNSIGNED_MILLION);
        if(AREA_ARB_STATE_MULTI_PACK_LEN == rcv_len &&
            ((tickNow - tickRcv) < g_PFM_Cfg.CYC_TIME))
        {
            Area_Arb_State_Multi_UnPack(&multi_pack, wire_buf, (CM_UINT32)rcv_len);
            crc1 = CM_Crc32_1(&wire_buf[1], (CM_UINT32)rcv_len - 9u);
            crc2 = CM_Crc32_2(&wire_buf[1], (CM_UINT32)rcv_len - 9u);
            if(crc1 == multi_pack.CRC1 && crc2 == multi_pack.CRC2 &&
                ((AREA_ARB_STATE_MULTI_PACK_LEN - 1u) == multi_pack.Len) &&
                ENUM_AREA_MSG_STATE_MULTI == multi_pack.MsgType)
            {
                /**此处仅设置主地主的状态，不作为与主地主通信状态的判断依据 */
                AreaArb_SetState_byID(multi_pack.SrcID, multi_pack.StateArea);
                AreaArb_Set2xState_byID(multi_pack.SrcID, multi_pack.State2x);
                AREA_LOG_MSG("AREA_ARB:Multicast state received, SrcID:%d SN:%u State:%d 2x2:%d\n",
                    multi_pack.SrcID, multi_pack.SN, multi_pack.StateArea, multi_pack.State2x);
            }
            else
            {
                /**接收失败清空结构体，等待2取同步 */
                CM_Memset(&multi_pack, 0, sizeof(multi_pack), sizeof(multi_pack));
                AREA_LOG_MSG("Multi Recv Crc Fail %08x-%08x, %08x-%08x\n",crc1, multi_pack.CRC1, crc2, multi_pack.CRC2);
            }
        }
        else
        {
            CM_Sleep(1u);  
        }     
        usedTime = tickNow - tickStart;   
    } while (AREA_MULTI_WAITE_TIME > usedTime);
    /**对组播接收进行2取同步 */
    Area_2oo2_Currency_NoSplit(&multi_pack, sizeof(multi_pack), &peer_pack, sizeof(peer_pack));
    if(peer_pack.SN > multi_pack.SN)
    {
        /**邻机有最新数据 */
        AREA_LOG_MSG("AREA_ARB: Multi Recv 2oo2 Sync, Peer-Mine:%d-%d\n", peer_pack.SN, multi_pack.SN);
        AreaArb_SetState_byID(peer_pack.SrcID, peer_pack.StateArea);
        AreaArb_Set2xState_byID(peer_pack.SrcID, peer_pack.State2x);
    }

}
/**
 * @brief 周期运行中的初始化，初始化接收状态和其他板卡状态
 */
static void s_Area_Cycle_Init(void)
{
    /**每周期都要初始化其他板卡的地状态 */
    AREA_STATE_CTRL_PTR->StateArea.Partner_state = ENUM_AREA_SHUTDOWN;
    AREA_STATE_CTRL_PTR->StateArea.Partner_Area_A_state = ENUM_AREA_SHUTDOWN;
    AREA_STATE_CTRL_PTR->StateArea.Partner_Area_B_state = ENUM_AREA_SHUTDOWN;
    /**初始化另一地的两系2乘状态 */
    AREA_STATE_CTRL_PTR->State2x.Area_A_State = ENUM_2x2_SHUTDOWN;
    AREA_STATE_CTRL_PTR->State2x.Area_B_State = ENUM_2x2_SHUTDOWN;
    /**从2乘线程获取地内的系状态 */
    SFM_2x2_GetStateAfterStateChange(&(AREA_STATE_CTRL_PTR->State2x.LocalState), &(AREA_STATE_CTRL_PTR->State2x.PartnerState));
    /**如果上周期与某一系通信中断，清空接收SN */
    if(CM_FALSE == AREA_COMM_STATUS_PTR->Patner_RcvFlag)
    {
        AREA_COMM_STATUS_PTR->PatnerSN = 0u;
    }
    if(CM_FALSE == AREA_COMM_STATUS_PTR->Area_A_RcvFlag)
    {
        AREA_COMM_STATUS_PTR->Area_A_SN = 0u;
    }
    if(CM_FALSE == AREA_COMM_STATUS_PTR->Area_B_RcvFlag)
    {
        AREA_COMM_STATUS_PTR->Area_B_SN = 0u;
    }    
    /**每周期初始化接收标志 */
    AREA_COMM_STATUS_PTR->Patner_RcvFlag = CM_FALSE;
    AREA_COMM_STATUS_PTR->Area_A_RcvFlag = CM_FALSE;
    AREA_COMM_STATUS_PTR->Area_B_RcvFlag = CM_FALSE;
    /**每周期获取所需标志 */
    AREA_FLAGS_CTRL_PTR->Time_Sync_Flag = CFM_GetTimeSyncFlag();
    AREA_FLAGS_CTRL_PTR->Sync_Fail_Flag = CFM_GetSyncFailFlag();
    AREA_FLAGS_CTRL_PTR->Sync_Health_Flag = CFM_GetSyncHealth();
}
/**
 * @brief 根据ID设置接收状态
 */
void AreaArb_SetCommStatus_byID(CM_UINT8 ID, CM_UINT32 sn, CM_BOOL rcv_flag)
{
    if(ID == AREA_BASIC_CFG_PTR->BoardID)
    {
        AREA_COMM_STATUS_PTR->LocalSN = sn;
    }
    else if(ID == AREA_BASIC_CFG_PTR->Partner_BoardID)
    {
        AREA_COMM_STATUS_PTR->PatnerSN = sn;
        AREA_COMM_STATUS_PTR->Patner_RcvFlag = rcv_flag;
    }
    else if(ID == AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID)
    {
        AREA_COMM_STATUS_PTR->Area_A_SN = sn;
        AREA_COMM_STATUS_PTR->Area_A_RcvFlag = rcv_flag;
    }
    else if(ID == AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID)
    {
        AREA_COMM_STATUS_PTR->Area_B_SN = sn;
        AREA_COMM_STATUS_PTR->Area_B_RcvFlag = rcv_flag;
    }
    else
    {
        AREA_LOG_MSG("Cant Find ID:%d\n", ID);
    }
}
/**
 * @brief 根据ID获取接收状态
 */
void AreaArb_GetCommStatus_byID(CM_UINT8 ID, CM_UINT32* sn, CM_BOOL* rcv_flag)
{
    if(ID == AREA_BASIC_CFG_PTR->BoardID)
    {
        if(NULL != sn)
        {
            *sn = AREA_COMM_STATUS_PTR->LocalSN;
        }
        if(NULL != rcv_flag)
        {
            *rcv_flag = CM_TRUE;
        }
       
    }
    else if(ID == AREA_BASIC_CFG_PTR->Partner_BoardID)
    {
        if(NULL != sn)
        {
            *sn = AREA_COMM_STATUS_PTR->PatnerSN;
        }
        if(NULL != rcv_flag)
        {
            *rcv_flag = AREA_COMM_STATUS_PTR->Patner_RcvFlag;
        }
    }
    else if(ID == AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID)
    {
        if(NULL != sn)
        {
            *sn = AREA_COMM_STATUS_PTR->Area_A_SN;
        }
        if(NULL != rcv_flag)
        {
            *rcv_flag = AREA_COMM_STATUS_PTR->Area_A_RcvFlag;
        }
    }
    else if(ID == AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID)
    {
        if(NULL != sn)
        {
            *sn = AREA_COMM_STATUS_PTR->Area_B_SN;
        }
        if(NULL != rcv_flag)
        {
            *rcv_flag = AREA_COMM_STATUS_PTR->Area_B_RcvFlag;
        }
    }
    else
    {
        AREA_LOG_MSG("Cant Find ID:%d\n", ID);
    }
}
/**
 * @brief 对接收到的区域状态请求进行2取同步
 */
static CM_UINT32 s_Area_2oo2Sync_AfterStateRecv(CM_BOOL ack_flags[5], CM_UINT32 used_time)
{
    STRU_AREA_WITH_ARB_COMM_STATUS_T peer_comm_status = {0};
    STRU_AREA_WITH_ARB_STATE_CTRL_T peer_state_ctrl = {0};
    CM_BOOL peer_ack_flags[5] = {CM_FALSE, CM_FALSE, CM_FALSE, CM_FALSE, CM_FALSE};
    CM_UINT32 len_comm_status = sizeof(STRU_AREA_WITH_ARB_COMM_STATUS_T);
    CM_UINT32 len_state_ctrl = sizeof(STRU_AREA_WITH_ARB_STATE_CTRL_T);
    CM_UINT32 len_ack_flags = sizeof(peer_ack_flags);
    CM_UINT8 id = 0u;
    CM_UINT8 send_buf [1400] = {0}, rcv_buf[1400];
    CM_INT32 send_len = 0u, rcv_len = 0u;
    CM_UINT32 rcv_offset = 0u;
    CM_UINT32 peer_time = 0u;

    /**将接收状态进行组包2取 */
    if((NULL != ack_flags) &&
        (sizeof(send_buf) >= (len_comm_status + len_state_ctrl + len_ack_flags)))
    {
        CM_Memcpy(send_buf, sizeof(send_buf), AREA_COMM_STATUS_PTR, len_comm_status);
        send_len += len_comm_status;
        CM_Memcpy(&send_buf[send_len], sizeof(send_buf) - send_len, AREA_STATE_CTRL_PTR, len_state_ctrl);
        send_len += len_state_ctrl;
        CM_Memcpy(&send_buf[send_len], sizeof(send_buf) - send_len, ack_flags, len_ack_flags);
        send_len += len_ack_flags;
        CM_LongToChar(used_time, &send_buf[send_len]);
        send_len += 4u;
    }
    rcv_len = Area_2oo2_Currency_NoSplit(send_buf, send_len, rcv_buf, sizeof(rcv_buf));
    if(rcv_len != send_len)
    {
        AREA_LOG_MSG("AREA_ARB:State 2oo2 sync failed, SendLen:%d RecvLen:%d\n",
            send_len, rcv_len);
    }
    CM_ASSERT(rcv_len == send_len, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
    /**对另一CPU数据解析 */
    rcv_offset = 0u;
    CM_Memcpy(&peer_comm_status, len_comm_status,&rcv_buf[rcv_offset], len_comm_status);
    rcv_offset += len_comm_status; 
    CM_Memcpy(&peer_state_ctrl, len_state_ctrl,&rcv_buf[rcv_offset], len_state_ctrl);
    rcv_offset += len_state_ctrl;
    CM_Memcpy(peer_ack_flags, len_ack_flags, &rcv_buf[rcv_offset], len_ack_flags);
    rcv_offset += len_ack_flags;
    peer_time = CM_LongFromChar(&rcv_buf[rcv_offset]);

    /**任一CPU收到请求，两个CPU都使用相同的ACK目标。 */
    for(id = MSCP_AREA_A_BOARD_ID_A; id <= MSCP_AREA_B_BOARD_ID_B; id++)
    {
        if(CM_TRUE == peer_ack_flags[id])
        {
            ack_flags[id] = CM_TRUE;
        }
    }

    /**更新对系的接收序列号 */
    if(((AREA_COMM_STATUS_PTR->PatnerSN < peer_comm_status.PatnerSN) ||
        (CM_TRUE != AREA_COMM_STATUS_PTR->Patner_RcvFlag)) &&
        (CM_TRUE == peer_comm_status.Patner_RcvFlag))
    {
        /**接收到的对系序列号不同，本CPU为旧数据，同步新数据 */
        AREA_COMM_STATUS_PTR->PatnerSN = peer_comm_status.PatnerSN;
        AREA_COMM_STATUS_PTR->Patner_RcvFlag = peer_comm_status.Patner_RcvFlag;

        AREA_STATE_CTRL_PTR->StateArea.Partner_state = peer_state_ctrl.StateArea.Partner_state;
        AREA_STATE_CTRL_PTR->State2x.PartnerState = peer_state_ctrl.State2x.PartnerState;
        AREA_LOG_MSG("AREA_STATE:2oo2 sync update, BoardID:%d SN:%d State:%d 2x2:%d\n",
            AREA_BASIC_CFG_PTR->Partner_BoardID, peer_comm_status.PatnerSN,
            peer_state_ctrl.StateArea.Partner_state, peer_state_ctrl.State2x.PartnerState);
    }
    else
    {
        /**接收到的对系序列号相同，或者本CPU为新数据，无操作*/
    }

    /**更新另一地A系的接收序列号 */
    if(((AREA_COMM_STATUS_PTR->Area_A_SN < peer_comm_status.Area_A_SN) ||
        (CM_TRUE != AREA_COMM_STATUS_PTR->Area_A_RcvFlag)) &&
        (CM_TRUE == peer_comm_status.Area_A_RcvFlag))
    {
        /**接收到的对系序列号不同，本CPU为旧数据，同步新数据 */
        AREA_COMM_STATUS_PTR->Area_A_SN = peer_comm_status.Area_A_SN;
        AREA_COMM_STATUS_PTR->Area_A_RcvFlag = peer_comm_status.Area_A_RcvFlag;

        AREA_STATE_CTRL_PTR->StateArea.Partner_Area_A_state = peer_state_ctrl.StateArea.Partner_Area_A_state;
        AREA_STATE_CTRL_PTR->State2x.Area_A_State = peer_state_ctrl.State2x.Area_A_State;
        AREA_LOG_MSG("AREA_STATE:2oo2 sync update, BoardID:%d SN:%d State:%d 2x2:%d\n",
            AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID, peer_comm_status.Area_A_SN,
            peer_state_ctrl.StateArea.Partner_Area_A_state, peer_state_ctrl.State2x.Area_A_State);
    }
    else
    {
        /**接收到的对系序列号相同，或者本CPU为新数据，无操作*/
    }

    /**更新另一地B系的接收序列号 */
    if(((AREA_COMM_STATUS_PTR->Area_B_SN < peer_comm_status.Area_B_SN) ||
        (CM_TRUE != AREA_COMM_STATUS_PTR->Area_B_RcvFlag)) &&
        (CM_TRUE == peer_comm_status.Area_B_RcvFlag))
    {
        /**接收到的对系序列号不同，本CPU为旧数据，同步新数据 */
        AREA_COMM_STATUS_PTR->Area_B_SN = peer_comm_status.Area_B_SN;
        AREA_COMM_STATUS_PTR->Area_B_RcvFlag = peer_comm_status.Area_B_RcvFlag;

        AREA_STATE_CTRL_PTR->StateArea.Partner_Area_B_state = peer_state_ctrl.StateArea.Partner_Area_B_state;
        AREA_STATE_CTRL_PTR->State2x.Area_B_State = peer_state_ctrl.State2x.Area_B_State;
        AREA_LOG_MSG("AREA_STATE:2oo2 sync update, BoardID:%d SN:%d State:%d 2x2:%d\n",
            AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID, peer_comm_status.Area_B_SN,
            peer_state_ctrl.StateArea.Partner_Area_B_state, peer_state_ctrl.State2x.Area_B_State);
    }
    else
    {
        /**接收到的对系序列号相同，或者本CPU为新数据，无操作*/
    }

    return peer_time;
}
/**
 * @brief 2取同步后，判断本周期是否收到请求，并进行回复组包发送
 */
static void s_Area_SendACK_After2oo2(CM_BOOL ack_partner, CM_BOOL ack_area_a, CM_BOOL ack_area_b)
{
    STRU_AREA_WITH_ARB_STATE_PACK_T state_pack = {0};
    ENUM_CM_RETURN send_rt = ENUM_CM_FALSE;
    /**发送帧初始化 */
    state_pack.Len = AREA_ARB_STATE_PACK_LEN - 1u;
    state_pack.MsgType = ENUM_AREA_MSG_STATE_ACK;
    state_pack.TimeSyncFlag = AREA_FLAGS_CTRL_PTR->Time_Sync_Flag; /**获取校时标志 */
    state_pack.SrcID = AREA_BASIC_CFG_PTR->BoardID;
    state_pack.StateArea = AREA_STATE_CTRL_PTR->StateArea.Local_state;
    state_pack.State2x = AREA_STATE_CTRL_PTR->State2x.LocalState;
    CM_Memset(&state_pack.Reserver[0], 0, AREA_ARB_RESERVER_LEN, AREA_ARB_RESERVER_LEN);

    /**判断请求的接收情况 */
    if(CM_TRUE == AREA_COMM_STATUS_PTR->Patner_RcvFlag && CM_TRUE == ack_partner)
    {
        /**接收到了对系的请求，组包回复 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_BoardID;
        state_pack.SN = AREA_COMM_STATUS_PTR->PatnerSN;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State ACK send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x, AREA_ARB_NOW_USED_TIME:%llums\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt, AREA_ARB_NOW_USED_TIME);
    }
    if(CM_TRUE == AREA_COMM_STATUS_PTR->Area_A_RcvFlag && CM_TRUE == ack_area_a)
    {
        /**接收到了另一地A系的请求，组包回复 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID;
        state_pack.SN = AREA_COMM_STATUS_PTR->Area_A_SN;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State ACK send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x, AREA_ARB_NOW_USED_TIME:%llums\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt, AREA_ARB_NOW_USED_TIME);
    }
    if(CM_TRUE == AREA_COMM_STATUS_PTR->Area_B_RcvFlag && CM_TRUE == ack_area_b)
    {
        /**接收到了另一地A系的请求，组包回复 */
        state_pack.DstID = AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID;
        state_pack.SN = AREA_COMM_STATUS_PTR->Area_B_SN;
        send_rt = s_Area_State_Pack_Send(&state_pack);
        AREA_LOG_MSG("AREA_ARB:State ACK send, DstID:%d SN:%u State:%d 2x2:%d Result:0x%x, AREA_ARB_NOW_USED_TIME:%llums\n",
            state_pack.DstID, state_pack.SN, state_pack.StateArea, state_pack.State2x, send_rt, AREA_ARB_NOW_USED_TIME);
    }
}
/**
 * @brief 对接收到的仲裁应答进行2取同步
 */
static void s_Area_2oo2Sync_AfterArbRecv()
{
    CM_INT32 len = sizeof(STRU_AREA_WITH_ARB_REQ_T), rcv_len = 0;
    STRU_AREA_WITH_ARB_REQ_T peer_ctrl = {0};
    /**2取交互仲裁应答信息 */
    rcv_len = Area_2oo2_Currency_NoSplit((const CM_UINT8 *)AREA_ARB_CTRL_PTR,
        len, (CM_UINT8 *)&peer_ctrl, len);
    if(len != rcv_len)
    {
        AREA_LOG_MSG("AREA_ARB:Arbitration 2oo2 sync failed, SendLen:%d RecvLen:%d\n",
            len, rcv_len);
    }
    CM_ASSERT(len == rcv_len, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);

    if(peer_ctrl.Arb_Ack == 0x55u && AREA_ARB_CTRL_PTR->Arb_Ack == 0x00u)
    {
        /**本CPU没有收到仲裁回复，另一CPU收到，同步仲裁状态 */
        AREA_ARB_CTRL_PTR->Arb_Ack = peer_ctrl.Arb_Ack;
        AREA_LOG_MSG("AREA_ARB:Arbitration ACK synchronized from peer CPU, ACK:0x%x\n",
            peer_ctrl.Arb_Ack);
    }
}
/**
 * @brief 地间状态帧组包、计算CRC并发送
 */
static ENUM_CM_RETURN s_Area_State_Pack_Send(INOUT STRU_AREA_WITH_ARB_STATE_PACK_T* state_pack)
{
    CM_UINT8 tmp_buf[AREA_ARB_STATE_PACK_LEN] = {0u};

    /**第一次打包用于计算双CRC */
    (void)Area_Arb_State_Pack(tmp_buf, sizeof(tmp_buf), state_pack);
    s_Area_DoubleCRC_Get(tmp_buf, AREA_ARB_STATE_PACK_LEN, &state_pack->CRC1, &state_pack->CRC2);
    /**第二次打包用于发送 */
    (void)Area_Arb_State_Pack(tmp_buf, sizeof(tmp_buf), state_pack);

    return Area_State_Send(state_pack->DstID, tmp_buf, AREA_ARB_STATE_PACK_LEN);
}
/**
 * @brief 根据已打包的线路报文计算并同步双CRC
 */
static void s_Area_DoubleCRC_Get(IN const CM_UINT8* buf, IN CM_UINT32 len,
    OUT CM_UINT32* crc1, OUT CM_UINT32* crc2)
{
    CM_UINT32 local_crc[2] = {0u, 0u};
    CM_UINT32 peer_crc[2] = {0u, 0u};
    CM_INT32 rcv_len = 0;

    if((NULL == buf) || (NULL == crc1) || (NULL == crc2) || (len < 9u))
    {
        CM_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);
        return;
    }

    if(1u == AREA_BASIC_CFG_PTR->Cpuid)
    {
        local_crc[0] = CM_Crc32_1(&buf[1], len - 9u);
    }
    else
    {
        local_crc[1] = CM_Crc32_2(&buf[1], len - 9u);
    }

    rcv_len = Area_2oo2_Currency_NoSplit((const CM_UINT8*)local_crc,
        sizeof(local_crc), (CM_UINT8*)peer_crc, sizeof(peer_crc));
    CM_ASSERT(rcv_len == sizeof(local_crc), NET_MODE,
        DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1);

    if(1u == AREA_BASIC_CFG_PTR->Cpuid)
    {
        local_crc[1] = peer_crc[1];
    }
    else
    {
        local_crc[0] = peer_crc[0];
    }
    *crc1 = local_crc[0];
    *crc2 = local_crc[1];
}
/**
 * @brief 获取另一地A系的ID
 */
CM_UINT8 AreaArb_GetArea_A_ID(void)
{
    return AREA_BASIC_CFG_PTR->Partner_Area_A_BoardID;
}
/**
 * @brief 获取另一地B系的ID
 */
CM_UINT8 AreaArb_GetArea_B_ID(void)
{
    return AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID;
}