From eb5bdc817714b124fc2243fb281675a54469baad Mon Sep 17 00:00:00 2001 From: lh <3191213465@qq.com> Date: Thu, 20 Aug 2026 18:54:04 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=BD=AC=E6=8D=A2=E5=BC=80?= =?UTF-8?q?=E5=8F=91=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TSCP/src/MSCP/Arb/Arb.c | 56 ++++++++++- TSCP/src/MSCP/Arb/Arb.h | 12 +++ TSCP/src/MSCP/Arb/Arb_State_Vote.c | 146 +++++++++++++++++++++++++++++ TSCP/src/MSCP/Arb/Arb_State_Vote.h | 8 ++ 4 files changed, 219 insertions(+), 3 deletions(-) create mode 100644 TSCP/src/MSCP/Arb/Arb_State_Vote.c create mode 100644 TSCP/src/MSCP/Arb/Arb_State_Vote.h diff --git a/TSCP/src/MSCP/Arb/Arb.c b/TSCP/src/MSCP/Arb/Arb.c index e428e15..1f0310f 100644 --- a/TSCP/src/MSCP/Arb/Arb.c +++ b/TSCP/src/MSCP/Arb/Arb.c @@ -7,6 +7,7 @@ #include "Area_2oo2.h" #include "Arb_State.h" #include "CFM_Sync.h" +#include "Arb_State_Vote.h" /*===========↓↓↓↓↓全局变量声明&定义↓↓↓↓↓=============*/ STRU_AREA_WITH_ARB_CFG_ALL_T g_area_with_arb_cfg = {0}; /*===========↑↑↑↑↑全局变量声明&定义↑↑↑↑↑=============*/ @@ -105,6 +106,10 @@ static void s_Area_2oo2Sync_AfterStateRecv(); * @brief 2取同步后,判断本周期是否收到请求,并进行回复组包发送 */ static void s_Area_SendACK_After2oo2(); +/** + * @brief 对接收到的仲裁应答进行2取同步 + */ +static void s_Area_2oo2Sync_AfterArbRecv(); /*===========↑↑↑↑↑静态函数声明↑↑↑↑↑=============*/ @@ -119,6 +124,15 @@ void Area_With_Arb_Init(void) AREA_BASIC_CFG_PTR->OutnetID = g_PFM_Cfg.BOARD_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_Arb_Net_Init(); /*信号量初始化*/ @@ -378,7 +392,7 @@ static void s_Area_State_Ack_Recv_Process(void) CM_UINT32 crc1 = 0u, crc2 = 0u; CM_UINT32 timeStamp = 0u, timeNow = 0u; CM_UINT8 srcID = 0u, dstID = 0u; - CM_UINT8 timeSyncFlag = CFM_GetTimeSyncFlag(); /**获取校时标志 */ + CM_UINT8 timeSyncFlag = AREA_FLAGS_CTRL_PTR->Time_Sync_Flag; /**获取校时标志 */ CM_UINT32 localsn = AREA_COMM_STATUS_PTR->LocalSN; do { @@ -446,6 +460,8 @@ static void s_Area_Arb_Send_Process(void) CM_UINT8 id_mm = Area_GetID_byState(ENUM_AREA_MASTER, ENUM_2x2_MASTER); /**主地主的板卡ID */ /**获取通信中断标志 */ CM_UINT8 flag_comm_all_down = 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 = 0u; /**判断是否发送仲裁请求 */ if(ENUM_2x2_MASTER == AREA_STATE_CTRL_PTR->State2x.LocalState) @@ -454,6 +470,7 @@ static void s_Area_Arb_Send_Process(void) if(ENUM_AREA_MASTER == local_area_state && 0u == id_sm) { /**本地主地主,与备地主通信中断,发送仲裁请求 */ + AREA_ARB_CTRL_PTR->Arb_Send_Flag = 1u; Area_Arb_Req_Send(&arb_pack, sizeof(arb_pack)); } else if(ENUM_AREA_SLAVE == local_area_state && 0u == id_mm) @@ -461,6 +478,7 @@ static void s_Area_Arb_Send_Process(void) /**本地备地主,与主地主通信中断,容忍一周期发送请求 */ if(tolerate_arb >= 1u) { + AREA_ARB_CTRL_PTR->Arb_Send_Flag = 1u; Area_Arb_Req_Send(&arb_pack, sizeof(arb_pack)); tolerate_arb = 0u; } @@ -474,6 +492,7 @@ static void s_Area_Arb_Send_Process(void) /**未知地主系,与其他三系通信持续中断10周期,发送仲裁请求 */ if(tolerate_arb >= 10u) { + AREA_ARB_CTRL_PTR->Arb_Send_Flag = 1u; Area_Arb_Req_Send(&arb_pack, sizeof(arb_pack)); tolerate_arb = 0u; } @@ -528,13 +547,23 @@ static void s_Area_Arb_Recv_Process(void) } } } + s_Area_2oo2Sync_AfterArbRecv(); } /** * @brief 状态转移处理 */ static void s_Area_Arb_State_Transition(void) { - + if(1u == AREA_ARB_CTRL_PTR->Arb_Send_Flag && 0x00u == AREA_ARB_CTRL_PTR->Arb_Ack) + { + /**发送了仲裁请求但未收到应答,直接宕机 */ + CM_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1); + } + else + { + /**进行状态转换 */ + Area_With_Arb_State_Vote(); + } } /** * @brief 主地主的组播发送状态数据处理 @@ -623,6 +652,10 @@ static void s_Area_Cycle_Init(void) 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设置接收状态 @@ -792,7 +825,7 @@ static void s_Area_SendACK_After2oo2() /**发送帧初始化 */ state_pack.Len = AREA_ARB_STATE_PACK_REAL_LEN - 1; state_pack.MsgType = ENUM_AREA_MSG_STATE_ACK; - state_pack.TimeSyncFlag = CFM_GetTimeSyncFlag(); /**获取校时标志 */ + 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; @@ -830,3 +863,20 @@ static void s_Area_SendACK_After2oo2() Area_State_Send(AREA_BASIC_CFG_PTR->Partner_Area_B_BoardID, &state_pack, sizeof(state_pack)); } } +/** + * @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(AREA_ARB_CTRL_PTR, len, &peer_ctrl, 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; + } +} diff --git a/TSCP/src/MSCP/Arb/Arb.h b/TSCP/src/MSCP/Arb/Arb.h index 2f9017b..01748ab 100644 --- a/TSCP/src/MSCP/Arb/Arb.h +++ b/TSCP/src/MSCP/Arb/Arb.h @@ -11,6 +11,7 @@ #define AREA_STATE_CTRL_PTR (&g_area_with_arb_cfg.State_CTRL) /**< 仲裁模式下使用,区域模块的状态控制 */ #define AREA_COMM_STATUS_PTR (&g_area_with_arb_cfg.Comm_Status) /**< 仲裁模式下使用,区域模块的通信状态记录 */ #define AREA_ARB_CTRL_PTR (&g_area_with_arb_cfg.Arb_CTRL) /**< 仲裁模式下使用,区域模块的仲裁控制 */ +#define AREA_FLAGS_CTRL_PTR (&g_area_with_arb_cfg.Flag_CTRL) /**< 仲裁模式下使用,区域模块使用的标志位 */ /*仲裁模式下,区域间所有通信相关配置*/ typedef struct @@ -35,9 +36,18 @@ typedef struct /*仲裁模式下,记录仲裁的回复*/ typedef struct { + CM_UINT8 Arb_Send_Flag; /**< 仲裁请求发送标志位,记录本周期是否发送了仲裁请求 */ CM_UINT8 Arb_Ack; /**< 记录仲裁的回复 */ }STRU_AREA_WITH_ARB_REQ_T; +/*仲裁模式下,记录各种同步标志(时间/数据同步) */ +typedef struct +{ + CM_BOOL Time_Sync_Flag; /**< 时间同步标志 */ + CM_BOOL Sync_Health_Flag; /**< 同步健康标志 */ + CM_BOOL Sync_Fail_Flag; /**< 同步失败标志 CM_FALSE-同步失败 CM_TRUE-同步成功*/ +}STRU_AREA_WITH_ARB_FLAGS_T; + /*仲裁模式下,区域线程控制*/ typedef struct { @@ -54,6 +64,7 @@ typedef struct CM_UINT8 Partner_Area_A_BoardID; /**< 对系id */ CM_UINT8 Partner_Area_B_BoardID; /**< 对系id */ CM_UINT16 OutnetID; /**<外网ID */ + CM_UINT8 AreaID; /**< 区域ID,A地或B地 */ }STRU_AREA_WITH_ARB_BASIC_CFG_T; /*仲裁模式下,记录2乘状态结构体*/ @@ -81,6 +92,7 @@ typedef struct STRU_AREA_WITH_ARB_STATE_CTRL_T State_CTRL; /**<状态控制 */ STRU_AREA_WITH_ARB_COMM_STATUS_T Comm_Status; /**<通信状态记录 */ STRU_AREA_WITH_ARB_REQ_T Arb_CTRL; /**< 与仲裁的交互 */ + STRU_AREA_WITH_ARB_FLAGS_T Flag_CTRL; /**< 记录各种标志 */ }STRU_AREA_WITH_ARB_CFG_ALL_T; extern STRU_AREA_WITH_ARB_CFG_ALL_T g_area_with_arb_cfg; diff --git a/TSCP/src/MSCP/Arb/Arb_State_Vote.c b/TSCP/src/MSCP/Arb/Arb_State_Vote.c new file mode 100644 index 0000000..7444124 --- /dev/null +++ b/TSCP/src/MSCP/Arb/Arb_State_Vote.c @@ -0,0 +1,146 @@ +#include "Arb_State_Vote.h" + +/**仅在状态表决时使用,简化宏,只包含区域状态 */ +#define VOTE_STATE_CTRL (&(AREA_STATE_CTRL_PTR->StateArea)) + +/** + * @brief 宕机状态转换 + */ +void s_Shutdown_vote(void); +/** + * @brief 未知地状态转换 + */ +void s_Unknown_vote(void); +/** + * @brief 离线地状态转换 + */ +void s_Offline_vote(void); +/** + * @brief 主地状态转换 + */ +void s_Master_vote(void); +/** + * @brief 备地状态转换 + */ +void s_Slave_vote(void); + +void Area_With_Arb_State_Vote(void) +{ + ENUM_AREA_STATE local_state = VOTE_STATE_CTRL->Local_state; + switch(local_state) + { + case ENUM_AREA_SHUTDOWN: + s_Shutdown_vote(); + break; + case ENUM_AREA_UNKNOW: + s_Unknown_vote(); + break; + case ENUM_AREA_OFFLINE: + s_Offline_vote(); + break; + case ENUM_AREA_MASTER: + s_Master_vote(); + break; + case ENUM_AREA_SLAVE: + s_Slave_vote(); + break; + + } +} +/** + * @brief 宕机状态转换 + */ +void s_Shutdown_vote(void) +{ + VOTE_STATE_CTRL->Local_state = ENUM_AREA_SHUTDOWN; + CM_ASSERT(0, NET_MODE, DARK_FAULT_CODE_FUN_ORDER_2, TSCP_DARK_ASSERT_1); +} +/** + * @brief 未知地状态转换 + */ +void s_Unknown_vote(void) +{ + /**获取另外三系状态 */ + ENUM_AREA_STATE Partner_State = VOTE_STATE_CTRL->Partner_state; + ENUM_AREA_STATE Area_A_State = VOTE_STATE_CTRL->Partner_Area_A_state; + ENUM_AREA_STATE Area_B_State = VOTE_STATE_CTRL->Partner_Area_B_state; + /**初始化未知地计数 */ + static CM_UINT32 unkown_cnt = 0u; + /**状态转换部分 */ + if(0x55u == AREA_ARB_CTRL_PTR->Arb_Ack) + { + /**收到仲裁升主回复 */ + VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER; + } + else if(ENUM_AREA_MASTER == Partner_State) + { + /**和主地在同一地 */ + VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER; + } + else if((ENUM_AREA_UNKNOW == Area_A_State || ENUM_AREA_UNKNOW == Area_B_State) + && (MSCP_AREA_ID_B == AREA_BASIC_CFG_PTR->AreaID)) + { + /**另一地是离线地,本地是B地,降离线 */ + VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE; + AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Offline, A is Unknown, Local is B\n"); + } + else if((ENUM_AREA_SLAVE == Area_A_State || ENUM_AREA_SLAVE == Area_B_State)) + { + /**另一地是备地,降离线(暂不存在改场景,预留转换) */ + VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE; + AREA_LOG_MSG("AREA_STATE_VOTE:Unknow>>>>>Offline, Another Area is Slave\n"); + } + else if((ENUM_AREA_MASTER == Area_A_State || ENUM_AREA_MASTER == Area_B_State)) + { + /**另一地是主地,降离线 */ + VOTE_STATE_CTRL->Local_state = ENUM_AREA_OFFLINE; + } + else if((MSCP_AREA_ID_A == AREA_BASIC_CFG_PTR->AreaID) + && (ENUM_AREA_UNKNOW == Area_A_State || ENUM_AREA_SHUTDOWN == Area_A_State || ENUM_AREA_OFFLINE == Area_A_State) + && (ENUM_AREA_UNKNOW == Area_B_State || ENUM_AREA_SHUTDOWN == Area_B_State || ENUM_AREA_OFFLINE == Area_B_State)) + { + /**另一地为未知地/离线地/宕机,本地是A地,维持10周期升主 */ + unkown_cnt++; + if(unkown_cnt > MSCP_AREA_UNKNOW_COUNT_MAX) + { + VOTE_STATE_CTRL->Local_state = ENUM_AREA_MASTER; + unkown_cnt = 0u; + } + } + else + { + + } + /**离开未知地,清空计数 */ + if(ENUM_AREA_UNKNOW == VOTE_STATE_CTRL->Local_state) + { + unkown_cnt = 0u; + } +} +/** + * @brief 离线地状态转换 + */ +void s_Offline_vote(void) +{ + CM_BOOL Sync_Fail_Flag = AREA_FLAGS_CTRL_PTR->Sync_Fail_Flag; + CM_BOOL Sync_Health_Flag = AREA_FLAGS_CTRL_PTR->Sync_Health_Flag; + if() + { + + } + +} +/** + * @brief 主地状态转换 + */ +void s_Master_vote(void) +{ + +} +/** + * @brief 备地状态转换 + */ +void s_Slave_vote(void) +{ + +} \ No newline at end of file diff --git a/TSCP/src/MSCP/Arb/Arb_State_Vote.h b/TSCP/src/MSCP/Arb/Arb_State_Vote.h new file mode 100644 index 0000000..f18ae1e --- /dev/null +++ b/TSCP/src/MSCP/Arb/Arb_State_Vote.h @@ -0,0 +1,8 @@ +#ifndef ARB_STATE_VOTE_H_ +#define ARB_STATE_VOTE_H_ + +#include "Arb.h" + +void Area_With_Arb_State_Vote(void); + +#endif \ No newline at end of file