#include "common_include.h" volatile uint8_t OWN_ID; volatile _NMPDU NM_RPDU; //receive PDU buf volatile _SleepStatus NM_Sleep; volatile _MarkerStatus NM_Marker; volatile uint16_t NM_rx_err_count; volatile uint16_t NM_tx_err_count; volatile uint8_t NM_RX_STATE; volatile uint8_t NMReset_main_Cnt; volatile uint8_t NM_IGN_State; volatile uint8_t NM_TX_STATE; volatile uint8_t NM_ER_STATE; volatile uint16_t NM_CAN_CHL_ID; //NM_CAN_ID_BASE + OWN_NODE_CHL0 volatile uint16_t NM_LAST_ID; volatile uint8_t NM_LimpHomeTxCnt; volatile uint8_t NM_Task_Lock; volatile _NM_TimeInfo NM_Time; volatile uint8_t NM_LastSend_PDU_Type; //Last PDU Type volatile uint8_t NM_Destination; volatile uint16_t NM_ID_BUF; volatile _NMPDU NM_SPDU; //send PDU buf volatile _NMPDU NM_PDU_BUF; volatile _NetWorkStatus NetWorkStatus; volatile uint16_t NM_tSleepRequestMin; // void NM_State_Transformation(void (* pProgram)(void)); void (* NM_Main_Program)(void); void (* NMInitReset_Program)(void); void (* NMReset_Program)(void); // void NM_ReceiveMsg_handle(void); uint8_t NM_CheckSkip(uint8_t Source,uint8_t Destination,uint8_t Own_Node); void NM_ConfigLogicalFun(uint8_t SourceID); void CancelAlarm(uint16_t timetype); //Cansel Ttyp /Tmax /Terror count void NM_SetTmaxTimer(uint16_t Second,_NM_TimeInfo *T); uint8_t NM_TmaxTimerOver(_NM_TimeInfo *T); void NM_SetTwbsTimer(uint16_t Second,_NM_TimeInfo *T); uint8_t NM_TwbsTimerOver(_NM_TimeInfo *T); void NM_SetSleepTimer(uint16_t Second,_NM_TimeInfo *T); uint8_t NM_SleepTimerOver(_NM_TimeInfo *T); void NM_SetTSendTimer(uint16_t Second,_NM_TimeInfo *T); uint8_t NM_TSendTimerOver(_NM_TimeInfo *T); void GotoMode(uint8_t Mode); void NM_Do_Nothing(void); void Transmit_NMPDU(uint8_t PDU_Type); void NMInitReset(void); void NMReset(void); void NMReset_main(void); void NMReset_tx(void); void NMReset_rx(void); void NMReset_error(void); void NMNormal_main(void); void NMNormal_rx(void); void NMNormal_tx(void); void NMNormal_error(void); void NMNormalPrepSleep_main(void); void NMNormalPrep_rx(void); void NMNormalPrep_tx(void); void NMNormalPrep_error(void); void NMLimpHome_rx(void); void NMLimpHome_tx(void); void NMLimpHome_error(void); void NMLimpHomePrepSleep_main(void); void NMLimpHomePrepSleep_rx(void); void NMTwbsNormal_main(void); void NMTwbsNormal_rx(void); void NMTwbsLimpHome_main(void); void NMTwbsLimpHome_rx(void); void NM_CheckBusOff_Fun(void); /*------------------------------------------------------------------------- * Function Name : NM_Do_Nothing * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_Do_Nothing (void){;} /*------------------------------------------------------------------------- * Function Name : NM_CheckBusOff_Fun * Description : handle Busoff interface function * Input : after busoff into limphome state * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_CheckBusOff_Fun(void) { if(NetWorkStatus.BusOffEvent) { NetWorkStatus.BusOffEvent = 0; NM_D_Offline(); if((NM_Main_Program != NMLimpHome_main) && (NM_Main_Program != NMLimpHomePrepSleep_main) && (NM_Main_Program != NMTwbsLimpHome_main) && (NM_Main_Program != NMBusSleep_main)) { CancelAlarm(NM_Time_Max); CancelAlarm(NM_Time_Type); Transmit_NMPDU(LIMP_HOME_MSG); NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMLimpHome_main); } } } /*------------------------------------------------------------------------- * Function Name : NM_Do_Nothing * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_State_Transformation(void (* pProgram)(void)) { NM_TX_STATE = 0; NM_RX_STATE = 0; NM_ER_STATE = 0; NM_Main_Program = pProgram; NMReset_main_Cnt = 0; } /*------------------------------------------------------------------------- * Function Name : NM_ReceiveMsg_handle * Description : handle receive PDU; * Input : * Output : None * Return : None * onther : propose : in interrupt function --------------------------------------------------------------------------*/ void NM_ReceiveMsg_handle(void) { if(NM_PDU_BUF.bits.ProceF == NM_BUF_FULL) { NM_RPDU.msg[ 0 ] = NM_PDU_BUF.msg[ 0 ]; NM_RPDU.msg[ 1 ] = NM_PDU_BUF.msg[ 1 ]; NM_RPDU.msg[ 2 ] = NM_PDU_BUF.msg[ 2 ]; NM_RPDU.msg[ 3 ] = NM_PDU_BUF.msg[ 3 ]; NM_RPDU.msg[ 4 ] = NM_PDU_BUF.msg[ 4 ]; NM_RPDU.msg[ 5 ] = NM_PDU_BUF.msg[ 5 ]; NM_RPDU.msg[ 6 ] = NM_PDU_BUF.msg[ 6 ]; NM_RPDU.msg[ 7 ] = NM_PDU_BUF.msg[ 7 ]; NM_RPDU.bits.SourceID = NM_ID_BUF; NM_RX_STATE = 1; NM_PDU_BUF.bits.ProceF = NM_BUF_EMPTY; } } /*------------------------------------------------------------------------- * Function Name : OsekNM_Manage_Main * Description : OSEK Main function * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void OsekNM_Manage_Main(uint16_t BatVolt) { if(CurIgnSt == EVENT_IGN_ON) { NM_IGN_State = NM_IGN_ON; } if(CurIgnSt == EVENT_IGN_OFF) { NM_IGN_State = NM_IGN_OFF; } if(NM_Task_Lock == NM_LOCK) { return; } if(NM_Volt_Abnormal == 1) { return; } if(NM_Volt_Abnormal == 2) { NM_Volt_Abnormal = 0; NMInitReset(); NM_State_Transformation(NMReset_main); NM_Destination = OWN_ID; NM_rx_err_count++; Transmit_NMPDU(ALIVE_MSG); } NM_ReceiveMsg_handle(); NM_CheckSleep_Fun( ); if(NM_IGN_State == NM_IGN_ON) { if(NetWorkStatus.bussleep == NM_NO) { if(NM_Main_Program != NMBusSleep_main) { GotoMode(NMAwake); } TalkNM( ); } } if(NM_Main_Program == NULL) { NM_Main_Program = NMReset_main; } NM_CheckBusOff_Fun( ); if(NetWorkStatus.NMactive == NM_Active) { (*NM_Main_Program)(); } if(NetWorkStatus.APPactive == NM_Active) { NM_Send_App_Fun( ); } } /*------------------------------------------------------------------------- * Function Name : NMInitReset * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMInitReset(void) { NM_rx_err_count = 0; NM_tx_err_count = 0; NM_D_Online(); } /*------------------------------------------------------------------------- * Function Name : NMReset * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMReset(void) { NMReset_main_Cnt = 0; NM_Destination = OWN_ID; NM_rx_err_count++; NM_RPDU.bits.Opcode = 0; NM_TX_STATE = 0; NM_RX_STATE = 0; NM_ER_STATE = 0; NM_tSleepRequestMin = 0; NM_LimpHomeTxCnt = 0; NetWorkStatus.bussleep = NM_NO; Transmit_NMPDU(ALIVE_MSG); } /*------------------------------------------------------------------------- * Function Name : NMReset_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMReset_main (void) { if(NMInitReset_Program == NMInitReset) { (*NMInitReset_Program)(); NMInitReset_Program = NM_Do_Nothing; } if(NMReset_Program == NMReset) { (*NMReset_Program)(); NMReset_Program = NM_Do_Nothing; } NMReset_main_Cnt ++; if(NMReset_main_Cnt > 100) { NMReset_error(); return; } if(NM_ER_STATE){NMReset_error();return;} if(NM_TX_STATE){NMReset_tx();} } void NMReset_error (void) { NM_ER_STATE = 0; NM_tx_err_count++; if((NM_tx_err_count > NM_TX_LIMIT) || (NM_rx_err_count > NM_RX_LIMIT)) { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo *)&NM_Time); NM_Marker.limphome = NM_NO; NM_State_Transformation(NMLimpHome_main); } else { NM_SetTSendTimer(NM_Time_Type,(_NM_TimeInfo *)&NM_Time); NM_State_Transformation(NMNormal_main); } } void NMReset_tx(void) { NM_TX_STATE = 0; if((NM_tx_err_count <= NM_TX_LIMIT) && (NM_rx_err_count <= NM_RX_LIMIT)) { NM_SetTSendTimer(NM_Time_Type,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMNormal_main); } else { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); NM_Marker.limphome = NM_NO; NM_State_Transformation(NMLimpHome_main); } } void NMReset_rx(void) { uint8_t OpCode = 0; uint8_t Source = 0; NM_RX_STATE = 0; NM_rx_err_count = 0; if(NM_LastSend_PDU_Type == ALIVE_MSG) { Source = NM_RPDU.bits.SourceID; OpCode = NM_RPDU.msg[ 1 ]; if(OpCode & 0x03) { NM_ConfigLogicalFun(Source); } } } /*------------------------------------------------------------------------- * Function Name : StartNM * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void StartNM(void) { OWN_ID = OWN_NODE; NM_CAN_CHL_ID = NM_CAN_ID_BASE + OWN_NODE; NM_Marker.stable = NM_Unstabitily; NM_Sleep.ind = NM_NO; NM_Sleep.ack = NM_NO; NM_D_Init(BusInit); NM_Task_Lock = NM_UNLOCK; TalkNM( ); TalkAPP( ); NMInitReset(); NMReset(); NM_Main_Program = NMReset_main; NMInitReset_Program = NM_Do_Nothing; NMReset_Program = NM_Do_Nothing; NetWorkStatus.BusOffEvent = 0; NetWorkStatus.WakeupEvent = NM_WaitWakeup; NM_tSleepRequestMin = 0; } /*------------------------------------------------------------------------- * Function Name : NMNormal_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMNormal_main (void) { if(NM_ER_STATE) { NMNormal_error(); return; } else if(NM_TX_STATE) { NMNormal_tx(); if(NM_Main_Program == NMNormalPrepSleep_main) { return; } } if(NM_RX_STATE) { NMNormal_rx(); if(NM_Main_Program == NMTwbsNormal_main) { return; } } if(NM_TSendTimerOver((_NM_TimeInfo*)&NM_Time)) { if(NetWorkStatus.NMactive == NM_Active) { NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); Transmit_NMPDU(RING_MSG); } } if(NM_TmaxTimerOver((_NM_TimeInfo*)&NM_Time)) { NMReset(); NM_Main_Program = NMReset_main; } } void NMNormal_rx (void) { uint8_t OpCode = 0; uint8_t Source = 0; uint8_t Destination = 0; uint8_t Own_Node_Staute = 0; uint8_t OwnID = 0; NM_RX_STATE = 0; NM_rx_err_count = 0; Source = NM_RPDU.bits.SourceID; Destination = NM_RPDU.bits.DestID; OpCode = NM_RPDU.msg[ 1 ]; if(OpCode & 0x03) { NM_ConfigLogicalFun(Source); } if(OpCode & 0x10) { NM_Sleep.ind = NM_YES; } else { NM_Sleep.ind = NM_NO; } if(OpCode & 0x02)//RING { CancelAlarm(NM_Time_Type); CancelAlarm(NM_Time_Max); if(OpCode & 0x20)//NM_Sleep_ACK=1 { if(NetWorkStatus.bussleep) { NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo *)&NM_Time); NM_State_Transformation(NMTwbsNormal_main); return; } } OwnID = OWN_ID; if((Destination == OwnID) || (Source == Destination)) { NM_SetTSendTimer(NM_Time_Type,(_NM_TimeInfo *)&NM_Time); } else { NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); Own_Node_Staute = NM_CheckSkip(Source,Destination,OwnID); if(Own_Node_Staute == NM_NODE_SKIP) { NM_Destination = OwnID; Transmit_NMPDU(ALIVE_MSG); } } } else if(OpCode & 0x01) { NM_Marker.stable = NM_Unstabitily; } } void NMNormal_tx (void) { NM_TX_STATE = 0; NM_tx_err_count = 0; if((NM_Sleep.ind) && (NetWorkStatus.bussleep) && (NM_LastSend_PDU_Type == RING_MSG)) { NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); CancelAlarm(NM_Time_Type); NM_Sleep.ack = NM_YES; NM_State_Transformation(NMNormalPrepSleep_main); } } void NMNormal_error(void) { NM_ER_STATE = 0; NM_tx_err_count++; if(NM_tx_err_count > NM_TX_LIMIT) { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); NM_Marker.limphome = NM_NO; NM_State_Transformation(NMLimpHome_main); } } /*------------------------------------------------------------------------- * Function Name : NMNormalPrepSleep_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMNormalPrepSleep_main(void) { if(NM_ER_STATE) { NMNormalPrep_error(); return; } else if(NM_TX_STATE) { NMNormalPrep_tx(); return; } if(NM_RX_STATE) { NMNormalPrep_rx(); if((NM_Main_Program == NMTwbsNormal_main) || (NM_Main_Program == NMNormal_main)) { return; } } if(NM_TmaxTimerOver((_NM_TimeInfo*)&NM_Time)) // { CancelAlarm(NM_Time_Error); CancelAlarm(NM_Time_Type); NM_Marker.limphome = NM_NO; NMReset(); NM_Main_Program = NMReset_main; return; } if(NM_TSendTimerOver((_NM_TimeInfo*)&NM_Time)) { if(NetWorkStatus.NMactive == NM_Active) { Transmit_NMPDU(RING_MSG); } } } void NMNormalPrep_rx(void) { uint8_t OpCode = 0; uint8_t Source = 0; uint8_t Destination = 0; uint8_t Own_Node_Staute = 0; uint8_t OwnID = 0; NM_RX_STATE = 0; NM_rx_err_count = 0; Source = NM_RPDU.bits.SourceID; Destination = NM_RPDU.bits.DestID; OpCode = NM_RPDU.msg[ 1 ]; if(OpCode & 0x03) { NM_ConfigLogicalFun(Source); } if(OpCode & 0x10) { NM_Sleep.ind = NM_YES; } else { NM_Sleep.ind = NM_NO; } OwnID = OWN_ID; if(NM_Sleep.ind == NM_NO) { CancelAlarm(NM_Time_Max); CancelAlarm(NM_Time_Type); if((Destination == OwnID) || (Source == Destination)) { NM_SetTSendTimer(NM_Time_Type,(_NM_TimeInfo *)&NM_Time); } else { NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); Own_Node_Staute = NM_CheckSkip(Source,Destination,OwnID); if(Own_Node_Staute == NM_NODE_SKIP) { NM_Destination = OwnID; Transmit_NMPDU(ALIVE_MSG); } } NM_Main_Program = NMNormal_main; } else { if(OpCode & 0x02)//RING { if((OpCode & 0x20) == 0x20) //NM_Sleep_ACK=1 { CancelAlarm(NM_Time_Type); CancelAlarm(NM_Time_Max); NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo *)&NM_Time); NM_State_Transformation(NMTwbsNormal_main); return; } CancelAlarm(NM_Time_Type); CancelAlarm(NM_Time_Max); if((Destination == OwnID) || (Source == Destination)) { NM_SetTSendTimer(NM_Time_Type,(_NM_TimeInfo *)&NM_Time); } else { NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); Own_Node_Staute = NM_CheckSkip(Source,Destination,OwnID); if(Own_Node_Staute == NM_NODE_SKIP) { NM_Destination = OwnID; Transmit_NMPDU(ALIVE_MSG); } } } else if(OpCode & 0x01) { NM_Marker.stable = NM_Unstabitily; } } } void NMNormalPrep_tx(void) { NM_TX_STATE = 0; if(NM_LastSend_PDU_Type == RING_MSG) { NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo *)&NM_Time); NM_D_Offline(); NM_State_Transformation(NMTwbsNormal_main); } } void NMNormalPrep_error(void) { NM_ER_STATE = 0; if(NM_LastSend_PDU_Type == RING_MSG) { NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo *)&NM_Time); NM_D_Offline(); NM_State_Transformation(NMTwbsNormal_main); } } /*------------------------------------------------------------------------- * Function Name : NMTwbsNormal_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMTwbsNormal_main(void) { NM_D_Offline( ); if(NM_RX_STATE) { NMTwbsNormal_rx(); if(NM_Main_Program == NMReset_main) { return; } } if(NM_TwbsTimerOver((_NM_TimeInfo *)&NM_Time)) { NM_State_Transformation(NMBusSleep_main); } } void NMTwbsNormal_rx(void) { NM_RX_STATE = 0; NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); NM_Sleep.ind = NM_RPDU.msg[ 1 ] & 0x30; if(NM_Sleep.ind == NM_NO) { NMInitReset(); NMReset(); NM_Main_Program = NMReset_main; } } /*------------------------------------------------------------------------- * Function Name : NMLimpHome_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMLimpHome_main (void) { if(NM_TX_STATE) { NMLimpHome_tx(); return; } if(NM_ER_STATE) { NMLimpHome_error(); return; } if(NM_RX_STATE) { NMLimpHome_rx(); if((NM_Main_Program == NMReset_main) || (NM_Main_Program == NMTwbsLimpHome_main)) { return; } } if(NM_TSendTimerOver((_NM_TimeInfo*)&NM_Time)) { if(NetWorkStatus.bussleep) { NM_SetTmaxTimer(NM_Time_Max,(_NM_TimeInfo *)&NM_Time); NM_TX_STATE = 0; NM_RX_STATE = 0; NM_ER_STATE = 0; NM_Destination = OWN_ID; Transmit_NMPDU(LIMP_HOME_MSG); if(NM_Sleep.ind) { NM_State_Transformation(NMLimpHomePrepSleep_main); } } else { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); Transmit_NMPDU(LIMP_HOME_MSG); } } } void NMLimpHome_rx(void) { uint8_t OpCode = 0; NM_RX_STATE = 0; OpCode = NM_RPDU.msg[ 1 ]; if(OpCode & 0x20) { NM_Sleep.ack = NM_YES; } else { NM_Sleep.ack = NM_NO; } if(OpCode & 0x10) { NM_Sleep.ind = NM_YES; } else { NM_Sleep.ind = NM_NO; } if(NetWorkStatus.NMactive == NM_Active) { if(NM_Marker.limphome == NM_YES) { if(NetWorkStatus.bussleep) { if(NM_Sleep.ack) { NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMTwbsLimpHome_main); } else //5 { CancelAlarm(NM_Time_Error); NM_Marker.limphome = NM_NO; NMInitReset(); NMReset(); NM_Main_Program = NMReset_main; } } else //if(NetWorkStatus.bussleep == NM_NO) //5 { CancelAlarm(NM_Time_Error); NM_Marker.limphome = NM_NO; NMInitReset(); NMReset(); NM_Main_Program = NMReset_main; } } else { if(NM_Sleep.ack) { NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMTwbsLimpHome_main); } else //5 { CancelAlarm(NM_Time_Error); NM_Marker.limphome = NM_NO; NMInitReset(); NMReset(); NM_Main_Program = NMReset_main; } } } } void NMLimpHome_tx (void) { NM_TX_STATE = 0; if(NM_LastSend_PDU_Type == LIMP_HOME_MSG) { NM_Marker.limphome = NM_YES; NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); } } void NMLimpHome_error(void) { NM_ER_STATE = 0; if(NM_LastSend_PDU_Type == LIMP_HOME_MSG) { if(!NM_Time.TtypEnable) { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); } } } /*------------------------------------------------------------------------- * Function Name : NMLimpHomePrepSleep_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMLimpHomePrepSleep_main(void) { if(NM_RX_STATE) { NMLimpHomePrepSleep_rx(); if((NM_Main_Program == NMLimpHome_main) || (NM_Main_Program == NMTwbsLimpHome_main)) { return; } } if(NM_TmaxTimerOver((_NM_TimeInfo*)&NM_Time))//P39 { NM_D_Offline( ); NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMTwbsLimpHome_main); } } void NMLimpHomePrepSleep_rx(void) { uint8_t OpCode = 0; NM_RX_STATE = 0; OpCode = NM_RPDU.msg[ 1 ]; if(OpCode & 0x20) //P39 { NM_SetTwbsTimer(NM_Time_WaitBusSleep,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMTwbsLimpHome_main); } else if(OpCode & 0x10) { } else { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMLimpHome_main); } } /*------------------------------------------------------------------------- * Function Name : NMTwbsLimpHome_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMTwbsLimpHome_main(void) { NM_D_Offline( ); if(NM_RX_STATE) { NMTwbsLimpHome_rx(); if(NM_Main_Program == NMLimpHome_main) { return; } } if(NM_TwbsTimerOver((_NM_TimeInfo*)&NM_Time)) { NM_State_Transformation(NMBusSleep_main); } } void NMTwbsLimpHome_rx(void) { uint8_t OpCode = 0; NM_RX_STATE = 0; OpCode = NM_RPDU.msg[ 1 ]; if((OpCode & 0x30) == 0) { NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); NM_State_Transformation(NMLimpHome_main); } } /*------------------------------------------------------------------------- * Function Name : NMBusSleep_main * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NMBusSleep_main (void) { NM_D_Offline( ); NM_rx_err_count = 0; NM_tx_err_count = 0; if(NetWorkStatus.WakeupEvent == NM_LocalWakeup) { NetWorkStatus.WakeupEvent = NM_WaitWakeup; GotoMode(NMAwake); } else if(NetWorkStatus.WakeupEvent == NM_RemoteWakeup) { NetWorkStatus.WakeupEvent = NM_WaitWakeup; GotoMode(NMAwake); } else { GotoMode(NMBusSleep); } } /*------------------------------------------------------------------------- * Function Name : NM_CheckSkip * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ uint8_t NM_CheckSkip (uint8_t Source,uint8_t Destination,uint8_t Own_Node) { uint8_t S = 0; uint8_t R = 0; uint8_t D = 0; uint8_t skip; S = Source; R = Own_Node; D = Destination; skip = 0; if(D < R) { if(S < D) { } else { if(S < R) { skip = NM_NODE_SKIP; } } } else { if(S < D) { if(S < R) { skip = NM_NODE_SKIP; } } else { skip = NM_NODE_SKIP; } } return skip; } /*------------------------------------------------------------------------- * Function Name : NM_ConfigLogicalFun * Description : determine logical successor * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_ConfigLogicalFun(uint8_t SourceID) { uint8_t S = 0; uint8_t R = 0; uint8_t L = 0; S = SourceID; R = OWN_ID; L = NM_Destination; if(L == R) { L = S; } else { if(L < R) { if(S < L) { L = S; } else { if(S < R) { } else { L = S; } } } else { if(S < L) { if(S < R) { } else { L = S; } } } } NM_Destination = L; } /*------------------------------------------------------------------------- * Function Name : GotoMode * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void GotoMode (uint8_t Mode) { switch(Mode) { case NMBusSleep: NM_TX_STATE = 0; NM_RX_STATE = 0; NM_ER_STATE = 0; NM_D_Init(BusSleep); SilentNM( ); break; case NMAwake: if((NM_Main_Program == NMNormal_main) || (NM_Main_Program == NMLimpHome_main)) { break; } TalkNM( ); if(NM_Main_Program == NMTwbsNormal_main) { CancelAlarm(NM_Time_WaitBusSleep); NMInitReset(); NM_State_Transformation(NMReset_main); NM_Destination = OWN_ID; NM_rx_err_count++; Transmit_NMPDU(ALIVE_MSG); break; } if(NM_Main_Program == NMLimpHomePrepSleep_main) { NM_Marker.limphome = NM_NO; NM_State_Transformation(NMLimpHome_main); NM_D_Online( ); Transmit_NMPDU(LIMP_HOME_MSG); NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); break; } if(NM_Main_Program == NMTwbsLimpHome_main) { CancelAlarm(NM_Time_WaitBusSleep); NM_Marker.limphome = NM_NO; NM_State_Transformation(NMLimpHome_main); NM_D_Online( ); Transmit_NMPDU(LIMP_HOME_MSG); NM_SetTSendTimer(NM_Time_Error,(_NM_TimeInfo*)&NM_Time); break; } if(NM_Main_Program == NMBusSleep_main) { NM_D_Init(BusInit); //initialize hardware by D_Init(...;BusInit)//NMInit NM_Marker.limphome = NM_NO;//NMInit NMInitReset(); NM_Destination = OWN_ID; //P26 reset the system specific default configuration NM_rx_err_count++; //P25 NM_State_Transformation(NMReset_main); NM_SPDU.bits.Opcode &= 0xCF; Transmit_NMPDU(ALIVE_MSG); break; } break; default: NM_State_Transformation(NM_Do_Nothing); } } /*------------------------------------------------------------------------- * Function Name : Transmit_NMPDU * Description : PDU Message handle * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void Transmit_NMPDU(uint8_t PDU_Type) { NM_LastSend_PDU_Type = PDU_Type; NM_Sleep.ind = NetWorkStatus.bussleep; switch(PDU_Type) { case ALIVE_MSG: NM_SPDU.bits.Opcode = 0x01; NM_Sleep.ack = 0; NM_Marker.stable = NM_Unstabitily; break; case RING_MSG: NM_SPDU.bits.Opcode = 0x02; NM_Marker.stable = NM_Stabilize; break; case LIMP_HOME_MSG: NM_SPDU.bits.Opcode = 0x04; NM_Sleep.ack = 0; NM_Marker.stable = NM_Unstabitily; break; default: ; } if((NM_SPDU.bits.Opcode & 0x04) == 0x04) { if(NM_LimpHomeTxCnt < 255) { NM_LimpHomeTxCnt ++; } } else { NM_LimpHomeTxCnt = 0; } if(NM_Sleep.ind == NM_YES) { NM_SPDU.bits.Opcode |= 0x10; } else { NM_SPDU.bits.Opcode &= 0xCF; } if(NM_Sleep.ind == NM_NO) { NM_Sleep.ack = 0; } if(NM_Main_Program != NMNormalPrepSleep_main) { NM_Sleep.ack = NM_NO; } if(NM_Sleep.ack) { NM_SPDU.bits.Opcode |= 0x20; } else { NM_SPDU.bits.Opcode &= 0xDF; } NM_SPDU.bits.NM_Data0 = 0x00; NM_SPDU.bits.NM_Data1 = 0x00; NM_SPDU.bits.NM_Data2 = 0x00; NM_SPDU.bits.NM_Data3 = 0x00; NM_SPDU.bits.Reserved0 = 0xFF; NM_SPDU.bits.Reserved1 = 0xFF; NM_ER_STATE = 0; NM_TX_STATE = 0; NM_Send_PDU_Fun( ); } /*------------------------------------------------------------------------- * Function Name : CancelAlarm * Description : Cansel Ttyp /Tmax /Terror count * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void CancelAlarm(uint16_t timetype) { switch(timetype) { case NM_Time_Error: case NM_Time_Type: NM_Time.TtypEnable = 0; NM_Time.TtypTime = 0; break; case NM_Time_Max: NM_Time.TmaxEnable = 0; NM_Time.TmaxTime = 0; break; case NM_Time_WaitBusSleep: NM_Time.SleepEnable = 0; break; default: ; } } /*------------------------------------------------------------------------- * Function Name : NM_SetTmaxTimer * Description : set Tmax count start * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_SetTmaxTimer(uint16_t Second,_NM_TimeInfo *T) { T->TtypEnable = 0; T->TtypTime = 0; T->TmaxEnable = 1; T->OverTmaxTime = Second; T->TmaxTime = 0; } /*------------------------------------------------------------------------- * Function Name : NM_TmaxTimerOver * Description : check Tmax out * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ uint8_t NM_TmaxTimerOver(_NM_TimeInfo *T) { if((T->TmaxTime >= T->OverTmaxTime)&&(T->TmaxEnable)) { T->TmaxEnable = 0; T->TmaxTime = 0; return 1; } else { return 0; } } /*------------------------------------------------------------------------- * Function Name : NM_SetTSendTimer * Description : set Ttyp or Terror count * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_SetTSendTimer(uint16_t Second,_NM_TimeInfo *T) { T->TmaxEnable = 0; T->TmaxTime = 0; T->TtypEnable = 1; T->OverTtypTime = Second; T->TtypTime = 0; } /*------------------------------------------------------------------------- * Function Name : NM_TSendTimerOver * Description : Ttyp or Terror out * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ uint8_t NM_TSendTimerOver(_NM_TimeInfo *T) { if((T->TtypTime >= T->OverTtypTime)&&(T->TtypEnable)) { T->TtypEnable = 0; T->TtypTime = 0; return 1; } else { return 0; } } /*------------------------------------------------------------------------- * Function Name : NM_SetTwbsTimer * Description : set Twbs count * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_SetTwbsTimer(uint16_t Second,_NM_TimeInfo *T) { T->TwbsEnable = 1; T->OverTwbsTime = Second; T->TwbsTime = 0; } /*------------------------------------------------------------------------- * Function Name : NM_TwbsTimerOver * Description : check Twbs out * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ uint8_t NM_TwbsTimerOver(_NM_TimeInfo *T) { if((T->TwbsTime >= T->OverTwbsTime)&&(T->TwbsEnable)) { T->TwbsEnable = 0; return 1; } else { return 0; } } /*------------------------------------------------------------------------- * Function Name : NM_SetSleepTimer * Description : set sleep wait timer * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ void NM_SetSleepTimer(uint16_t Second,_NM_TimeInfo *T) { T->SleepEnable = 1; T->OverSleepTime = Second; T->SleepTime = 0; } /*------------------------------------------------------------------------- * Function Name : NM_SleepTimerOver * Description : * Input : * Output : None * Return : None * onther : --------------------------------------------------------------------------*/ uint8_t NM_SleepTimerOver(_NM_TimeInfo *T) { if((T->SleepTime >= T->OverSleepTime)&&(T->SleepEnable)) { T->SleepEnable = 0; T->SleepTime = 0; return 1; } else { return 0; } }