1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: source file for NMT-MN-Module
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
23 3. Neither the name of SYSTEC electronic GmbH nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without prior written permission. For written
26 permission, please contact info@systec-electronic.com.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
43 If a provision of this License is or becomes illegal, invalid or
44 unenforceable in any jurisdiction, that shall not affect:
45 1. the validity or enforceability in that jurisdiction of any other
46 provision of this License; or
47 2. the validity or enforceability in other jurisdictions of that or
48 any other provision of this License.
50 -------------------------------------------------------------------------
52 $RCSfile: EplNmtMnu.c,v $
56 $Revision: 1.18 $ $Date: 2008/11/19 09:52:24 $
63 -------------------------------------------------------------------------
67 2006/06/09 k.t.: start of the implementation
69 ****************************************************************************/
71 #include "user/EplNmtMnu.h"
72 #include "user/EplTimeru.h"
73 #include "user/EplIdentu.h"
74 #include "user/EplStatusu.h"
75 #include "user/EplObdu.h"
76 #include "user/EplDlluCal.h"
77 #include "Benchmark.h"
79 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
81 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
82 #error "EPL NmtMnu module needs EPL module OBDU or OBDK!"
85 //=========================================================================//
87 // P R I V A T E D E F I N I T I O N S //
89 //=========================================================================//
91 //---------------------------------------------------------------------------
93 //---------------------------------------------------------------------------
95 // TracePoint support for realtime-debugging
96 #ifdef _DBG_TRACE_POINTS_
97 void TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
98 void TgtDbgPostTraceValue(u32 dwTraceValue_p);
99 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
100 #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
102 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
103 #define TGT_DBG_POST_TRACE_VALUE(v)
105 #define EPL_NMTMNU_DBG_POST_TRACE_VALUE(Event_p, uiNodeId_p, wErrorCode_p) \
106 TGT_DBG_POST_TRACE_VALUE((kEplEventSinkNmtMnu << 28) | (Event_p << 24) \
107 | (uiNodeId_p << 16) | wErrorCode_p)
109 // defines for flags in node info structure
110 #define EPL_NMTMNU_NODE_FLAG_ISOCHRON 0x0001 // CN is being accessed isochronously
111 #define EPL_NMTMNU_NODE_FLAG_NOT_SCANNED 0x0002 // CN was not scanned once -> decrement SignalCounter and reset flag
112 #define EPL_NMTMNU_NODE_FLAG_HALTED 0x0004 // boot process for this CN is halted
113 #define EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED 0x0008 // NMT command was just issued, wrong NMT states will be tolerated
114 #define EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ 0x0300 // counter for StatusRequest timer handle
115 #define EPL_NMTMNU_NODE_FLAG_COUNT_LONGER 0x0C00 // counter for longer timeouts timer handle
116 #define EPL_NMTMNU_NODE_FLAG_INC_STATREQ 0x0100 // increment for StatusRequest timer handle
117 #define EPL_NMTMNU_NODE_FLAG_INC_LONGER 0x0400 // increment for longer timeouts timer handle
118 // These counters will be incremented at every timer start
119 // and copied to timerarg. When the timer event occures
120 // both will be compared and if unequal the timer event
121 // will be discarded, because it is an old one.
123 // defines for timer arguments to draw a distinction between serveral events
124 #define EPL_NMTMNU_TIMERARG_NODE_MASK 0x000000FFL // mask that contains the node-ID
125 #define EPL_NMTMNU_TIMERARG_IDENTREQ 0x00010000L // timer event is for IdentRequest
126 #define EPL_NMTMNU_TIMERARG_STATREQ 0x00020000L // timer event is for StatusRequest
127 #define EPL_NMTMNU_TIMERARG_LONGER 0x00040000L // timer event is for longer timeouts
128 #define EPL_NMTMNU_TIMERARG_STATE_MON 0x00080000L // timer event for StatusRequest to monitor execution of NMT state changes
129 #define EPL_NMTMNU_TIMERARG_COUNT_SR 0x00000300L // counter for StatusRequest
130 #define EPL_NMTMNU_TIMERARG_COUNT_LO 0x00000C00L // counter for longer timeouts
131 // The counters must have the same position as in the node flags above.
133 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
134 pNodeInfo_p->m_wFlags = \
135 ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
136 & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
137 | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
138 TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p | \
139 (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
140 TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
142 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
143 pNodeInfo_p->m_wFlags = \
144 ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
145 & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
146 | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
147 TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p | \
148 (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
149 TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
151 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
152 pNodeInfo_p->m_wFlags = \
153 ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_LONGER) \
154 & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) \
155 | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \
156 TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p | \
157 (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER); \
158 TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
160 #define EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON(pNodeInfo_p, uiNodeId_p, TimerArg_p) \
161 pNodeInfo_p->m_wFlags = \
162 ((pNodeInfo_p->m_wFlags + EPL_NMTMNU_NODE_FLAG_INC_STATREQ) \
163 & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) \
164 | (pNodeInfo_p->m_wFlags & ~EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
165 TimerArg_p.m_ulArg = EPL_NMTMNU_TIMERARG_STATE_MON | uiNodeId_p | \
166 (pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ); \
167 TimerArg_p.m_EventSink = kEplEventSinkNmtMnu;
169 // defines for global flags
170 #define EPL_NMTMNU_FLAG_HALTED 0x0001 // boot process is halted
171 #define EPL_NMTMNU_FLAG_APP_INFORMED 0x0002 // application was informed about possible NMT state change
173 // return pointer to node info structure for specified node ID
174 // d.k. may be replaced by special (hash) function if node ID array is smaller than 254
175 #define EPL_NMTMNU_GET_NODEINFO(uiNodeId_p) (&EplNmtMnuInstance_g.m_aNodeInfo[uiNodeId_p - 1])
177 //---------------------------------------------------------------------------
179 //---------------------------------------------------------------------------
182 kEplNmtMnuIntNodeEventNoIdentResponse = 0x00,
183 kEplNmtMnuIntNodeEventIdentResponse = 0x01,
184 kEplNmtMnuIntNodeEventBoot = 0x02,
185 kEplNmtMnuIntNodeEventExecReset = 0x03,
186 kEplNmtMnuIntNodeEventConfigured = 0x04,
187 kEplNmtMnuIntNodeEventNoStatusResponse = 0x05,
188 kEplNmtMnuIntNodeEventStatusResponse = 0x06,
189 kEplNmtMnuIntNodeEventHeartbeat = 0x07,
190 kEplNmtMnuIntNodeEventNmtCmdSent = 0x08,
191 kEplNmtMnuIntNodeEventTimerIdentReq = 0x09,
192 kEplNmtMnuIntNodeEventTimerStatReq = 0x0A,
193 kEplNmtMnuIntNodeEventTimerStateMon = 0x0B,
194 kEplNmtMnuIntNodeEventTimerLonger = 0x0C,
195 kEplNmtMnuIntNodeEventError = 0x0D,
197 } tEplNmtMnuIntNodeEvent;
200 kEplNmtMnuNodeStateUnknown = 0x00,
201 kEplNmtMnuNodeStateIdentified = 0x01,
202 kEplNmtMnuNodeStateResetConf = 0x02, // CN reset after configuration update
203 kEplNmtMnuNodeStateConfigured = 0x03, // BootStep1 completed
204 kEplNmtMnuNodeStateReadyToOp = 0x04, // BootStep2 completed
205 kEplNmtMnuNodeStateComChecked = 0x05, // Communication checked successfully
206 kEplNmtMnuNodeStateOperational = 0x06, // CN is in NMT state OPERATIONAL
208 } tEplNmtMnuNodeState;
211 tEplTimerHdl m_TimerHdlStatReq; // timer to delay StatusRequests and IdentRequests
212 tEplTimerHdl m_TimerHdlLonger; // 2nd timer for NMT command EnableReadyToOp and CheckCommunication
213 tEplNmtMnuNodeState m_NodeState; // internal node state (kind of sub state of NMT state)
214 u32 m_dwNodeCfg; // subindex from 0x1F81
215 u16 m_wFlags; // flags: CN is being accessed isochronously
217 } tEplNmtMnuNodeInfo;
220 tEplNmtMnuNodeInfo m_aNodeInfo[EPL_NMT_MAX_NODE_ID];
221 tEplTimerHdl m_TimerHdlNmtState; // timeout for stay in NMT state
222 unsigned int m_uiMandatorySlaveCount;
223 unsigned int m_uiSignalSlaveCount;
224 unsigned long m_ulStatusRequestDelay; // in [ms] (object 0x1006 * EPL_C_NMT_STATREQ_CYCLE)
225 unsigned long m_ulTimeoutReadyToOp; // in [ms] (object 0x1F89/5)
226 unsigned long m_ulTimeoutCheckCom; // in [ms] (object 0x1006 * MultiplexedCycleCount)
227 u16 m_wFlags; // global flags
228 u32 m_dwNmtStartup; // object 0x1F80 NMT_StartUp_U32
229 tEplNmtMnuCbNodeEvent m_pfnCbNodeEvent;
230 tEplNmtMnuCbBootEvent m_pfnCbBootEvent;
232 } tEplNmtMnuInstance;
234 //---------------------------------------------------------------------------
236 //---------------------------------------------------------------------------
238 static tEplNmtMnuInstance EplNmtMnuInstance_g;
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
244 static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p);
246 static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
247 tEplIdentResponse *pIdentResponse_p);
249 static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
250 tEplStatusResponse *pStatusResponse_p);
252 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
253 tEplNmtMnuNodeInfo * pNodeInfo_p,
254 tEplNmtState NodeNmtState_p,
256 tEplNmtState LocalNmtState_p);
258 static tEplKernel EplNmtMnuStartBootStep1(void);
260 static tEplKernel EplNmtMnuStartBootStep2(void);
262 static tEplKernel EplNmtMnuStartCheckCom(void);
264 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
265 tEplNmtMnuNodeInfo * pNodeInfo_p);
267 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
268 tEplNmtMnuNodeInfo * pNodeInfo_p);
270 static tEplKernel EplNmtMnuStartNodes(void);
272 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
273 tEplNmtState NodeNmtState_p,
275 tEplNmtMnuIntNodeEvent
278 static tEplKernel EplNmtMnuReset(void);
280 //=========================================================================//
282 // P U B L I C F U N C T I O N S //
284 //=========================================================================//
286 //---------------------------------------------------------------------------
288 // Function: EplNmtMnuInit
290 // Description: init first instance of the module
297 // Returns: tEplKernel = errorcode
302 //---------------------------------------------------------------------------
304 tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
305 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
309 Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p);
314 //---------------------------------------------------------------------------
316 // Function: EplNmtMnuAddInstance
318 // Description: init other instances of the module
325 // Returns: tEplKernel = errorcode
330 //---------------------------------------------------------------------------
332 tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
333 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
337 Ret = kEplSuccessful;
339 // reset instance structure
340 EPL_MEMSET(&EplNmtMnuInstance_g, 0, sizeof(EplNmtMnuInstance_g));
342 if ((pfnCbNodeEvent_p == NULL) || (pfnCbBootEvent_p == NULL)) {
343 Ret = kEplNmtInvalidParam;
346 EplNmtMnuInstance_g.m_pfnCbNodeEvent = pfnCbNodeEvent_p;
347 EplNmtMnuInstance_g.m_pfnCbBootEvent = pfnCbBootEvent_p;
349 // initialize StatusRequest delay
350 EplNmtMnuInstance_g.m_ulStatusRequestDelay = 5000L;
352 // register NmtMnResponse callback function
354 EplDlluCalRegAsndService(kEplDllAsndNmtRequest,
355 EplNmtMnuCbNmtRequest,
356 kEplDllAsndFilterLocal);
363 //---------------------------------------------------------------------------
365 // Function: EplNmtMnuDelInstance
367 // Description: delete instance
374 // Returns: tEplKernel = errorcode
379 //---------------------------------------------------------------------------
381 tEplKernel EplNmtMnuDelInstance(void)
385 Ret = kEplSuccessful;
387 // deregister NmtMnResponse callback function
389 EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL,
390 kEplDllAsndFilterNone);
392 Ret = EplNmtMnuReset();
398 //---------------------------------------------------------------------------
400 // Function: EplNmtMnuSendNmtCommandEx
402 // Description: sends the specified NMT command to the specified node.
404 // Parameters: uiNodeId_p = node ID to which the NMT command will be sent
405 // NmtCommand_p = NMT command
407 // Returns: tEplKernel = error code
411 //---------------------------------------------------------------------------
413 tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p,
414 tEplNmtCommand NmtCommand_p,
415 void *pNmtCommandData_p,
416 unsigned int uiDataSize_p)
418 tEplKernel Ret = kEplSuccessful;
419 tEplFrameInfo FrameInfo;
420 u8 abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT];
421 tEplFrame *pFrame = (tEplFrame *) abBuffer;
422 BOOL fSoftDeleteNode = FALSE;
424 if ((uiNodeId_p == 0) || (uiNodeId_p > EPL_C_ADR_BROADCAST)) { // invalid node ID specified
425 Ret = kEplInvalidNodeId;
429 if ((pNmtCommandData_p != NULL)
431 (EPL_C_DLL_MINSIZE_NMTCMDEXT - EPL_C_DLL_MINSIZE_NMTCMD))) {
432 Ret = kEplNmtInvalidParam;
435 // $$$ d.k. may be check in future versions if the caller wants to perform prohibited state transitions
436 // the CN should not perform these transitions, but the expected NMT state will be changed and never fullfilled.
439 EPL_MEMSET(pFrame, 0x00, sizeof(abBuffer));
440 AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (u8) uiNodeId_p);
441 AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
442 (u8) kEplDllAsndNmtCommand);
443 AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
444 m_le_bNmtCommandId, (u8) NmtCommand_p);
445 if ((pNmtCommandData_p != NULL) && (uiDataSize_p > 0)) { // copy command data to frame
446 EPL_MEMCPY(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
447 m_le_abNmtCommandData[0], pNmtCommandData_p,
450 // build info structure
451 FrameInfo.m_NetTime.m_dwNanoSec = 0;
452 FrameInfo.m_NetTime.m_dwSec = 0;
453 FrameInfo.m_pFrame = pFrame;
454 FrameInfo.m_uiFrameSize = sizeof(abBuffer);
457 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
458 Ret = EplDlluCalAsyncSend(&FrameInfo, // pointer to frameinfo
459 kEplDllAsyncReqPrioNmt); // priority
461 if (Ret != kEplSuccessful) {
465 EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p,
468 switch (NmtCommand_p) {
469 case kEplNmtCmdStartNode:
470 case kEplNmtCmdEnterPreOperational2:
471 case kEplNmtCmdEnableReadyToOperate:
473 // nothing left to do,
474 // because any further processing is done
475 // when the NMT command is actually sent
479 case kEplNmtCmdStopNode:
481 fSoftDeleteNode = TRUE;
485 case kEplNmtCmdResetNode:
486 case kEplNmtCmdResetCommunication:
487 case kEplNmtCmdResetConfiguration:
488 case kEplNmtCmdSwReset:
497 // remove CN from isochronous phase;
498 // This must be done here and not when NMT command is actually sent
499 // because it will be too late and may cause unwanted errors
500 if (uiNodeId_p != EPL_C_ADR_BROADCAST) {
501 if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
502 Ret = EplDlluCalDeleteNode(uiNodeId_p);
503 } else { // remove CN from isochronous phase softly
504 Ret = EplDlluCalSoftDeleteNode(uiNodeId_p);
506 } else { // do it for all active CNs
508 uiNodeId_p <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
510 if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId_p)->
511 m_dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN |
512 EPL_NODEASSIGN_NODE_EXISTS)) != 0) {
513 if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
514 Ret = EplDlluCalDeleteNode(uiNodeId_p);
515 } else { // remove CN from isochronous phase softly
517 EplDlluCalSoftDeleteNode
528 //---------------------------------------------------------------------------
530 // Function: EplNmtMnuSendNmtCommand
532 // Description: sends the specified NMT command to the specified node.
534 // Parameters: uiNodeId_p = node ID to which the NMT command will be sent
535 // NmtCommand_p = NMT command
537 // Returns: tEplKernel = error code
541 //---------------------------------------------------------------------------
543 tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p,
544 tEplNmtCommand NmtCommand_p)
546 tEplKernel Ret = kEplSuccessful;
548 Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, NmtCommand_p, NULL, 0);
554 //---------------------------------------------------------------------------
556 // Function: EplNmtMnuTriggerStateChange
558 // Description: triggers the specified node command for the specified node.
560 // Parameters: uiNodeId_p = node ID for which the node command will be executed
561 // NodeCommand_p = node command
563 // Returns: tEplKernel = error code
567 //---------------------------------------------------------------------------
569 tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,
570 tEplNmtNodeCommand NodeCommand_p)
572 tEplKernel Ret = kEplSuccessful;
573 tEplNmtMnuIntNodeEvent NodeEvent;
576 u16 wErrorCode = EPL_E_NO_ERROR;
578 if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) {
579 Ret = kEplInvalidNodeId;
583 switch (NodeCommand_p) {
584 case kEplNmtNodeCommandBoot:
586 NodeEvent = kEplNmtMnuIntNodeEventBoot;
590 case kEplNmtNodeCommandConfOk:
592 NodeEvent = kEplNmtMnuIntNodeEventConfigured;
596 case kEplNmtNodeCommandConfErr:
598 NodeEvent = kEplNmtMnuIntNodeEventError;
599 wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY;
603 case kEplNmtNodeCommandConfReset:
605 NodeEvent = kEplNmtMnuIntNodeEventExecReset;
610 { // invalid node command
615 // fetch current NMT state
617 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize);
618 if (Ret != kEplSuccessful) {
622 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
623 (tEplNmtState) (bNmtState |
625 wErrorCode, NodeEvent);
631 //---------------------------------------------------------------------------
633 // Function: EplNmtMnuCbNmtStateChange
635 // Description: callback function for NMT state changes
637 // Parameters: NmtStateChange_p = NMT state change event
639 // Returns: tEplKernel = error code
644 //---------------------------------------------------------------------------
646 tEplKernel EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p)
648 tEplKernel Ret = kEplSuccessful;
650 // do work which must be done in that state
651 switch (NmtStateChange_p.m_NewNmtState) {
652 // EPL stack is not running
653 /* case kEplNmtGsOff:
656 // first init of the hardware
657 case kEplNmtGsInitialising:
660 // init of the manufacturer-specific profile area and the
661 // standardised device profile area
662 case kEplNmtGsResetApplication:
667 // init of the communication profile area
668 case kEplNmtGsResetCommunication:
673 // build the configuration with infos from OD
674 case kEplNmtGsResetConfiguration:
679 // read object 0x1F80 NMT_StartUp_U32
682 EplObduReadEntry(0x1F80, 0,
683 &EplNmtMnuInstance_g.
684 m_dwNmtStartup, &ObdSize);
685 if (Ret != kEplSuccessful) {
688 // compute StatusReqDelay = object 0x1006 * EPL_C_NMT_STATREQ_CYCLE
689 ObdSize = sizeof(dwTimeout);
690 Ret = EplObduReadEntry(0x1006, 0, &dwTimeout, &ObdSize);
691 if (Ret != kEplSuccessful) {
694 if (dwTimeout != 0L) {
695 EplNmtMnuInstance_g.m_ulStatusRequestDelay =
696 dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
697 if (EplNmtMnuInstance_g.
698 m_ulStatusRequestDelay == 0L) {
699 EplNmtMnuInstance_g.m_ulStatusRequestDelay = 1L; // at least 1 ms
701 // $$$ fetch and use MultiplexedCycleCount from OD
702 EplNmtMnuInstance_g.m_ulTimeoutCheckCom =
703 dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
704 if (EplNmtMnuInstance_g.m_ulTimeoutCheckCom ==
706 EplNmtMnuInstance_g.m_ulTimeoutCheckCom = 1L; // at least 1 ms
709 // fetch ReadyToOp Timeout from OD
710 ObdSize = sizeof(dwTimeout);
711 Ret = EplObduReadEntry(0x1F89, 5, &dwTimeout, &ObdSize);
712 if (Ret != kEplSuccessful) {
715 if (dwTimeout != 0L) {
716 // convert [us] to [ms]
718 if (dwTimeout == 0L) {
719 dwTimeout = 1L; // at least 1 ms
721 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp =
724 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L;
729 //-----------------------------------------------------------
730 // CN part of the state machine
732 // node liste for EPL-Frames and check timeout
733 case kEplNmtCsNotActive:
738 // node process only async frames
739 case kEplNmtCsPreOperational1:
744 // node process isochronus and asynchronus frames
745 case kEplNmtCsPreOperational2:
750 // node should be configured und application is ready
751 case kEplNmtCsReadyToOperate:
757 case kEplNmtCsOperational:
762 // node stopped by MN
763 // -> only process asynchronus frames
764 case kEplNmtCsStopped:
770 // -> normal ethernet communication
771 case kEplNmtCsBasicEthernet:
776 //-----------------------------------------------------------
777 // MN part of the state machine
779 // node listens for EPL-Frames and check timeout
780 case kEplNmtMsNotActive:
785 // node processes only async frames
786 case kEplNmtMsPreOperational1:
789 tEplTimerArg TimerArg;
793 // clear global flags, e.g. reenable boot process
794 EplNmtMnuInstance_g.m_wFlags = 0;
796 // reset IdentResponses and running IdentRequests and StatusRequests
797 Ret = EplIdentuReset();
798 Ret = EplStatusuReset();
801 Ret = EplNmtMnuReset();
803 // 2008/11/18 d.k. reset internal node info is not necessary,
804 // because timer flags are important and other
805 // things are reset by EplNmtMnuStartBootStep1().
807 EPL_MEMSET(EplNmtMnuInstance_g.m_aNodeInfo,
809 sizeof (EplNmtMnuInstance_g.m_aNodeInfo));
812 // inform DLL about NMT state change,
813 // so that it can clear the asynchonous queues and start the reduced cycle
814 Event.m_EventSink = kEplEventSinkDllk;
815 Event.m_EventType = kEplEventTypeDllkStartReducedCycle;
816 EPL_MEMSET(&Event.m_NetTime, 0x00,
817 sizeof(Event.m_NetTime));
820 Ret = EplEventuPost(&Event);
821 if (Ret != kEplSuccessful) {
825 // d.k.: skip this step if was just done before, e.g. because of a ResetNode command from a diagnostic node
826 if (NmtStateChange_p.m_NmtEvent ==
827 kEplNmtEventTimerMsPreOp1) {
828 BENCHMARK_MOD_07_TOGGLE(9);
830 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
832 kEplNmtCmdResetNode);
835 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
836 kEplNmtCmdResetNode);
837 if (Ret != kEplSuccessful) {
841 // start network scan
842 Ret = EplNmtMnuStartBootStep1();
844 // start timer for 0x1F89/2 MNTimeoutPreOp1_U32
845 ObdSize = sizeof(dwTimeout);
846 Ret = EplObduReadEntry(0x1F89, 2, &dwTimeout, &ObdSize);
847 if (Ret != kEplSuccessful) {
850 if (dwTimeout != 0L) {
852 if (dwTimeout == 0L) {
853 dwTimeout = 1L; // at least 1 ms
855 TimerArg.m_EventSink = kEplEventSinkNmtMnu;
856 TimerArg.m_ulArg = 0;
858 EplTimeruModifyTimerMs(&EplNmtMnuInstance_g.
860 dwTimeout, TimerArg);
865 // node processes isochronous and asynchronous frames
866 case kEplNmtMsPreOperational2:
868 // add identified CNs to isochronous phase
869 // send EnableReadyToOp to all identified CNs
870 Ret = EplNmtMnuStartBootStep2();
872 // wait for NMT state change of CNs
876 // node should be configured und application is ready
877 case kEplNmtMsReadyToOperate:
879 // check if PRes of CNs are OK
880 // d.k. that means wait CycleLength * MultiplexCycleCount (i.e. start timer)
881 // because Dllk checks PRes of CNs automatically in ReadyToOp
882 Ret = EplNmtMnuStartCheckCom();
887 case kEplNmtMsOperational:
889 // send StartNode to CNs
890 // wait for NMT state change of CNs
891 Ret = EplNmtMnuStartNodes();
896 // -> normal ethernet communication
897 case kEplNmtMsBasicEthernet:
904 // TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n");
911 //---------------------------------------------------------------------------
913 // Function: EplNmtMnuCbCheckEvent
915 // Description: callback funktion for NMT events before they are actually executed.
916 // The EPL API layer must forward NMT events from NmtCnu module.
917 // This module will reject some NMT commands while MN.
919 // Parameters: NmtEvent_p = outstanding NMT event for approval
921 // Returns: tEplKernel = error code
922 // kEplReject = reject the NMT event
926 //---------------------------------------------------------------------------
928 tEplKernel EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p)
930 tEplKernel Ret = kEplSuccessful;
935 //---------------------------------------------------------------------------
937 // Function: EplNmtuProcessEvent
939 // Description: processes events from event queue
941 // Parameters: pEvent_p = pointer to event
943 // Returns: tEplKernel = errorcode
947 //---------------------------------------------------------------------------
949 EPLDLLEXPORT tEplKernel EplNmtMnuProcessEvent(tEplEvent *pEvent_p)
953 Ret = kEplSuccessful;
956 switch (pEvent_p->m_EventType) {
958 case kEplEventTypeTimer:
960 tEplTimerEventArg *pTimerEventArg =
961 (tEplTimerEventArg *) pEvent_p->m_pArg;
962 unsigned int uiNodeId;
965 (unsigned int)(pTimerEventArg->
967 EPL_NMTMNU_TIMERARG_NODE_MASK);
971 tEplNmtMnuNodeInfo *pNodeInfo;
973 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId);
977 EplObduReadEntry(0x1F8E, uiNodeId,
978 &bNmtState, &ObdSize);
979 if (Ret != kEplSuccessful) {
983 if ((pTimerEventArg->
984 m_ulArg & EPL_NMTMNU_TIMERARG_IDENTREQ) !=
988 EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
989 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
990 // but not the current timer
992 EPL_NMTMNU_DBG_POST_TRACE_VALUE
993 (kEplNmtMnuIntNodeEventTimerIdentReq,
1002 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq,
1004 ((pNodeInfo->m_NodeState << 8)
1006 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1007 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1010 EplNmtMnuProcessInternalEvent
1012 (tEplNmtState) (bNmtState |
1015 kEplNmtMnuIntNodeEventTimerIdentReq);
1018 else if ((pTimerEventArg->
1019 m_ulArg & EPL_NMTMNU_TIMERARG_STATREQ)
1023 EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
1024 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
1025 // but not the current timer
1027 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1028 (kEplNmtMnuIntNodeEventTimerStatReq,
1037 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1039 ((pNodeInfo->m_NodeState << 8)
1041 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1042 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1045 EplNmtMnuProcessInternalEvent
1047 (tEplNmtState) (bNmtState |
1050 kEplNmtMnuIntNodeEventTimerStatReq);
1053 else if ((pTimerEventArg->
1055 EPL_NMTMNU_TIMERARG_STATE_MON) !=
1059 EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
1060 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
1061 // but not the current timer
1063 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1064 (kEplNmtMnuIntNodeEventTimerStateMon,
1073 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1075 ((pNodeInfo->m_NodeState << 8)
1077 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1078 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1081 EplNmtMnuProcessInternalEvent
1083 (tEplNmtState) (bNmtState |
1086 kEplNmtMnuIntNodeEventTimerStateMon);
1089 else if ((pTimerEventArg->
1090 m_ulArg & EPL_NMTMNU_TIMERARG_LONGER)
1094 EPL_NMTMNU_NODE_FLAG_COUNT_LONGER)
1095 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO)) { // this is an old (already deleted or modified) timer
1096 // but not the current timer
1098 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1099 (kEplNmtMnuIntNodeEventTimerLonger,
1108 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger,
1110 ((pNodeInfo->m_NodeState << 8)
1112 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) >> 6)
1113 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO) >> 8)));
1116 EplNmtMnuProcessInternalEvent
1118 (tEplNmtState) (bNmtState |
1121 kEplNmtMnuIntNodeEventTimerLonger);
1124 } else { // global timer event
1129 case kEplEventTypeHeartbeat:
1131 tEplHeartbeatEvent *pHeartbeatEvent =
1132 (tEplHeartbeatEvent *) pEvent_p->m_pArg;
1135 EplNmtMnuProcessInternalEvent(pHeartbeatEvent->
1141 kEplNmtMnuIntNodeEventHeartbeat);
1145 case kEplEventTypeNmtMnuNmtCmdSent:
1147 tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg;
1148 unsigned int uiNodeId;
1149 tEplNmtCommand NmtCommand;
1152 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
1154 (tEplNmtCommand) AmiGetByteFromLe(&pFrame->m_Data.
1156 m_NmtCommandService.
1157 m_le_bNmtCommandId);
1159 switch (NmtCommand) {
1160 case kEplNmtCmdStartNode:
1162 (u8) (kEplNmtCsOperational & 0xFF);
1165 case kEplNmtCmdStopNode:
1166 bNmtState = (u8) (kEplNmtCsStopped & 0xFF);
1169 case kEplNmtCmdEnterPreOperational2:
1171 (u8) (kEplNmtCsPreOperational2 & 0xFF);
1174 case kEplNmtCmdEnableReadyToOperate:
1175 // d.k. do not change expected node state, because of DS 1.0.0 7.3.1.2.1 Plain NMT State Command
1176 // and because node may not change NMT state within EPL_C_NMT_STATE_TOLERANCE
1178 (u8) (kEplNmtCsPreOperational2 & 0xFF);
1181 case kEplNmtCmdResetNode:
1182 case kEplNmtCmdResetCommunication:
1183 case kEplNmtCmdResetConfiguration:
1184 case kEplNmtCmdSwReset:
1185 bNmtState = (u8) (kEplNmtCsNotActive & 0xFF);
1186 // EplNmtMnuProcessInternalEvent() sets internal node state to kEplNmtMnuNodeStateUnknown
1187 // after next unresponded IdentRequest/StatusRequest
1194 // process as internal event which update expected NMT state in OD
1195 if (uiNodeId != EPL_C_ADR_BROADCAST) {
1196 Ret = EplNmtMnuProcessInternalEvent(uiNodeId,
1201 kEplNmtMnuIntNodeEventNmtCmdSent);
1203 } else { // process internal event for all active nodes (except myself)
1207 tabentries(EplNmtMnuInstance_g.
1208 m_aNodeInfo); uiNodeId++) {
1209 if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId)->
1211 (EPL_NODEASSIGN_NODE_IS_CN |
1212 EPL_NODEASSIGN_NODE_EXISTS)) !=
1215 EplNmtMnuProcessInternalEvent
1217 (tEplNmtState) (bNmtState |
1220 kEplNmtMnuIntNodeEventNmtCmdSent);
1222 if (Ret != kEplSuccessful) {
1234 Ret = kEplNmtInvalidEvent;
1243 //---------------------------------------------------------------------------
1245 // Function: EplNmtMnuGetRunningTimerStatReq
1247 // Description: returns a bit field with running StatReq timers
1248 // just for debugging purposes
1250 // Parameters: (none)
1252 // Returns: tEplKernel = error code
1256 //---------------------------------------------------------------------------
1258 tEplKernel EplNmtMnuGetDiagnosticInfo(unsigned int *puiMandatorySlaveCount_p,
1259 unsigned int *puiSignalSlaveCount_p,
1262 tEplKernel Ret = kEplSuccessful;
1264 if ((puiMandatorySlaveCount_p == NULL)
1265 || (puiSignalSlaveCount_p == NULL)
1266 || (pwFlags_p == NULL)) {
1267 Ret = kEplNmtInvalidParam;
1271 *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount;
1272 *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount;
1273 *pwFlags_p = EplNmtMnuInstance_g.m_wFlags;
1279 //---------------------------------------------------------------------------
1281 // Function: EplNmtMnuGetRunningTimerStatReq
1283 // Description: returns a bit field with running StatReq timers
1284 // just for debugging purposes
1286 // Parameters: (none)
1288 // Returns: tEplKernel = error code
1292 //---------------------------------------------------------------------------
1294 u32 EplNmtMnuGetRunningTimerStatReq(void)
1296 tEplKernel Ret = kEplSuccessful;
1297 unsigned int uiIndex;
1298 tEplNmtMnuNodeInfo* pNodeInfo;
1300 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1301 for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++)
1303 if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured)
1305 // reset flag "scanned once"
1306 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_SCANNED;
1308 Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1309 if (Ret != kEplSuccessful)
1313 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1314 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1315 // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
1324 //=========================================================================//
1326 // P R I V A T E F U N C T I O N S //
1328 //=========================================================================//
1330 //---------------------------------------------------------------------------
1332 // Function: EplNmtMnuCbNmtRequest
1334 // Description: callback funktion for NmtRequest
1336 // Parameters: pFrameInfo_p = Frame with the NmtRequest
1338 // Returns: tEplKernel = error code
1343 //---------------------------------------------------------------------------
1345 static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p)
1347 tEplKernel Ret = kEplSuccessful;
1349 // $$$ perform NMTRequest
1353 //---------------------------------------------------------------------------
1355 // Function: EplNmtMnuCbIdentResponse
1357 // Description: callback funktion for IdentResponse
1359 // Parameters: uiNodeId_p = node ID for which IdentReponse was received
1360 // pIdentResponse_p = pointer to IdentResponse
1361 // is NULL if node did not answer
1363 // Returns: tEplKernel = error code
1367 //---------------------------------------------------------------------------
1369 static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
1370 tEplIdentResponse *pIdentResponse_p)
1372 tEplKernel Ret = kEplSuccessful;
1374 if (pIdentResponse_p == NULL) { // node did not answer
1375 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_IDENT_RES, // was EPL_E_NO_ERROR
1376 kEplNmtMnuIntNodeEventNoIdentResponse);
1377 } else { // node answered IdentRequest
1378 tEplObdSize ObdSize;
1380 u16 wErrorCode = EPL_E_NO_ERROR;
1381 tEplNmtState NmtState =
1382 (tEplNmtState) (AmiGetByteFromLe
1383 (&pIdentResponse_p->
1384 m_le_bNmtStatus) | EPL_NMT_TYPE_CS);
1386 // check IdentResponse $$$ move to ProcessIntern, because this function may be called also if CN
1388 // check DeviceType (0x1F84)
1391 EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize);
1392 if (Ret != kEplSuccessful) {
1395 if (dwDevType != 0L) { // actually compare it with DeviceType from IdentResponse
1396 if (AmiGetDwordFromLe(&pIdentResponse_p->m_le_dwDeviceType) != dwDevType) { // wrong DeviceType
1397 NmtState = kEplNmtCsNotActive;
1398 wErrorCode = EPL_E_NMT_BPO1_DEVICE_TYPE;
1402 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
1405 kEplNmtMnuIntNodeEventIdentResponse);
1412 //---------------------------------------------------------------------------
1414 // Function: EplNmtMnuCbStatusResponse
1416 // Description: callback funktion for StatusResponse
1418 // Parameters: uiNodeId_p = node ID for which IdentReponse was received
1419 // pIdentResponse_p = pointer to IdentResponse
1420 // is NULL if node did not answer
1422 // Returns: tEplKernel = error code
1426 //---------------------------------------------------------------------------
1428 static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
1429 tEplStatusResponse *pStatusResponse_p)
1431 tEplKernel Ret = kEplSuccessful;
1433 if (pStatusResponse_p == NULL) { // node did not answer
1434 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_STATUS_RES, // was EPL_E_NO_ERROR
1435 kEplNmtMnuIntNodeEventNoStatusResponse);
1436 } else { // node answered StatusRequest
1437 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
1440 (&pStatusResponse_p->
1444 kEplNmtMnuIntNodeEventStatusResponse);
1450 //---------------------------------------------------------------------------
1452 // Function: EplNmtMnuStartBootStep1
1454 // Description: starts BootStep1
1456 // Parameters: (none)
1458 // Returns: tEplKernel = error code
1462 //---------------------------------------------------------------------------
1464 static tEplKernel EplNmtMnuStartBootStep1(void)
1466 tEplKernel Ret = kEplSuccessful;
1467 unsigned int uiSubIndex;
1468 unsigned int uiLocalNodeId;
1470 tEplObdSize ObdSize;
1472 // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32
1474 // start network scan
1475 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1476 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1478 uiLocalNodeId = EplObduGetNodeId();
1479 for (uiSubIndex = 1; uiSubIndex <= 254; uiSubIndex++) {
1482 EplObduReadEntry(0x1F81, uiSubIndex, &dwNodeCfg, &ObdSize);
1483 if (Ret != kEplSuccessful) {
1486 if (uiSubIndex != uiLocalNodeId) {
1487 // reset flags "not scanned" and "isochronous"
1488 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags &=
1489 ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON |
1490 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED);
1492 if (uiSubIndex == EPL_C_ADR_DIAG_DEF_NODE_ID) { // diagnostic node must be scanned by MN in any case
1494 (EPL_NODEASSIGN_NODE_IS_CN |
1495 EPL_NODEASSIGN_NODE_EXISTS);
1496 // and it must be isochronously accessed
1497 dwNodeCfg &= ~EPL_NODEASSIGN_ASYNCONLY_NODE;
1499 // save node config in local node info structure
1500 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_dwNodeCfg =
1502 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_NodeState =
1503 kEplNmtMnuNodeStateUnknown;
1505 if ((dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // node is configured as CN
1506 // identify the node
1508 EplIdentuRequestIdentResponse(uiSubIndex,
1509 EplNmtMnuCbIdentResponse);
1510 if (Ret != kEplSuccessful) {
1513 // set flag "not scanned"
1514 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags |=
1515 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1516 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1517 // signal slave counter shall be decremented if IdentRequest was sent once to a CN
1519 if ((dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1520 EplNmtMnuInstance_g.
1521 m_uiMandatorySlaveCount++;
1522 // mandatory slave counter shall be decremented if mandatory CN was configured successfully
1525 } else { // subindex of MN
1526 if ((dwNodeCfg & (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // MN shall send PRes
1527 tEplDllNodeInfo DllNodeInfo;
1529 EPL_MEMSET(&DllNodeInfo, 0,
1530 sizeof(DllNodeInfo));
1531 DllNodeInfo.m_uiNodeId = uiLocalNodeId;
1533 Ret = EplDlluCalAddNode(&DllNodeInfo);
1542 //---------------------------------------------------------------------------
1544 // Function: EplNmtMnuStartBootStep2
1546 // Description: starts BootStep2.
1547 // That means add nodes to isochronous phase and send
1548 // NMT EnableReadyToOp.
1550 // Parameters: (none)
1552 // Returns: tEplKernel = error code
1556 //---------------------------------------------------------------------------
1558 static tEplKernel EplNmtMnuStartBootStep2(void)
1560 tEplKernel Ret = kEplSuccessful;
1561 unsigned int uiIndex;
1562 tEplNmtMnuNodeInfo *pNodeInfo;
1564 if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
1565 // add nodes to isochronous phase and send NMT EnableReadyToOp
1566 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1567 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1568 // reset flag that application was informed about possible state change
1569 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1571 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1573 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1574 uiIndex++, pNodeInfo++) {
1575 if (pNodeInfo->m_NodeState ==
1576 kEplNmtMnuNodeStateConfigured) {
1578 EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1579 if (Ret != kEplSuccessful) {
1582 // set flag "not scanned"
1583 pNodeInfo->m_wFlags |=
1584 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1586 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1587 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1589 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1590 EplNmtMnuInstance_g.
1591 m_uiMandatorySlaveCount++;
1593 // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
1602 //---------------------------------------------------------------------------
1604 // Function: EplNmtMnuNodeBootStep2
1606 // Description: starts BootStep2 for the specified node.
1607 // This means the CN is added to isochronous phase if not
1608 // async-only and it gets the NMT command EnableReadyToOp.
1609 // The CN must be in node state Configured, when it enters
1610 // BootStep2. When BootStep2 finishes, the CN is in node state
1612 // If TimeoutReadyToOp in object 0x1F89/5 is configured,
1613 // TimerHdlLonger will be started with this timeout.
1615 // Parameters: uiNodeId_p = node ID
1616 // pNodeInfo_p = pointer to internal node info structure
1618 // Returns: tEplKernel = error code
1622 //---------------------------------------------------------------------------
1624 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
1625 tEplNmtMnuNodeInfo * pNodeInfo_p)
1627 tEplKernel Ret = kEplSuccessful;
1628 tEplDllNodeInfo DllNodeInfo;
1630 tEplObdSize ObdSize;
1631 tEplTimerArg TimerArg;
1633 dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
1634 if ((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0) { // add node to isochronous phase
1635 DllNodeInfo.m_uiNodeId = uiNodeId_p;
1638 EplObduReadEntry(0x1F92, uiNodeId_p,
1639 &DllNodeInfo.m_dwPresTimeout, &ObdSize);
1640 if (Ret != kEplSuccessful) {
1646 EplObduReadEntry(0x1F8B, uiNodeId_p,
1647 &DllNodeInfo.m_wPreqPayloadLimit,
1649 if (Ret != kEplSuccessful) {
1655 EplObduReadEntry(0x1F8D, uiNodeId_p,
1656 &DllNodeInfo.m_wPresPayloadLimit,
1658 if (Ret != kEplSuccessful) {
1662 pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON;
1664 Ret = EplDlluCalAddNode(&DllNodeInfo);
1665 if (Ret != kEplSuccessful) {
1671 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1673 kEplNmtCmdEnableReadyToOperate);
1676 EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate);
1677 if (Ret != kEplSuccessful) {
1681 if (EplNmtMnuInstance_g.m_ulTimeoutReadyToOp != 0L) { // start timer
1682 // when the timer expires the CN must be ReadyToOp
1683 EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
1685 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1686 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1688 EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1689 EplNmtMnuInstance_g.
1690 m_ulTimeoutReadyToOp, TimerArg);
1697 //---------------------------------------------------------------------------
1699 // Function: EplNmtMnuStartCheckCom
1701 // Description: starts CheckCommunication
1703 // Parameters: (none)
1705 // Returns: tEplKernel = error code
1709 //---------------------------------------------------------------------------
1711 static tEplKernel EplNmtMnuStartCheckCom(void)
1713 tEplKernel Ret = kEplSuccessful;
1714 unsigned int uiIndex;
1715 tEplNmtMnuNodeInfo *pNodeInfo;
1717 if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
1718 // wait some time and check that no communication error occurs
1719 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1720 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1721 // reset flag that application was informed about possible state change
1722 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1724 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1726 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1727 uiIndex++, pNodeInfo++) {
1728 if (pNodeInfo->m_NodeState ==
1729 kEplNmtMnuNodeStateReadyToOp) {
1730 Ret = EplNmtMnuNodeCheckCom(uiIndex, pNodeInfo);
1731 if (Ret == kEplReject) { // timer was started
1732 // wait until it expires
1733 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1734 EplNmtMnuInstance_g.
1735 m_uiMandatorySlaveCount++;
1737 } else if (Ret != kEplSuccessful) {
1740 // set flag "not scanned"
1741 pNodeInfo->m_wFlags |=
1742 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1744 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1745 // signal slave counter shall be decremented if timeout elapsed and regardless of an error
1746 // mandatory slave counter shall be decremented if timeout elapsed and no error occured
1751 Ret = kEplSuccessful;
1757 //---------------------------------------------------------------------------
1759 // Function: EplNmtMnuNodeCheckCom
1761 // Description: checks communication of the specified node.
1762 // That means wait some time and if no error occured everything
1765 // Parameters: uiNodeId_p = node ID
1766 // pNodeInfo_p = pointer to internal node info structure
1768 // Returns: tEplKernel = error code
1772 //---------------------------------------------------------------------------
1774 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
1775 tEplNmtMnuNodeInfo * pNodeInfo_p)
1777 tEplKernel Ret = kEplSuccessful;
1779 tEplTimerArg TimerArg;
1781 dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
1782 if (((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0)
1783 && (EplNmtMnuInstance_g.m_ulTimeoutCheckCom != 0L)) { // CN is not async-only and timeout for CheckCom was set
1785 // check communication,
1786 // that means wait some time and if no error occured everything is OK;
1788 // start timer (when the timer expires the CN must be still ReadyToOp)
1789 EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
1791 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1792 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1794 EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1795 EplNmtMnuInstance_g.
1796 m_ulTimeoutCheckCom, TimerArg);
1798 // update mandatory slave counter, because timer was started
1799 if (Ret == kEplSuccessful) {
1802 } else { // timer was not started
1803 // assume everything is OK
1804 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked;
1811 //---------------------------------------------------------------------------
1813 // Function: EplNmtMnuStartNodes
1815 // Description: really starts all nodes which are ReadyToOp and CheckCom did not fail
1817 // Parameters: (none)
1819 // Returns: tEplKernel = error code
1823 //---------------------------------------------------------------------------
1825 static tEplKernel EplNmtMnuStartNodes(void)
1827 tEplKernel Ret = kEplSuccessful;
1828 unsigned int uiIndex;
1829 tEplNmtMnuNodeInfo *pNodeInfo;
1831 if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
1832 // send NMT command Start Node
1833 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1834 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1835 // reset flag that application was informed about possible state change
1836 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1838 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1840 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1841 uiIndex++, pNodeInfo++) {
1842 if (pNodeInfo->m_NodeState ==
1843 kEplNmtMnuNodeStateComChecked) {
1844 if ((EplNmtMnuInstance_g.
1845 m_dwNmtStartup & EPL_NMTST_STARTALLNODES)
1847 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1849 kEplNmtCmdStartNode);
1852 EplNmtMnuSendNmtCommand(uiIndex,
1853 kEplNmtCmdStartNode);
1854 if (Ret != kEplSuccessful) {
1859 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1860 EplNmtMnuInstance_g.
1861 m_uiMandatorySlaveCount++;
1863 // set flag "not scanned"
1864 pNodeInfo->m_wFlags |=
1865 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1867 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1868 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1869 // mandatory slave counter shall be decremented if mandatory CN is OPERATIONAL
1873 // $$$ inform application if EPL_NMTST_NO_STARTNODE is set
1875 if ((EplNmtMnuInstance_g.
1876 m_dwNmtStartup & EPL_NMTST_STARTALLNODES) != 0) {
1877 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, EPL_C_ADR_BROADCAST,
1878 kEplNmtCmdStartNode);
1881 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
1882 kEplNmtCmdStartNode);
1883 if (Ret != kEplSuccessful) {
1893 //---------------------------------------------------------------------------
1895 // Function: EplNmtMnuProcessInternalEvent
1897 // Description: processes internal node events
1899 // Parameters: uiNodeId_p = node ID
1900 // NodeNmtState_p = NMT state of CN
1901 // NodeEvent_p = occured events
1903 // Returns: tEplKernel = error code
1908 //---------------------------------------------------------------------------
1910 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
1911 tEplNmtState NodeNmtState_p,
1913 tEplNmtMnuIntNodeEvent
1916 tEplKernel Ret = kEplSuccessful;
1917 tEplNmtState NmtState;
1918 tEplNmtMnuNodeInfo *pNodeInfo;
1919 tEplTimerArg TimerArg;
1921 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId_p);
1922 NmtState = EplNmtuGetNmtState();
1923 if (NmtState <= kEplNmtMsNotActive) { // MN is not active
1927 switch (NodeEvent_p) {
1928 case kEplNmtMnuIntNodeEventIdentResponse:
1932 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1934 pNodeInfo->m_NodeState);
1936 if (pNodeInfo->m_NodeState !=
1937 kEplNmtMnuNodeStateResetConf) {
1938 pNodeInfo->m_NodeState =
1939 kEplNmtMnuNodeStateIdentified;
1941 // reset flags ISOCHRON and NMT_CMD_ISSUED
1942 pNodeInfo->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON
1944 EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED);
1946 if ((NmtState == kEplNmtMsPreOperational1)
1949 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
1951 // decrement only signal slave count
1952 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
1953 pNodeInfo->m_wFlags &=
1954 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1956 // update object 0x1F8F NMT_MNNodeExpState_AU8 to PreOp1 (even if local state >= PreOp2)
1957 bNmtState = (u8) (kEplNmtCsPreOperational1 & 0xFF);
1959 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
1962 // check NMT state of CN
1964 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
1965 NodeNmtState_p, wErrorCode_p,
1967 if (Ret != kEplSuccessful) {
1968 if (Ret == kEplReject) {
1969 Ret = kEplSuccessful;
1973 // request StatusResponse immediately,
1974 // because we want a fast boot-up of CNs
1976 EplStatusuRequestStatusResponse(uiNodeId_p,
1977 EplNmtMnuCbStatusResponse);
1978 if (Ret != kEplSuccessful) {
1979 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1983 if (Ret == kEplInvalidOperation) { // the only situation when this should happen is, when
1984 // StatusResponse was already requested from within
1985 // the StatReq timer event.
1986 // so ignore this error.
1987 Ret = kEplSuccessful;
1993 if (pNodeInfo->m_NodeState !=
1994 kEplNmtMnuNodeStateResetConf) {
1995 // inform application
1997 EplNmtMnuInstance_g.
1998 m_pfnCbNodeEvent(uiNodeId_p,
1999 kEplNmtNodeEventFound,
2004 EPL_NODEASSIGN_MANDATORY_CN)
2006 if (Ret == kEplReject) { // interrupt boot process on user request
2007 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2008 (NodeEvent_p, uiNodeId_p,
2009 ((pNodeInfo->m_NodeState << 8)
2012 Ret = kEplSuccessful;
2014 } else if (Ret != kEplSuccessful) {
2015 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2016 (NodeEvent_p, uiNodeId_p,
2017 ((pNodeInfo->m_NodeState << 8)
2023 // continue BootStep1
2026 case kEplNmtMnuIntNodeEventBoot:
2029 // $$$ check identification (vendor ID, product code, revision no, serial no)
2031 if (pNodeInfo->m_NodeState ==
2032 kEplNmtMnuNodeStateIdentified) {
2033 // $$$ check software
2035 // check/start configuration
2036 // inform application
2038 EplNmtMnuInstance_g.
2039 m_pfnCbNodeEvent(uiNodeId_p,
2040 kEplNmtNodeEventCheckConf,
2045 EPL_NODEASSIGN_MANDATORY_CN)
2047 if (Ret == kEplReject) { // interrupt boot process on user request
2048 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2049 (kEplNmtMnuIntNodeEventBoot,
2051 ((pNodeInfo->m_NodeState << 8)
2054 Ret = kEplSuccessful;
2056 } else if (Ret != kEplSuccessful) {
2057 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2058 (kEplNmtMnuIntNodeEventBoot,
2060 ((pNodeInfo->m_NodeState << 8)
2065 } else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) { // wrong CN state
2069 // $$$ d.k.: currently we assume configuration is OK
2071 // continue BootStep1
2074 case kEplNmtMnuIntNodeEventConfigured:
2076 if ((pNodeInfo->m_NodeState !=
2077 kEplNmtMnuNodeStateIdentified)
2078 && (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf)) { // wrong CN state
2083 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateConfigured;
2085 if (NmtState == kEplNmtMsPreOperational1) {
2086 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // decrement mandatory CN counter
2087 EplNmtMnuInstance_g.
2088 m_uiMandatorySlaveCount--;
2091 // put optional node to next step (BootStep2)
2093 EplNmtMnuNodeBootStep2(uiNodeId_p,
2099 case kEplNmtMnuIntNodeEventNoIdentResponse:
2101 if ((NmtState == kEplNmtMsPreOperational1)
2104 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2106 // decrement only signal slave count
2107 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2108 pNodeInfo->m_wFlags &=
2109 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2112 if (pNodeInfo->m_NodeState !=
2113 kEplNmtMnuNodeStateResetConf) {
2114 pNodeInfo->m_NodeState =
2115 kEplNmtMnuNodeStateUnknown;
2117 // $$$ d.k. check start time for 0x1F89/2 MNTimeoutPreOp1_U32
2118 // $$$ d.k. check individual timeout 0x1F89/6 MNIdentificationTimeout_U32
2119 // if mandatory node and timeout elapsed -> halt boot procedure
2120 // trigger IdentRequest again (if >= PreOp2, after delay)
2121 if (NmtState >= kEplNmtMsPreOperational2) { // start timer
2122 EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
2123 (pNodeInfo, uiNodeId_p, TimerArg);
2124 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2125 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p;
2127 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventNoIdentResponse,
2129 ((pNodeInfo->m_NodeState << 8)
2131 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2132 | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2135 EplTimeruModifyTimerMs(&pNodeInfo->
2137 EplNmtMnuInstance_g.
2138 m_ulStatusRequestDelay,
2140 } else { // trigger IdentRequest immediately
2142 EplIdentuRequestIdentResponse(uiNodeId_p,
2143 EplNmtMnuCbIdentResponse);
2148 case kEplNmtMnuIntNodeEventStatusResponse:
2150 if ((NmtState >= kEplNmtMsPreOperational2)
2153 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2155 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2156 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2157 pNodeInfo->m_wFlags &=
2158 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2160 // check NMT state of CN
2162 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2163 NodeNmtState_p, wErrorCode_p,
2165 if (Ret != kEplSuccessful) {
2166 if (Ret == kEplReject) {
2167 Ret = kEplSuccessful;
2172 if (NmtState == kEplNmtMsPreOperational1) {
2173 // request next StatusResponse immediately
2175 EplStatusuRequestStatusResponse(uiNodeId_p,
2176 EplNmtMnuCbStatusResponse);
2177 if (Ret != kEplSuccessful) {
2178 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2179 (NodeEvent_p, uiNodeId_p, Ret);
2182 } else if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_ISOCHRON) == 0) { // start timer
2183 // not isochronously accessed CN (e.g. async-only or stopped CN)
2184 EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo,
2187 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2188 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p;
2190 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventStatusResponse,
2192 ((pNodeInfo->m_NodeState << 8)
2194 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2195 | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2198 EplTimeruModifyTimerMs(&pNodeInfo->
2200 EplNmtMnuInstance_g.
2201 m_ulStatusRequestDelay,
2208 case kEplNmtMnuIntNodeEventNoStatusResponse:
2210 // function CheckNmtState sets node state to unknown if necessary
2212 if ((NmtState >= kEplNmtMsPreOperational2)
2213 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
2215 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2216 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2217 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2220 // check NMT state of CN
2222 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2223 NodeNmtState_p, wErrorCode_p,
2225 if (Ret != kEplSuccessful) {
2226 if (Ret == kEplReject) {
2227 Ret = kEplSuccessful;
2235 case kEplNmtMnuIntNodeEventError:
2236 { // currently only issued on kEplNmtNodeCommandConfErr
2238 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
2242 // check NMT state of CN
2244 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2246 wErrorCode_p, NmtState);
2247 if (Ret != kEplSuccessful) {
2248 if (Ret == kEplReject) {
2249 Ret = kEplSuccessful;
2257 case kEplNmtMnuIntNodeEventExecReset:
2259 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
2264 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf;
2266 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2271 kEplNmtCmdResetConfiguration));
2273 // send NMT reset configuration to CN for activation of configuration
2275 EplNmtMnuSendNmtCommand(uiNodeId_p,
2276 kEplNmtCmdResetConfiguration);
2281 case kEplNmtMnuIntNodeEventHeartbeat:
2284 if ((NmtState >= kEplNmtMsPreOperational2)
2285 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
2287 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2288 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2289 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2292 // check NMT state of CN
2294 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2295 NodeNmtState_p, wErrorCode_p,
2297 if (Ret != kEplSuccessful) {
2298 if (Ret == kEplReject) {
2299 Ret = kEplSuccessful;
2307 case kEplNmtMnuIntNodeEventTimerIdentReq:
2309 EPL_DBGLVL_NMTMN_TRACE1
2310 ("TimerStatReq->IdentReq(%02X)\n", uiNodeId_p);
2311 // trigger IdentRequest again
2313 EplIdentuRequestIdentResponse(uiNodeId_p,
2314 EplNmtMnuCbIdentResponse);
2315 if (Ret != kEplSuccessful) {
2316 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2318 (((NodeNmtState_p & 0xFF) << 8)
2320 if (Ret == kEplInvalidOperation) { // this can happen because of a bug in EplTimeruLinuxKernel.c
2321 // so ignore this error.
2322 Ret = kEplSuccessful;
2329 case kEplNmtMnuIntNodeEventTimerStateMon:
2331 // reset NMT state change flag
2332 // because from now on the CN must have the correct NMT state
2333 pNodeInfo->m_wFlags &=
2334 ~EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
2336 // continue with normal StatReq processing
2339 case kEplNmtMnuIntNodeEventTimerStatReq:
2341 EPL_DBGLVL_NMTMN_TRACE1("TimerStatReq->StatReq(%02X)\n",
2343 // request next StatusResponse
2345 EplStatusuRequestStatusResponse(uiNodeId_p,
2346 EplNmtMnuCbStatusResponse);
2347 if (Ret != kEplSuccessful) {
2348 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2350 (((NodeNmtState_p & 0xFF) << 8)
2352 if (Ret == kEplInvalidOperation) { // the only situation when this should happen is, when
2353 // StatusResponse was already requested while processing
2354 // event IdentResponse.
2355 // so ignore this error.
2356 Ret = kEplSuccessful;
2363 case kEplNmtMnuIntNodeEventTimerLonger:
2365 switch (pNodeInfo->m_NodeState) {
2366 case kEplNmtMnuNodeStateConfigured:
2367 { // node should be ReadyToOp but it is not
2369 // check NMT state which shall be intentionally wrong, so that ERROR_TREATMENT will be started
2371 EplNmtMnuCheckNmtState(uiNodeId_p,
2376 if (Ret != kEplSuccessful) {
2377 if (Ret == kEplReject) {
2378 Ret = kEplSuccessful;
2386 case kEplNmtMnuNodeStateReadyToOp:
2387 { // CheckCom finished successfully
2389 pNodeInfo->m_NodeState =
2390 kEplNmtMnuNodeStateComChecked;
2394 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED)
2396 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2397 EplNmtMnuInstance_g.
2398 m_uiSignalSlaveCount--;
2399 pNodeInfo->m_wFlags &=
2400 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2405 EPL_NODEASSIGN_MANDATORY_CN) !=
2407 // decrement mandatory slave counter
2408 EplNmtMnuInstance_g.
2409 m_uiMandatorySlaveCount--;
2411 if (NmtState != kEplNmtMsReadyToOperate) {
2412 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2413 (NodeEvent_p, uiNodeId_p,
2414 (((NodeNmtState_p & 0xFF)
2416 | kEplNmtCmdStartNode));
2418 // start optional CN
2420 EplNmtMnuSendNmtCommand
2422 kEplNmtCmdStartNode);
2435 case kEplNmtMnuIntNodeEventNmtCmdSent:
2439 // update expected NMT state with the one that results
2440 // from the sent NMT command
2441 bNmtState = (u8) (NodeNmtState_p & 0xFF);
2443 // write object 0x1F8F NMT_MNNodeExpState_AU8
2445 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
2447 if (Ret != kEplSuccessful) {
2451 if (NodeNmtState_p == kEplNmtCsNotActive) { // restart processing with IdentRequest
2452 EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
2453 (pNodeInfo, uiNodeId_p, TimerArg);
2454 } else { // monitor NMT state change with StatusRequest after
2455 // the corresponding delay;
2456 // until then wrong NMT states will be ignored
2457 EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON
2458 (pNodeInfo, uiNodeId_p, TimerArg);
2460 // set NMT state change flag
2461 pNodeInfo->m_wFlags |=
2462 EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
2466 EplTimeruModifyTimerMs(&pNodeInfo->
2468 EplNmtMnuInstance_g.
2469 m_ulStatusRequestDelay,
2472 // finish processing, because NmtState_p is the expected and not the current state
2482 // check if network is ready to change local NMT state and this was not done before
2483 if ((EplNmtMnuInstance_g.m_wFlags & (EPL_NMTMNU_FLAG_HALTED | EPL_NMTMNU_FLAG_APP_INFORMED)) == 0) { // boot process is not halted
2485 case kEplNmtMsPreOperational1:
2487 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2489 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs scanned once and all mandatory CNs configured successfully
2490 EplNmtMnuInstance_g.m_wFlags |=
2491 EPL_NMTMNU_FLAG_APP_INFORMED;
2492 // inform application
2494 EplNmtMnuInstance_g.
2496 (kEplNmtBootEventBootStep1Finish,
2497 NmtState, EPL_E_NO_ERROR);
2498 if (Ret != kEplSuccessful) {
2499 if (Ret == kEplReject) {
2500 // wait for application
2501 Ret = kEplSuccessful;
2508 (kEplNmtEventAllMandatoryCNIdent);
2513 case kEplNmtMsPreOperational2:
2515 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2517 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs checked once for ReadyToOp and all mandatory CNs are ReadyToOp
2518 EplNmtMnuInstance_g.m_wFlags |=
2519 EPL_NMTMNU_FLAG_APP_INFORMED;
2520 // inform application
2522 EplNmtMnuInstance_g.
2524 (kEplNmtBootEventBootStep2Finish,
2525 NmtState, EPL_E_NO_ERROR);
2526 if (Ret != kEplSuccessful) {
2527 if (Ret == kEplReject) {
2528 // wait for application
2529 Ret = kEplSuccessful;
2536 (kEplNmtEventEnterReadyToOperate);
2541 case kEplNmtMsReadyToOperate:
2543 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2545 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all CNs checked for errorless communication
2546 EplNmtMnuInstance_g.m_wFlags |=
2547 EPL_NMTMNU_FLAG_APP_INFORMED;
2548 // inform application
2550 EplNmtMnuInstance_g.
2552 (kEplNmtBootEventCheckComFinish,
2553 NmtState, EPL_E_NO_ERROR);
2554 if (Ret != kEplSuccessful) {
2555 if (Ret == kEplReject) {
2556 // wait for application
2557 Ret = kEplSuccessful;
2561 // enter Operational
2564 (kEplNmtEventEnterMsOperational);
2569 case kEplNmtMsOperational:
2571 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2573 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs scanned once and all mandatory CNs are OPERATIONAL
2574 EplNmtMnuInstance_g.m_wFlags |=
2575 EPL_NMTMNU_FLAG_APP_INFORMED;
2576 // inform application
2578 EplNmtMnuInstance_g.
2580 (kEplNmtBootEventOperational,
2581 NmtState, EPL_E_NO_ERROR);
2582 if (Ret != kEplSuccessful) {
2583 if (Ret == kEplReject) {
2584 // ignore error code
2585 Ret = kEplSuccessful;
2604 //---------------------------------------------------------------------------
2606 // Function: EplNmtMnuCheckNmtState
2608 // Description: checks the NMT state, i.e. evaluates it with object 0x1F8F
2609 // NMT_MNNodeExpState_AU8 and updates object 0x1F8E
2610 // NMT_MNNodeCurrState_AU8.
2611 // It manipulates m_NodeState in internal node info structure.
2613 // Parameters: uiNodeId_p = node ID
2614 // NodeNmtState_p = NMT state of CN
2616 // Returns: tEplKernel = error code
2617 // kEplReject = CN was in wrong state and has been reset
2621 //---------------------------------------------------------------------------
2623 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
2624 tEplNmtMnuNodeInfo * pNodeInfo_p,
2625 tEplNmtState NodeNmtState_p,
2627 tEplNmtState LocalNmtState_p)
2629 tEplKernel Ret = kEplSuccessful;
2630 tEplObdSize ObdSize;
2633 tEplNmtState ExpNmtState;
2636 // read object 0x1F8F NMT_MNNodeExpState_AU8
2637 Ret = EplObduReadEntry(0x1F8F, uiNodeId_p, &bNmtState, &ObdSize);
2638 if (Ret != kEplSuccessful) {
2641 // compute expected NMT state
2642 ExpNmtState = (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS);
2643 // compute u8 of current NMT state
2644 bNmtState = ((u8) NodeNmtState_p & 0xFF);
2646 if (ExpNmtState == kEplNmtCsNotActive) { // ignore the current state, because the CN shall be not active
2649 } else if ((ExpNmtState == kEplNmtCsPreOperational2)
2650 && (NodeNmtState_p == kEplNmtCsReadyToOperate)) { // CN switched to ReadyToOp
2651 // delete timer for timeout handling
2652 Ret = EplTimeruDeleteTimer(&pNodeInfo_p->m_TimerHdlLonger);
2653 if (Ret != kEplSuccessful) {
2656 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateReadyToOp;
2658 // update object 0x1F8F NMT_MNNodeExpState_AU8 to ReadyToOp
2659 Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1);
2660 if (Ret != kEplSuccessful) {
2664 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter
2665 EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
2667 if (LocalNmtState_p >= kEplNmtMsReadyToOperate) { // start procedure CheckCommunication for this node
2668 Ret = EplNmtMnuNodeCheckCom(uiNodeId_p, pNodeInfo_p);
2669 if (Ret != kEplSuccessful) {
2673 if ((LocalNmtState_p == kEplNmtMsOperational)
2674 && (pNodeInfo_p->m_NodeState ==
2675 kEplNmtMnuNodeStateComChecked)) {
2676 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, uiNodeId_p,
2677 (((NodeNmtState_p & 0xFF) << 8)
2679 kEplNmtCmdStartNode));
2681 // immediately start optional CN, because communication is always OK (e.g. async-only CN)
2683 EplNmtMnuSendNmtCommand(uiNodeId_p,
2684 kEplNmtCmdStartNode);
2685 if (Ret != kEplSuccessful) {
2691 } else if ((ExpNmtState == kEplNmtCsReadyToOperate)
2692 && (NodeNmtState_p == kEplNmtCsOperational)) { // CN switched to OPERATIONAL
2693 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateOperational;
2695 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter
2696 EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
2699 } else if ((ExpNmtState != NodeNmtState_p)
2700 && !((ExpNmtState == kEplNmtCsPreOperational1)
2701 && (NodeNmtState_p == kEplNmtCsPreOperational2))) { // CN is not in expected NMT state (without the exceptions above)
2705 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) {
2706 // decrement only signal slave count if checked once
2707 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2708 pNodeInfo_p->m_wFlags &=
2709 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2712 if (pNodeInfo_p->m_NodeState == kEplNmtMnuNodeStateUnknown) { // CN is already in state unknown, which means that it got
2713 // NMT reset command earlier
2716 // -> CN is in wrong NMT state
2717 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateUnknown;
2719 if (wErrorCode_p == 0) { // assume wrong NMT state error
2720 if ((pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED) != 0) { // NMT command has been just issued;
2721 // ignore wrong NMT state until timer expires;
2722 // other errors like LOSS_PRES_TH are still processed
2726 wErrorCode_p = EPL_E_NMT_WRONG_STATE;
2729 BENCHMARK_MOD_07_TOGGLE(9);
2731 // $$$ start ERROR_TREATMENT and inform application
2732 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2733 kEplNmtNodeEventError,
2738 EPL_NODEASSIGN_MANDATORY_CN)
2740 if (Ret != kEplSuccessful) {
2744 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
2746 (((NodeNmtState_p & 0xFF) << 8)
2747 | kEplNmtCmdResetNode));
2750 // store error code in NMT command data for diagnostic purpose
2751 AmiSetWordToLe(&wbeErrorCode, wErrorCode_p);
2753 EplNmtMnuSendNmtCommandEx(uiNodeId_p, kEplNmtCmdResetNode,
2755 sizeof(wbeErrorCode));
2756 if (Ret == kEplSuccessful) {
2762 // check if NMT_MNNodeCurrState_AU8 has to be changed
2764 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtStatePrev, &ObdSize);
2765 if (Ret != kEplSuccessful) {
2768 if (bNmtState != bNmtStatePrev) {
2769 // update object 0x1F8E NMT_MNNodeCurrState_AU8
2770 Ret = EplObduWriteEntry(0x1F8E, uiNodeId_p, &bNmtState, 1);
2771 if (Ret != kEplSuccessful) {
2774 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2775 kEplNmtNodeEventNmtState,
2780 EPL_NODEASSIGN_MANDATORY_CN)
2782 if (Ret != kEplSuccessful) {
2791 //---------------------------------------------------------------------------
2793 // Function: EplNmtMnuReset
2795 // Description: reset internal structures, e.g. timers
2799 // Returns: tEplKernel = error code
2803 //---------------------------------------------------------------------------
2805 static tEplKernel EplNmtMnuReset(void)
2810 Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState);
2812 for (iIndex = 1; iIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
2814 // delete timer handles
2816 EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2819 EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2826 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)