/**************************************************************************** (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 www.systec-electronic.com Project: openPOWERLINK Description: source file for NMT-Kernelspace-Module License: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of SYSTEC electronic GmbH nor the names of its contributors may be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact info@systec-electronic.com. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Severability Clause: If a provision of this License is or becomes illegal, invalid or unenforceable in any jurisdiction, that shall not affect: 1. the validity or enforceability in that jurisdiction of any other provision of this License; or 2. the validity or enforceability in other jurisdictions of that or any other provision of this License. ------------------------------------------------------------------------- $RCSfile: EplNmtk.c,v $ $Author: D.Krueger $ $Revision: 1.12 $ $Date: 2008/11/13 17:13:09 $ $State: Exp $ Build Environment: GCC V3.4 ------------------------------------------------------------------------- Revision History: 2006/06/09 k.t.: start of the implementation ****************************************************************************/ #include "kernel/EplNmtk.h" #include "kernel/EplTimerk.h" #include "kernel/EplDllk.h" // for EplDllkProcess() #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) /***************************************************************************/ /* */ /* */ /* G L O B A L D E F I N I T I O N S */ /* */ /* */ /***************************************************************************/ //--------------------------------------------------------------------------- // const defines //--------------------------------------------------------------------------- // TracePoint support for realtime-debugging #ifdef _DBG_TRACE_POINTS_ void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p); void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p); #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p) #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v) #else #define TGT_DBG_SIGNAL_TRACE_POINT(p) #define TGT_DBG_POST_TRACE_VALUE(v) #endif #define EPL_NMTK_DBG_POST_TRACE_VALUE(NmtEvent_p, OldNmtState_p, NewNmtState_p) \ TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtk << 28) | (NmtEvent_p << 16) \ | ((OldNmtState_p & 0xFF) << 8) \ | (NewNmtState_p & 0xFF)) //--------------------------------------------------------------------------- // local types //--------------------------------------------------------------------------- // struct for instance table INSTANCE_TYPE_BEGIN EPL_MCO_DECL_INSTANCE_MEMBER() STATIC volatile tEplNmtState INST_FAR m_NmtState; STATIC volatile BOOL INST_FAR m_fEnableReadyToOperate; STATIC volatile BOOL INST_FAR m_fAppReadyToOperate; STATIC volatile BOOL INST_FAR m_fTimerMsPreOp2; STATIC volatile BOOL INST_FAR m_fAllMandatoryCNIdent; STATIC volatile BOOL INST_FAR m_fFrozen; INSTANCE_TYPE_END //--------------------------------------------------------------------------- // modul globale vars //--------------------------------------------------------------------------- // This macro replace the unspecific pointer to an instance through // the modul specific type for the local instance table. This macro // must defined in each modul. //#define tEplPtrInstance tEplInstanceInfo MEM* EPL_MCO_DECL_INSTANCE_VAR() //--------------------------------------------------------------------------- // local function prototypes //--------------------------------------------------------------------------- EPL_MCO_DEFINE_INSTANCE_FCT() /***************************************************************************/ /* */ /* */ /* C L A S S */ /* */ /* */ /***************************************************************************/ // // Description: This module realize the NMT-State-Machine of the EPL-Stack // // /***************************************************************************/ //=========================================================================// // // // P U B L I C F U N C T I O N S // // // //=========================================================================// //--------------------------------------------------------------------------- // // Function: EplNmtkInit // // Description: initializes the first instance // // // // Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer // uiNodeId_p = Node Id of the lokal node // // // Returns: tEplKernel = Errorcode // // // State: // //--------------------------------------------------------------------------- EPLDLLEXPORT tEplKernel PUBLIC EplNmtkInit(EPL_MCO_DECL_PTR_INSTANCE_PTR) { tEplKernel Ret; Ret = EplNmtkAddInstance(EPL_MCO_PTR_INSTANCE_PTR); return Ret; } //--------------------------------------------------------------------------- // // Function: EplNmtkAddInstance // // Description: adds a new instance // // // // Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer // // // Returns: tEplKernel = Errorcode // // // State: // //--------------------------------------------------------------------------- EPLDLLEXPORT tEplKernel PUBLIC EplNmtkAddInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) { EPL_MCO_DECL_INSTANCE_PTR_LOCAL tEplKernel Ret; //tEplEvent Event; //tEplEventNmtStateChange NmtStateChange; // check if pointer to instance pointer valid // get free instance and set the globale instance pointer // set also the instance addr to parameterlist EPL_MCO_CHECK_PTR_INSTANCE_PTR(); EPL_MCO_GET_FREE_INSTANCE_PTR(); EPL_MCO_SET_PTR_INSTANCE_PTR(); // sign instance as used EPL_MCO_WRITE_INSTANCE_STATE(kStateUsed); Ret = kEplSuccessful; // initialize intern vaiables // 2006/07/31 d.k.: set NMT-State to kEplNmtGsOff EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; // set NMT-State to kEplNmtGsInitialising //EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; // set flags to FALSE EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) = FALSE; EPL_MCO_GLB_VAR(m_fAllMandatoryCNIdent) = FALSE; EPL_MCO_GLB_VAR(m_fFrozen) = FALSE; // EPL_MCO_GLB_VAR(m_TimerHdl) = 0; // inform higher layer about state change // 2006/07/31 d.k.: The EPL API layer/application has to start NMT state // machine via NmtEventSwReset after initialisation of // all modules has been completed. DLL has to be initialised // after NMTk because NMT state shall not be uninitialised // at that time. /* NmtStateChange.m_NewNmtState = EPL_MCO_GLB_VAR(m_NmtState); NmtStateChange.m_NmtEvent = kEplNmtEventNoEvent; Event.m_EventSink = kEplEventSinkNmtu; Event.m_EventType = kEplEventTypeNmtStateChange; EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); Event.m_pArg = &NmtStateChange; Event.m_uiSize = sizeof(NmtStateChange); Ret = EplEventkPost(&Event); */ return Ret; } //--------------------------------------------------------------------------- // // Function: EplNmtkDelInstance // // Description: delete instance // // // // Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR = Instance pointer // // // Returns: tEplKernel = Errorcode // // // State: // //--------------------------------------------------------------------------- #if (EPL_USE_DELETEINST_FUNC != FALSE) EPLDLLEXPORT tEplKernel PUBLIC EplNmtkDelInstance(EPL_MCO_DECL_PTR_INSTANCE_PTR) { tEplKernel Ret = kEplSuccessful; // check for all API function if instance is valid EPL_MCO_CHECK_INSTANCE_STATE(); // set NMT-State to kEplNmtGsOff EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; // sign instance as unused EPL_MCO_WRITE_INSTANCE_STATE(kStateUnused); // delete timer // Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); return Ret; } #endif // (EPL_USE_DELETEINST_FUNC != FALSE) //--------------------------------------------------------------------------- // // Function: EplNmtkProcess // // Description: main process function // -> process NMT-State-Maschine und read NMT-Events from Queue // // // // Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR_ = Instance pointer // pEvent_p = Epl-Event with NMT-event to process // // // Returns: tEplKernel = Errorcode // // // State: // //--------------------------------------------------------------------------- EPLDLLEXPORT tEplKernel PUBLIC EplNmtkProcess(EPL_MCO_DECL_PTR_INSTANCE_PTR_ tEplEvent * pEvent_p) { tEplKernel Ret; tEplNmtState OldNmtState; tEplNmtEvent NmtEvent; tEplEvent Event; tEplEventNmtStateChange NmtStateChange; // check for all API function if instance is valid EPL_MCO_CHECK_INSTANCE_STATE(); Ret = kEplSuccessful; switch (pEvent_p->m_EventType) { case kEplEventTypeNmtEvent: { NmtEvent = *((tEplNmtEvent *) pEvent_p->m_pArg); break; } case kEplEventTypeTimer: { NmtEvent = (tEplNmtEvent) ((tEplTimerEventArg *) pEvent_p-> m_pArg)->m_ulArg; break; } default: { Ret = kEplNmtInvalidEvent; goto Exit; } } // save NMT-State // needed for later comparison to // inform hgher layer about state change OldNmtState = EPL_MCO_GLB_VAR(m_NmtState); // NMT-State-Maschine switch (EPL_MCO_GLB_VAR(m_NmtState)) { //----------------------------------------------------------- // general part of the statemaschine // first init of the hardware case kEplNmtGsOff: { // leave this state only if higher layer says so if (NmtEvent == kEplNmtEventSwReset) { // new state kEplNmtGsInitialising EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; } break; } // first init of the hardware case kEplNmtGsInitialising: { // leave this state only if higher layer says so // check events switch (NmtEvent) { // 2006/07/31 d.k.: react also on NMT reset commands in ResetApp state // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // new state kEplNmtGsResetApplication case kEplNmtEventEnterResetApp: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } default: { break; } } break; } // init of the manufacturer-specific profile area and the // standardised device profile area case kEplNmtGsResetApplication: { // check events switch (NmtEvent) { // 2006/07/31 d.k.: react also on NMT reset commands in ResetApp state // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // leave this state only if higher layer // say so case kEplNmtEventEnterResetCom: { // new state kEplNmtGsResetCommunication EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } default: { break; } } break; } // init of the communication profile area case kEplNmtGsResetCommunication: { // check events switch (NmtEvent) { // 2006/07/31 d.k.: react also on NMT reset commands in ResetComm state // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // leave this state only if higher layer // say so case kEplNmtEventEnterResetConfig: { // new state kEplNmtGsResetCommunication EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } default: { break; } } break; } // build the configuration with infos from OD case kEplNmtGsResetConfiguration: { // reset flags EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_fFrozen) = FALSE; // check events switch (NmtEvent) { // 2006/07/31 d.k.: react also on NMT reset commands in ResetConf state // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication case kEplNmtEventResetCom: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // leave this state only if higher layer says so case kEplNmtEventEnterCsNotActive: { // Node should be CN EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsNotActive; break; } case kEplNmtEventEnterMsNotActive: { // Node should be CN #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) // no MN functionality // TODO: -create error E_NMT_BA1_NO_MN_SUPPORT EPL_MCO_GLB_VAR(m_fFrozen) = TRUE; #else EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsNotActive; #endif break; } default: { break; } } break; } //----------------------------------------------------------- // CN part of the statemaschine // node liste for EPL-Frames and check timeout case kEplNmtCsNotActive: { // check events switch (NmtEvent) { // 2006/07/31 d.k.: react also on NMT reset commands in NotActive state // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; // Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; // Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; // Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); break; } // NMT Command Reset Configuration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; // Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); break; } // see if SoA or SoC received // k.t. 20.07.2006: only SoA forces change of state // see EPL V2 DS 1.0.0 p.267 // case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // new state PRE_OPERATIONAL1 EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; // Ret = EplTimerkDeleteTimer(&EPL_MCO_GLB_VAR(m_TimerHdl)); break; } // timeout for SoA and Soc case kEplNmtEventTimerBasicEthernet: { // new state BASIC_ETHERNET EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsBasicEthernet; break; } default: { break; } } // end of switch(NmtEvent) break; } // node processes only async frames case kEplNmtCsPreOperational1: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command Reset Configuration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // NMT Command StopNode case kEplNmtEventStopNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; break; } // check if SoC received case kEplNmtEventDllCeSoc: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational2; break; } default: { break; } } // end of switch(NmtEvent) break; } // node processes isochronous and asynchronous frames case kEplNmtCsPreOperational2: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command Reset Configuration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // NMT Command StopNode case kEplNmtEventStopNode: { // reset flags EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; break; } // error occured case kEplNmtEventNmtCycleError: { // reset flags EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_fAppReadyToOperate) = FALSE; EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } // check if application is ready to operate case kEplNmtEventEnterReadyToOperate: { // check if command NMTEnableReadyToOperate from MN was received if (EPL_MCO_GLB_VAR(m_fEnableReadyToOperate) == TRUE) { // reset flags EPL_MCO_GLB_VAR (m_fEnableReadyToOperate) = FALSE; EPL_MCO_GLB_VAR (m_fAppReadyToOperate) = FALSE; // change state EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsReadyToOperate; } else { // set Flag EPL_MCO_GLB_VAR (m_fAppReadyToOperate) = TRUE; } break; } // NMT Commando EnableReadyToOperate case kEplNmtEventEnableReadyToOperate: { // check if application is ready if (EPL_MCO_GLB_VAR(m_fAppReadyToOperate) == TRUE) { // reset flags EPL_MCO_GLB_VAR (m_fEnableReadyToOperate) = FALSE; EPL_MCO_GLB_VAR (m_fAppReadyToOperate) = FALSE; // change state EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsReadyToOperate; } else { // set Flag EPL_MCO_GLB_VAR (m_fEnableReadyToOperate) = TRUE; } break; } default: { break; } } // end of switch(NmtEvent) break; } // node should be configured und application is ready case kEplNmtCsReadyToOperate: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // NMT Command StopNode case kEplNmtEventStopNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; break; } // error occured case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } // NMT Command StartNode case kEplNmtEventStartNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsOperational; break; } default: { break; } } // end of switch(NmtEvent) break; } // normal work state case kEplNmtCsOperational: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // NMT Command StopNode case kEplNmtEventStopNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsStopped; break; } // NMT Command EnterPreOperational2 case kEplNmtEventEnterPreOperational2: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational2; break; } // error occured case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } default: { break; } } // end of switch(NmtEvent) break; } // node stopped by MN // -> only process asynchronous frames case kEplNmtCsStopped: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // NMT Command EnterPreOperational2 case kEplNmtEventEnterPreOperational2: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational2; break; } // error occured case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } default: { break; } } // end of switch(NmtEvent) break; } // no epl cycle // -> normal ethernet communication case kEplNmtCsBasicEthernet: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // error occured // d.k.: how does this error occur? on CRC errors /* case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } */ case kEplNmtEventDllCeSoc: case kEplNmtEventDllCePreq: case kEplNmtEventDllCePres: case kEplNmtEventDllCeSoa: { // Epl-Frame on net -> stop any communication EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } default: { break; } } // end of switch(NmtEvent) break; } //----------------------------------------------------------- // MN part of the statemaschine // MN listen to network // -> if no EPL traffic go to next state case kEplNmtMsNotActive: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) // no MN functionality // TODO: -create error E_NMT_BA1_NO_MN_SUPPORT EPL_MCO_GLB_VAR(m_fFrozen) = TRUE; #else // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // EPL frames received case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // other MN in network // $$$ d.k.: generate error history entry EPL_MCO_GLB_VAR(m_fFrozen) = TRUE; break; } // timeout event case kEplNmtEventTimerBasicEthernet: { if (EPL_MCO_GLB_VAR(m_fFrozen) == FALSE) { // new state BasicEthernet EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsBasicEthernet; } break; } // timeout event case kEplNmtEventTimerMsPreOp1: { if (EPL_MCO_GLB_VAR(m_fFrozen) == FALSE) { // new state PreOp1 EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; EPL_MCO_GLB_VAR (m_fTimerMsPreOp2) = FALSE; EPL_MCO_GLB_VAR (m_fAllMandatoryCNIdent) = FALSE; } break; } default: { break; } } // end of switch(NmtEvent) #endif // ((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) == 0) break; } #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) // MN process reduces epl cycle case kEplNmtMsPreOperational1: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // EPL frames received case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // other MN in network // $$$ d.k.: generate error history entry EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // error occured // d.k. MSPreOp1->CSPreOp1: nonsense -> keep state /* case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } */ case kEplNmtEventAllMandatoryCNIdent: { // all mandatory CN identified if (EPL_MCO_GLB_VAR(m_fTimerMsPreOp2) != FALSE) { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational2; } else { EPL_MCO_GLB_VAR (m_fAllMandatoryCNIdent) = TRUE; } break; } case kEplNmtEventTimerMsPreOp2: { // residence time for PreOp1 is elapsed if (EPL_MCO_GLB_VAR (m_fAllMandatoryCNIdent) != FALSE) { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational2; } else { EPL_MCO_GLB_VAR (m_fTimerMsPreOp2) = TRUE; } break; } default: { break; } } // end of switch(NmtEvent) break; } // MN process full epl cycle case kEplNmtMsPreOperational2: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // EPL frames received case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // other MN in network // $$$ d.k.: generate error history entry EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // error occured case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; break; } case kEplNmtEventEnterReadyToOperate: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsReadyToOperate; break; } default: { break; } } // end of switch(NmtEvent) break; } // all madatory nodes ready to operate // -> MN process full epl cycle case kEplNmtMsReadyToOperate: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // EPL frames received case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // other MN in network // $$$ d.k.: generate error history entry EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // error occured case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; break; } case kEplNmtEventEnterMsOperational: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsOperational; break; } default: { break; } } // end of switch(NmtEvent) break; } // normal eplcycle processing case kEplNmtMsOperational: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // EPL frames received case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // other MN in network // $$$ d.k.: generate error history entry EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // error occured case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtMsPreOperational1; break; } default: { break; } } // end of switch(NmtEvent) break; } // normal ethernet traffic case kEplNmtMsBasicEthernet: { // check events switch (NmtEvent) { // NMT Command SwitchOff case kEplNmtEventCriticalError: case kEplNmtEventSwitchOff: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsOff; break; } // NMT Command SwReset case kEplNmtEventSwReset: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsInitialising; break; } // NMT Command ResetNode case kEplNmtEventResetNode: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; break; } // NMT Command ResetCommunication // or internal Communication error case kEplNmtEventResetCom: case kEplNmtEventInternComError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // NMT Command ResetConfiguration case kEplNmtEventResetConfig: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetConfiguration; break; } // EPL frames received case kEplNmtEventDllCeSoc: case kEplNmtEventDllCeSoa: { // other MN in network // $$$ d.k.: generate error history entry EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetCommunication; break; } // error occured // d.k. BE->PreOp1 on cycle error? No /* case kEplNmtEventNmtCycleError: { EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtCsPreOperational1; break; } */ default: { break; } } // end of switch(NmtEvent) break; } #endif //#if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) default: { //DEBUG_EPL_DBGLVL_NMTK_TRACE0(EPL_DBGLVL_NMT ,"Error in EplNmtProcess: Unknown NMT-State"); //EPL_MCO_GLB_VAR(m_NmtState) = kEplNmtGsResetApplication; Ret = kEplNmtInvalidState; goto Exit; } } // end of switch(NmtEvent) // inform higher layer about State-Change if needed if (OldNmtState != EPL_MCO_GLB_VAR(m_NmtState)) { EPL_NMTK_DBG_POST_TRACE_VALUE(NmtEvent, OldNmtState, EPL_MCO_GLB_VAR(m_NmtState)); // d.k.: memorize NMT state before posting any events NmtStateChange.m_NewNmtState = EPL_MCO_GLB_VAR(m_NmtState); // inform DLL if ((OldNmtState > kEplNmtGsResetConfiguration) && (EPL_MCO_GLB_VAR(m_NmtState) <= kEplNmtGsResetConfiguration)) { // send DLL DEINIT Event.m_EventSink = kEplEventSinkDllk; Event.m_EventType = kEplEventTypeDllkDestroy; EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); Event.m_pArg = &OldNmtState; Event.m_uiSize = sizeof(OldNmtState); // d.k.: directly call DLLk process function, because // 1. execution of process function is still synchonized and serialized, // 2. it is the same as without event queues (i.e. well tested), // 3. DLLk will get those necessary events even if event queue is full, // 4. event queue is very inefficient #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkProcess(&Event); #else Ret = EplEventkPost(&Event); #endif } else if ((OldNmtState <= kEplNmtGsResetConfiguration) && (EPL_MCO_GLB_VAR(m_NmtState) > kEplNmtGsResetConfiguration)) { // send DLL INIT Event.m_EventSink = kEplEventSinkDllk; Event.m_EventType = kEplEventTypeDllkCreate; EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); Event.m_pArg = &NmtStateChange.m_NewNmtState; Event.m_uiSize = sizeof(NmtStateChange.m_NewNmtState); // d.k.: directly call DLLk process function, because // 1. execution of process function is still synchonized and serialized, // 2. it is the same as without event queues (i.e. well tested), // 3. DLLk will get those necessary events even if event queue is full // 4. event queue is very inefficient #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkProcess(&Event); #else Ret = EplEventkPost(&Event); #endif } else if ((EPL_MCO_GLB_VAR(m_NmtState) == kEplNmtCsBasicEthernet) || (EPL_MCO_GLB_VAR(m_NmtState) == kEplNmtMsBasicEthernet)) { tEplDllAsyncReqPriority AsyncReqPriority; // send DLL Fill Async Tx Buffer, because state BasicEthernet was entered Event.m_EventSink = kEplEventSinkDllk; Event.m_EventType = kEplEventTypeDllkFillTx; EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); AsyncReqPriority = kEplDllAsyncReqPrioGeneric; Event.m_pArg = &AsyncReqPriority; Event.m_uiSize = sizeof(AsyncReqPriority); // d.k.: directly call DLLk process function, because // 1. execution of process function is still synchonized and serialized, // 2. it is the same as without event queues (i.e. well tested), // 3. DLLk will get those necessary events even if event queue is full // 4. event queue is very inefficient #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkProcess(&Event); #else Ret = EplEventkPost(&Event); #endif } // inform higher layer about state change NmtStateChange.m_NmtEvent = NmtEvent; Event.m_EventSink = kEplEventSinkNmtu; Event.m_EventType = kEplEventTypeNmtStateChange; EPL_MEMSET(&Event.m_NetTime, 0x00, sizeof(Event.m_NetTime)); Event.m_pArg = &NmtStateChange; Event.m_uiSize = sizeof(NmtStateChange); Ret = EplEventkPost(&Event); EPL_DBGLVL_NMTK_TRACE2 ("EplNmtkProcess(NMT-Event = 0x%04X): New NMT-State = 0x%03X\n", NmtEvent, NmtStateChange.m_NewNmtState); } Exit: return Ret; } //--------------------------------------------------------------------------- // // Function: EplNmtkGetNmtState // // Description: return the actuell NMT-State and the bits // to for MN- or CN-mode // // // // Parameters: EPL_MCO_DECL_PTR_INSTANCE_PTR_ = Instancepointer // // // Returns: tEplNmtState = NMT-State // // // State: // //--------------------------------------------------------------------------- EPLDLLEXPORT tEplNmtState PUBLIC EplNmtkGetNmtState(EPL_MCO_DECL_PTR_INSTANCE_PTR) { tEplNmtState NmtState; NmtState = EPL_MCO_GLB_VAR(m_NmtState); return NmtState; } //=========================================================================// // // // P R I V A T E D E F I N I T I O N S // // // //=========================================================================// EPL_MCO_DECL_INSTANCE_FCT() //--------------------------------------------------------------------------- // // Function: // // Description: // // // // Parameters: // // // Returns: // // // State: // //--------------------------------------------------------------------------- #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) // EOF