added 2.6.29.6 aldebaran kernel
[nao-ulib.git] / kernel / 2.6.29.6-aldebaran-rt / drivers / staging / epl / EplNmtMnu.c
blob4ed0b6ce487c8820e8064d5a9a9c360bb509625f
1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
6 Project: openPOWERLINK
8 Description: source file for NMT-MN-Module
10 License:
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
14 are met:
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.
41 Severability Clause:
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 $
54 $Author: D.Krueger $
56 $Revision: 1.18 $ $Date: 2008/11/19 09:52:24 $
58 $State: Exp $
60 Build Environment:
61 GCC V3.4
63 -------------------------------------------------------------------------
65 Revision History:
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!"
83 #endif
85 //=========================================================================//
86 // //
87 // P R I V A T E D E F I N I T I O N S //
88 // //
89 //=========================================================================//
91 //---------------------------------------------------------------------------
92 // const defines
93 //---------------------------------------------------------------------------
95 // TracePoint support for realtime-debugging
96 #ifdef _DBG_TRACE_POINTS_
97 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
98 void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
99 #define TGT_DBG_SIGNAL_TRACE_POINT(p) TgtDbgSignalTracePoint(p)
100 #define TGT_DBG_POST_TRACE_VALUE(v) TgtDbgPostTraceValue(v)
101 #else
102 #define TGT_DBG_SIGNAL_TRACE_POINT(p)
103 #define TGT_DBG_POST_TRACE_VALUE(v)
104 #endif
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 //---------------------------------------------------------------------------
178 // local types
179 //---------------------------------------------------------------------------
181 typedef enum {
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;
199 typedef enum {
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;
210 typedef struct {
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 DWORD m_dwNodeCfg; // subindex from 0x1F81
215 WORD m_wFlags; // flags: CN is being accessed isochronously
217 } tEplNmtMnuNodeInfo;
219 typedef struct {
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 WORD m_wFlags; // global flags
228 DWORD m_dwNmtStartup; // object 0x1F80 NMT_StartUp_U32
229 tEplNmtMnuCbNodeEvent m_pfnCbNodeEvent;
230 tEplNmtMnuCbBootEvent m_pfnCbBootEvent;
232 } tEplNmtMnuInstance;
234 //---------------------------------------------------------------------------
235 // local vars
236 //---------------------------------------------------------------------------
238 static tEplNmtMnuInstance EplNmtMnuInstance_g;
240 //---------------------------------------------------------------------------
241 // local function prototypes
242 //---------------------------------------------------------------------------
244 static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p);
246 static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
247 tEplIdentResponse *
248 pIdentResponse_p);
250 static tEplKernel PUBLIC EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
251 tEplStatusResponse *
252 pStatusResponse_p);
254 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
255 tEplNmtMnuNodeInfo * pNodeInfo_p,
256 tEplNmtState NodeNmtState_p,
257 WORD wErrorCode_p,
258 tEplNmtState LocalNmtState_p);
260 static tEplKernel EplNmtMnuStartBootStep1(void);
262 static tEplKernel EplNmtMnuStartBootStep2(void);
264 static tEplKernel EplNmtMnuStartCheckCom(void);
266 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
267 tEplNmtMnuNodeInfo * pNodeInfo_p);
269 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
270 tEplNmtMnuNodeInfo * pNodeInfo_p);
272 static tEplKernel EplNmtMnuStartNodes(void);
274 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
275 tEplNmtState NodeNmtState_p,
276 WORD wErrorCode_p,
277 tEplNmtMnuIntNodeEvent
278 NodeEvent_p);
280 static tEplKernel EplNmtMnuReset(void);
282 //=========================================================================//
283 // //
284 // P U B L I C F U N C T I O N S //
285 // //
286 //=========================================================================//
288 //---------------------------------------------------------------------------
290 // Function: EplNmtMnuInit
292 // Description: init first instance of the module
296 // Parameters:
299 // Returns: tEplKernel = errorcode
302 // State:
304 //---------------------------------------------------------------------------
306 tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
307 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
309 tEplKernel Ret;
311 Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p);
313 return Ret;
316 //---------------------------------------------------------------------------
318 // Function: EplNmtMnuAddInstance
320 // Description: init other instances of the module
324 // Parameters:
327 // Returns: tEplKernel = errorcode
330 // State:
332 //---------------------------------------------------------------------------
334 tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
335 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
337 tEplKernel Ret;
339 Ret = kEplSuccessful;
341 // reset instance structure
342 EPL_MEMSET(&EplNmtMnuInstance_g, 0, sizeof(EplNmtMnuInstance_g));
344 if ((pfnCbNodeEvent_p == NULL) || (pfnCbBootEvent_p == NULL)) {
345 Ret = kEplNmtInvalidParam;
346 goto Exit;
348 EplNmtMnuInstance_g.m_pfnCbNodeEvent = pfnCbNodeEvent_p;
349 EplNmtMnuInstance_g.m_pfnCbBootEvent = pfnCbBootEvent_p;
351 // initialize StatusRequest delay
352 EplNmtMnuInstance_g.m_ulStatusRequestDelay = 5000L;
354 // register NmtMnResponse callback function
355 Ret =
356 EplDlluCalRegAsndService(kEplDllAsndNmtRequest,
357 EplNmtMnuCbNmtRequest,
358 kEplDllAsndFilterLocal);
360 Exit:
361 return Ret;
365 //---------------------------------------------------------------------------
367 // Function: EplNmtMnuDelInstance
369 // Description: delete instance
373 // Parameters:
376 // Returns: tEplKernel = errorcode
379 // State:
381 //---------------------------------------------------------------------------
383 tEplKernel EplNmtMnuDelInstance()
385 tEplKernel Ret;
387 Ret = kEplSuccessful;
389 // deregister NmtMnResponse callback function
390 Ret =
391 EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL,
392 kEplDllAsndFilterNone);
394 Ret = EplNmtMnuReset();
396 return Ret;
400 //---------------------------------------------------------------------------
402 // Function: EplNmtMnuSendNmtCommandEx
404 // Description: sends the specified NMT command to the specified node.
406 // Parameters: uiNodeId_p = node ID to which the NMT command will be sent
407 // NmtCommand_p = NMT command
409 // Returns: tEplKernel = error code
411 // State:
413 //---------------------------------------------------------------------------
415 tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p,
416 tEplNmtCommand NmtCommand_p,
417 void *pNmtCommandData_p,
418 unsigned int uiDataSize_p)
420 tEplKernel Ret = kEplSuccessful;
421 tEplFrameInfo FrameInfo;
422 BYTE abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT];
423 tEplFrame *pFrame = (tEplFrame *) abBuffer;
424 BOOL fSoftDeleteNode = FALSE;
426 if ((uiNodeId_p == 0) || (uiNodeId_p > EPL_C_ADR_BROADCAST)) { // invalid node ID specified
427 Ret = kEplInvalidNodeId;
428 goto Exit;
431 if ((pNmtCommandData_p != NULL)
432 && (uiDataSize_p >
433 (EPL_C_DLL_MINSIZE_NMTCMDEXT - EPL_C_DLL_MINSIZE_NMTCMD))) {
434 Ret = kEplNmtInvalidParam;
435 goto Exit;
437 // $$$ d.k. may be check in future versions if the caller wants to perform prohibited state transitions
438 // the CN should not perform these transitions, but the expected NMT state will be changed and never fullfilled.
440 // build frame
441 EPL_MEMSET(pFrame, 0x00, sizeof(abBuffer));
442 AmiSetByteToLe(&pFrame->m_le_bDstNodeId, (BYTE) uiNodeId_p);
443 AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_le_bServiceId,
444 (BYTE) kEplDllAsndNmtCommand);
445 AmiSetByteToLe(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
446 m_le_bNmtCommandId, (BYTE) NmtCommand_p);
447 if ((pNmtCommandData_p != NULL) && (uiDataSize_p > 0)) { // copy command data to frame
448 EPL_MEMCPY(&pFrame->m_Data.m_Asnd.m_Payload.m_NmtCommandService.
449 m_le_abNmtCommandData[0], pNmtCommandData_p,
450 uiDataSize_p);
452 // build info structure
453 FrameInfo.m_NetTime.m_dwNanoSec = 0;
454 FrameInfo.m_NetTime.m_dwSec = 0;
455 FrameInfo.m_pFrame = pFrame;
456 FrameInfo.m_uiFrameSize = sizeof(abBuffer);
458 // send NMT-Request
459 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
460 Ret = EplDlluCalAsyncSend(&FrameInfo, // pointer to frameinfo
461 kEplDllAsyncReqPrioNmt); // priority
462 #endif
463 if (Ret != kEplSuccessful) {
464 goto Exit;
467 EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p,
468 uiNodeId_p);
470 switch (NmtCommand_p) {
471 case kEplNmtCmdStartNode:
472 case kEplNmtCmdEnterPreOperational2:
473 case kEplNmtCmdEnableReadyToOperate:
475 // nothing left to do,
476 // because any further processing is done
477 // when the NMT command is actually sent
478 goto Exit;
481 case kEplNmtCmdStopNode:
483 fSoftDeleteNode = TRUE;
484 break;
487 case kEplNmtCmdResetNode:
488 case kEplNmtCmdResetCommunication:
489 case kEplNmtCmdResetConfiguration:
490 case kEplNmtCmdSwReset:
492 break;
495 default:
496 goto Exit;
499 // remove CN from isochronous phase;
500 // This must be done here and not when NMT command is actually sent
501 // because it will be too late and may cause unwanted errors
502 if (uiNodeId_p != EPL_C_ADR_BROADCAST) {
503 if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
504 Ret = EplDlluCalDeleteNode(uiNodeId_p);
505 } else { // remove CN from isochronous phase softly
506 Ret = EplDlluCalSoftDeleteNode(uiNodeId_p);
508 } else { // do it for all active CNs
509 for (uiNodeId_p = 1;
510 uiNodeId_p <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
511 uiNodeId_p++) {
512 if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId_p)->
513 m_dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN |
514 EPL_NODEASSIGN_NODE_EXISTS)) != 0) {
515 if (fSoftDeleteNode == FALSE) { // remove CN immediately from isochronous phase
516 Ret = EplDlluCalDeleteNode(uiNodeId_p);
517 } else { // remove CN from isochronous phase softly
518 Ret =
519 EplDlluCalSoftDeleteNode
520 (uiNodeId_p);
526 Exit:
527 return Ret;
530 //---------------------------------------------------------------------------
532 // Function: EplNmtMnuSendNmtCommand
534 // Description: sends the specified NMT command to the specified node.
536 // Parameters: uiNodeId_p = node ID to which the NMT command will be sent
537 // NmtCommand_p = NMT command
539 // Returns: tEplKernel = error code
541 // State:
543 //---------------------------------------------------------------------------
545 tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p,
546 tEplNmtCommand NmtCommand_p)
548 tEplKernel Ret = kEplSuccessful;
550 Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, NmtCommand_p, NULL, 0);
552 //Exit:
553 return Ret;
556 //---------------------------------------------------------------------------
558 // Function: EplNmtMnuTriggerStateChange
560 // Description: triggers the specified node command for the specified node.
562 // Parameters: uiNodeId_p = node ID for which the node command will be executed
563 // NodeCommand_p = node command
565 // Returns: tEplKernel = error code
567 // State:
569 //---------------------------------------------------------------------------
571 tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,
572 tEplNmtNodeCommand NodeCommand_p)
574 tEplKernel Ret = kEplSuccessful;
575 tEplNmtMnuIntNodeEvent NodeEvent;
576 tEplObdSize ObdSize;
577 BYTE bNmtState;
578 WORD wErrorCode = EPL_E_NO_ERROR;
580 if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) {
581 Ret = kEplInvalidNodeId;
582 goto Exit;
585 switch (NodeCommand_p) {
586 case kEplNmtNodeCommandBoot:
588 NodeEvent = kEplNmtMnuIntNodeEventBoot;
589 break;
592 case kEplNmtNodeCommandConfOk:
594 NodeEvent = kEplNmtMnuIntNodeEventConfigured;
595 break;
598 case kEplNmtNodeCommandConfErr:
600 NodeEvent = kEplNmtMnuIntNodeEventError;
601 wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY;
602 break;
605 case kEplNmtNodeCommandConfReset:
607 NodeEvent = kEplNmtMnuIntNodeEventExecReset;
608 break;
611 default:
612 { // invalid node command
613 goto Exit;
617 // fetch current NMT state
618 ObdSize = 1;
619 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize);
620 if (Ret != kEplSuccessful) {
621 goto Exit;
624 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
625 (tEplNmtState) (bNmtState |
626 EPL_NMT_TYPE_CS),
627 wErrorCode, NodeEvent);
629 Exit:
630 return Ret;
633 //---------------------------------------------------------------------------
635 // Function: EplNmtMnuCbNmtStateChange
637 // Description: callback function for NMT state changes
639 // Parameters: NmtStateChange_p = NMT state change event
641 // Returns: tEplKernel = error code
644 // State:
646 //---------------------------------------------------------------------------
648 tEplKernel PUBLIC EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange
649 NmtStateChange_p)
651 tEplKernel Ret = kEplSuccessful;
653 // do work which must be done in that state
654 switch (NmtStateChange_p.m_NewNmtState) {
655 // EPL stack is not running
656 /* case kEplNmtGsOff:
657 break;
659 // first init of the hardware
660 case kEplNmtGsInitialising:
661 break;
663 // init of the manufacturer-specific profile area and the
664 // standardised device profile area
665 case kEplNmtGsResetApplication:
667 break;
670 // init of the communication profile area
671 case kEplNmtGsResetCommunication:
673 break;
676 // build the configuration with infos from OD
677 case kEplNmtGsResetConfiguration:
679 DWORD dwTimeout;
680 tEplObdSize ObdSize;
682 // read object 0x1F80 NMT_StartUp_U32
683 ObdSize = 4;
684 Ret =
685 EplObduReadEntry(0x1F80, 0,
686 &EplNmtMnuInstance_g.
687 m_dwNmtStartup, &ObdSize);
688 if (Ret != kEplSuccessful) {
689 break;
691 // compute StatusReqDelay = object 0x1006 * EPL_C_NMT_STATREQ_CYCLE
692 ObdSize = sizeof(dwTimeout);
693 Ret = EplObduReadEntry(0x1006, 0, &dwTimeout, &ObdSize);
694 if (Ret != kEplSuccessful) {
695 break;
697 if (dwTimeout != 0L) {
698 EplNmtMnuInstance_g.m_ulStatusRequestDelay =
699 dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
700 if (EplNmtMnuInstance_g.
701 m_ulStatusRequestDelay == 0L) {
702 EplNmtMnuInstance_g.m_ulStatusRequestDelay = 1L; // at least 1 ms
704 // $$$ fetch and use MultiplexedCycleCount from OD
705 EplNmtMnuInstance_g.m_ulTimeoutCheckCom =
706 dwTimeout * EPL_C_NMT_STATREQ_CYCLE / 1000L;
707 if (EplNmtMnuInstance_g.m_ulTimeoutCheckCom ==
708 0L) {
709 EplNmtMnuInstance_g.m_ulTimeoutCheckCom = 1L; // at least 1 ms
712 // fetch ReadyToOp Timeout from OD
713 ObdSize = sizeof(dwTimeout);
714 Ret = EplObduReadEntry(0x1F89, 5, &dwTimeout, &ObdSize);
715 if (Ret != kEplSuccessful) {
716 break;
718 if (dwTimeout != 0L) {
719 // convert [us] to [ms]
720 dwTimeout /= 1000L;
721 if (dwTimeout == 0L) {
722 dwTimeout = 1L; // at least 1 ms
724 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp =
725 dwTimeout;
726 } else {
727 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L;
729 break;
732 //-----------------------------------------------------------
733 // CN part of the state machine
735 // node liste for EPL-Frames and check timeout
736 case kEplNmtCsNotActive:
738 break;
741 // node process only async frames
742 case kEplNmtCsPreOperational1:
744 break;
747 // node process isochronus and asynchronus frames
748 case kEplNmtCsPreOperational2:
750 break;
753 // node should be configured und application is ready
754 case kEplNmtCsReadyToOperate:
756 break;
759 // normal work state
760 case kEplNmtCsOperational:
762 break;
765 // node stopped by MN
766 // -> only process asynchronus frames
767 case kEplNmtCsStopped:
769 break;
772 // no EPL cycle
773 // -> normal ethernet communication
774 case kEplNmtCsBasicEthernet:
776 break;
779 //-----------------------------------------------------------
780 // MN part of the state machine
782 // node listens for EPL-Frames and check timeout
783 case kEplNmtMsNotActive:
785 break;
788 // node processes only async frames
789 case kEplNmtMsPreOperational1:
791 DWORD dwTimeout;
792 tEplTimerArg TimerArg;
793 tEplObdSize ObdSize;
794 tEplEvent Event;
796 // clear global flags, e.g. reenable boot process
797 EplNmtMnuInstance_g.m_wFlags = 0;
799 // reset IdentResponses and running IdentRequests and StatusRequests
800 Ret = EplIdentuReset();
801 Ret = EplStatusuReset();
803 // reset timers
804 Ret = EplNmtMnuReset();
806 // 2008/11/18 d.k. reset internal node info is not necessary,
807 // because timer flags are important and other
808 // things are reset by EplNmtMnuStartBootStep1().
810 EPL_MEMSET(EplNmtMnuInstance_g.m_aNodeInfo,
812 sizeof (EplNmtMnuInstance_g.m_aNodeInfo));
815 // inform DLL about NMT state change,
816 // so that it can clear the asynchonous queues and start the reduced cycle
817 Event.m_EventSink = kEplEventSinkDllk;
818 Event.m_EventType = kEplEventTypeDllkStartReducedCycle;
819 EPL_MEMSET(&Event.m_NetTime, 0x00,
820 sizeof(Event.m_NetTime));
821 Event.m_pArg = NULL;
822 Event.m_uiSize = 0;
823 Ret = EplEventuPost(&Event);
824 if (Ret != kEplSuccessful) {
825 break;
827 // reset all nodes
828 // d.k.: skip this step if was just done before, e.g. because of a ResetNode command from a diagnostic node
829 if (NmtStateChange_p.m_NmtEvent ==
830 kEplNmtEventTimerMsPreOp1) {
831 BENCHMARK_MOD_07_TOGGLE(9);
833 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
834 EPL_C_ADR_BROADCAST,
835 kEplNmtCmdResetNode);
837 Ret =
838 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
839 kEplNmtCmdResetNode);
840 if (Ret != kEplSuccessful) {
841 break;
844 // start network scan
845 Ret = EplNmtMnuStartBootStep1();
847 // start timer for 0x1F89/2 MNTimeoutPreOp1_U32
848 ObdSize = sizeof(dwTimeout);
849 Ret = EplObduReadEntry(0x1F89, 2, &dwTimeout, &ObdSize);
850 if (Ret != kEplSuccessful) {
851 break;
853 if (dwTimeout != 0L) {
854 dwTimeout /= 1000L;
855 if (dwTimeout == 0L) {
856 dwTimeout = 1L; // at least 1 ms
858 TimerArg.m_EventSink = kEplEventSinkNmtMnu;
859 TimerArg.m_ulArg = 0;
860 Ret =
861 EplTimeruModifyTimerMs(&EplNmtMnuInstance_g.
862 m_TimerHdlNmtState,
863 dwTimeout, TimerArg);
865 break;
868 // node processes isochronous and asynchronous frames
869 case kEplNmtMsPreOperational2:
871 // add identified CNs to isochronous phase
872 // send EnableReadyToOp to all identified CNs
873 Ret = EplNmtMnuStartBootStep2();
875 // wait for NMT state change of CNs
876 break;
879 // node should be configured und application is ready
880 case kEplNmtMsReadyToOperate:
882 // check if PRes of CNs are OK
883 // d.k. that means wait CycleLength * MultiplexCycleCount (i.e. start timer)
884 // because Dllk checks PRes of CNs automatically in ReadyToOp
885 Ret = EplNmtMnuStartCheckCom();
886 break;
889 // normal work state
890 case kEplNmtMsOperational:
892 // send StartNode to CNs
893 // wait for NMT state change of CNs
894 Ret = EplNmtMnuStartNodes();
895 break;
898 // no EPL cycle
899 // -> normal ethernet communication
900 case kEplNmtMsBasicEthernet:
902 break;
905 default:
907 // TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n");
911 return Ret;
914 //---------------------------------------------------------------------------
916 // Function: EplNmtMnuCbCheckEvent
918 // Description: callback funktion for NMT events before they are actually executed.
919 // The EPL API layer must forward NMT events from NmtCnu module.
920 // This module will reject some NMT commands while MN.
922 // Parameters: NmtEvent_p = outstanding NMT event for approval
924 // Returns: tEplKernel = error code
925 // kEplReject = reject the NMT event
927 // State:
929 //---------------------------------------------------------------------------
931 tEplKernel PUBLIC EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p)
933 tEplKernel Ret = kEplSuccessful;
935 return Ret;
938 //---------------------------------------------------------------------------
940 // Function: EplNmtuProcessEvent
942 // Description: processes events from event queue
944 // Parameters: pEvent_p = pointer to event
946 // Returns: tEplKernel = errorcode
948 // State:
950 //---------------------------------------------------------------------------
952 EPLDLLEXPORT tEplKernel PUBLIC EplNmtMnuProcessEvent(tEplEvent * pEvent_p)
954 tEplKernel Ret;
956 Ret = kEplSuccessful;
958 // process event
959 switch (pEvent_p->m_EventType) {
960 // timer event
961 case kEplEventTypeTimer:
963 tEplTimerEventArg *pTimerEventArg =
964 (tEplTimerEventArg *) pEvent_p->m_pArg;
965 unsigned int uiNodeId;
967 uiNodeId =
968 (unsigned int)(pTimerEventArg->
969 m_ulArg &
970 EPL_NMTMNU_TIMERARG_NODE_MASK);
971 if (uiNodeId != 0) {
972 tEplObdSize ObdSize;
973 BYTE bNmtState;
974 tEplNmtMnuNodeInfo *pNodeInfo;
976 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId);
978 ObdSize = 1;
979 Ret =
980 EplObduReadEntry(0x1F8E, uiNodeId,
981 &bNmtState, &ObdSize);
982 if (Ret != kEplSuccessful) {
983 break;
986 if ((pTimerEventArg->
987 m_ulArg & EPL_NMTMNU_TIMERARG_IDENTREQ) !=
988 0L) {
989 if ((pNodeInfo->
990 m_wFlags &
991 EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
992 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
993 // but not the current timer
994 // so discard it
995 EPL_NMTMNU_DBG_POST_TRACE_VALUE
996 (kEplNmtMnuIntNodeEventTimerIdentReq,
997 uiNodeId,
998 ((pNodeInfo->
999 m_NodeState << 8)
1000 | 0xFF));
1002 break;
1005 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq,
1006 uiNodeId,
1007 ((pNodeInfo->m_NodeState << 8)
1008 | 0x80
1009 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1010 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1012 Ret =
1013 EplNmtMnuProcessInternalEvent
1014 (uiNodeId,
1015 (tEplNmtState) (bNmtState |
1016 EPL_NMT_TYPE_CS),
1017 EPL_E_NO_ERROR,
1018 kEplNmtMnuIntNodeEventTimerIdentReq);
1021 else if ((pTimerEventArg->
1022 m_ulArg & EPL_NMTMNU_TIMERARG_STATREQ)
1023 != 0L) {
1024 if ((pNodeInfo->
1025 m_wFlags &
1026 EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
1027 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
1028 // but not the current timer
1029 // so discard it
1030 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1031 (kEplNmtMnuIntNodeEventTimerStatReq,
1032 uiNodeId,
1033 ((pNodeInfo->
1034 m_NodeState << 8)
1035 | 0xFF));
1037 break;
1040 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1041 uiNodeId,
1042 ((pNodeInfo->m_NodeState << 8)
1043 | 0x80
1044 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1045 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1047 Ret =
1048 EplNmtMnuProcessInternalEvent
1049 (uiNodeId,
1050 (tEplNmtState) (bNmtState |
1051 EPL_NMT_TYPE_CS),
1052 EPL_E_NO_ERROR,
1053 kEplNmtMnuIntNodeEventTimerStatReq);
1056 else if ((pTimerEventArg->
1057 m_ulArg &
1058 EPL_NMTMNU_TIMERARG_STATE_MON) !=
1059 0L) {
1060 if ((pNodeInfo->
1061 m_wFlags &
1062 EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ)
1063 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR)) { // this is an old (already deleted or modified) timer
1064 // but not the current timer
1065 // so discard it
1066 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1067 (kEplNmtMnuIntNodeEventTimerStateMon,
1068 uiNodeId,
1069 ((pNodeInfo->
1070 m_NodeState << 8)
1071 | 0xFF));
1073 break;
1076 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1077 uiNodeId,
1078 ((pNodeInfo->m_NodeState << 8)
1079 | 0x80
1080 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1081 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1083 Ret =
1084 EplNmtMnuProcessInternalEvent
1085 (uiNodeId,
1086 (tEplNmtState) (bNmtState |
1087 EPL_NMT_TYPE_CS),
1088 EPL_E_NO_ERROR,
1089 kEplNmtMnuIntNodeEventTimerStateMon);
1092 else if ((pTimerEventArg->
1093 m_ulArg & EPL_NMTMNU_TIMERARG_LONGER)
1094 != 0L) {
1095 if ((pNodeInfo->
1096 m_wFlags &
1097 EPL_NMTMNU_NODE_FLAG_COUNT_LONGER)
1098 != (pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO)) { // this is an old (already deleted or modified) timer
1099 // but not the current timer
1100 // so discard it
1101 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1102 (kEplNmtMnuIntNodeEventTimerLonger,
1103 uiNodeId,
1104 ((pNodeInfo->
1105 m_NodeState << 8)
1106 | 0xFF));
1108 break;
1111 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger,
1112 uiNodeId,
1113 ((pNodeInfo->m_NodeState << 8)
1114 | 0x80
1115 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) >> 6)
1116 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO) >> 8)));
1118 Ret =
1119 EplNmtMnuProcessInternalEvent
1120 (uiNodeId,
1121 (tEplNmtState) (bNmtState |
1122 EPL_NMT_TYPE_CS),
1123 EPL_E_NO_ERROR,
1124 kEplNmtMnuIntNodeEventTimerLonger);
1127 } else { // global timer event
1129 break;
1132 case kEplEventTypeHeartbeat:
1134 tEplHeartbeatEvent *pHeartbeatEvent =
1135 (tEplHeartbeatEvent *) pEvent_p->m_pArg;
1137 Ret =
1138 EplNmtMnuProcessInternalEvent(pHeartbeatEvent->
1139 m_uiNodeId,
1140 pHeartbeatEvent->
1141 m_NmtState,
1142 pHeartbeatEvent->
1143 m_wErrorCode,
1144 kEplNmtMnuIntNodeEventHeartbeat);
1145 break;
1148 case kEplEventTypeNmtMnuNmtCmdSent:
1150 tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg;
1151 unsigned int uiNodeId;
1152 tEplNmtCommand NmtCommand;
1153 BYTE bNmtState;
1155 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
1156 NmtCommand =
1157 (tEplNmtCommand) AmiGetByteFromLe(&pFrame->m_Data.
1158 m_Asnd.m_Payload.
1159 m_NmtCommandService.
1160 m_le_bNmtCommandId);
1162 switch (NmtCommand) {
1163 case kEplNmtCmdStartNode:
1164 bNmtState =
1165 (BYTE) (kEplNmtCsOperational & 0xFF);
1166 break;
1168 case kEplNmtCmdStopNode:
1169 bNmtState = (BYTE) (kEplNmtCsStopped & 0xFF);
1170 break;
1172 case kEplNmtCmdEnterPreOperational2:
1173 bNmtState =
1174 (BYTE) (kEplNmtCsPreOperational2 & 0xFF);
1175 break;
1177 case kEplNmtCmdEnableReadyToOperate:
1178 // d.k. do not change expected node state, because of DS 1.0.0 7.3.1.2.1 Plain NMT State Command
1179 // and because node may not change NMT state within EPL_C_NMT_STATE_TOLERANCE
1180 bNmtState =
1181 (BYTE) (kEplNmtCsPreOperational2 & 0xFF);
1182 break;
1184 case kEplNmtCmdResetNode:
1185 case kEplNmtCmdResetCommunication:
1186 case kEplNmtCmdResetConfiguration:
1187 case kEplNmtCmdSwReset:
1188 bNmtState = (BYTE) (kEplNmtCsNotActive & 0xFF);
1189 // EplNmtMnuProcessInternalEvent() sets internal node state to kEplNmtMnuNodeStateUnknown
1190 // after next unresponded IdentRequest/StatusRequest
1191 break;
1193 default:
1194 goto Exit;
1197 // process as internal event which update expected NMT state in OD
1198 if (uiNodeId != EPL_C_ADR_BROADCAST) {
1199 Ret = EplNmtMnuProcessInternalEvent(uiNodeId,
1200 (tEplNmtState)
1201 (bNmtState |
1202 EPL_NMT_TYPE_CS),
1204 kEplNmtMnuIntNodeEventNmtCmdSent);
1206 } else { // process internal event for all active nodes (except myself)
1208 for (uiNodeId = 1;
1209 uiNodeId <=
1210 tabentries(EplNmtMnuInstance_g.
1211 m_aNodeInfo); uiNodeId++) {
1212 if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId)->
1213 m_dwNodeCfg &
1214 (EPL_NODEASSIGN_NODE_IS_CN |
1215 EPL_NODEASSIGN_NODE_EXISTS)) !=
1216 0) {
1217 Ret =
1218 EplNmtMnuProcessInternalEvent
1219 (uiNodeId,
1220 (tEplNmtState) (bNmtState |
1221 EPL_NMT_TYPE_CS),
1223 kEplNmtMnuIntNodeEventNmtCmdSent);
1225 if (Ret != kEplSuccessful) {
1226 goto Exit;
1232 break;
1235 default:
1237 Ret = kEplNmtInvalidEvent;
1242 Exit:
1243 return Ret;
1246 //---------------------------------------------------------------------------
1248 // Function: EplNmtMnuGetRunningTimerStatReq
1250 // Description: returns a bit field with running StatReq timers
1251 // just for debugging purposes
1253 // Parameters: (none)
1255 // Returns: tEplKernel = error code
1257 // State:
1259 //---------------------------------------------------------------------------
1261 tEplKernel PUBLIC EplNmtMnuGetDiagnosticInfo(unsigned int
1262 *puiMandatorySlaveCount_p,
1263 unsigned int
1264 *puiSignalSlaveCount_p,
1265 WORD * pwFlags_p)
1267 tEplKernel Ret = kEplSuccessful;
1269 if ((puiMandatorySlaveCount_p == NULL)
1270 || (puiSignalSlaveCount_p == NULL)
1271 || (pwFlags_p == NULL)) {
1272 Ret = kEplNmtInvalidParam;
1273 goto Exit;
1276 *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount;
1277 *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount;
1278 *pwFlags_p = EplNmtMnuInstance_g.m_wFlags;
1280 Exit:
1281 return Ret;
1284 //---------------------------------------------------------------------------
1286 // Function: EplNmtMnuGetRunningTimerStatReq
1288 // Description: returns a bit field with running StatReq timers
1289 // just for debugging purposes
1291 // Parameters: (none)
1293 // Returns: tEplKernel = error code
1295 // State:
1297 //---------------------------------------------------------------------------
1299 DWORD EplNmtMnuGetRunningTimerStatReq(void)
1301 tEplKernel Ret = kEplSuccessful;
1302 unsigned int uiIndex;
1303 tEplNmtMnuNodeInfo* pNodeInfo;
1305 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1306 for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++)
1308 if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured)
1310 // reset flag "scanned once"
1311 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_SCANNED;
1313 Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1314 if (Ret != kEplSuccessful)
1316 goto Exit;
1318 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1319 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1320 // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
1324 Exit:
1325 return Ret;
1329 //=========================================================================//
1330 // //
1331 // P R I V A T E F U N C T I O N S //
1332 // //
1333 //=========================================================================//
1335 //---------------------------------------------------------------------------
1337 // Function: EplNmtMnuCbNmtRequest
1339 // Description: callback funktion for NmtRequest
1341 // Parameters: pFrameInfo_p = Frame with the NmtRequest
1343 // Returns: tEplKernel = error code
1346 // State:
1348 //---------------------------------------------------------------------------
1350 static tEplKernel PUBLIC EplNmtMnuCbNmtRequest(tEplFrameInfo * pFrameInfo_p)
1352 tEplKernel Ret = kEplSuccessful;
1354 // $$$ perform NMTRequest
1355 return Ret;
1358 //---------------------------------------------------------------------------
1360 // Function: EplNmtMnuCbIdentResponse
1362 // Description: callback funktion for IdentResponse
1364 // Parameters: uiNodeId_p = node ID for which IdentReponse was received
1365 // pIdentResponse_p = pointer to IdentResponse
1366 // is NULL if node did not answer
1368 // Returns: tEplKernel = error code
1370 // State:
1372 //---------------------------------------------------------------------------
1374 static tEplKernel PUBLIC EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p,
1375 tEplIdentResponse *
1376 pIdentResponse_p)
1378 tEplKernel Ret = kEplSuccessful;
1380 if (pIdentResponse_p == NULL) { // node did not answer
1381 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_IDENT_RES, // was EPL_E_NO_ERROR
1382 kEplNmtMnuIntNodeEventNoIdentResponse);
1383 } else { // node answered IdentRequest
1384 tEplObdSize ObdSize;
1385 DWORD dwDevType;
1386 WORD wErrorCode = EPL_E_NO_ERROR;
1387 tEplNmtState NmtState =
1388 (tEplNmtState) (AmiGetByteFromLe
1389 (&pIdentResponse_p->
1390 m_le_bNmtStatus) | EPL_NMT_TYPE_CS);
1392 // check IdentResponse $$$ move to ProcessIntern, because this function may be called also if CN
1394 // check DeviceType (0x1F84)
1395 ObdSize = 4;
1396 Ret =
1397 EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize);
1398 if (Ret != kEplSuccessful) {
1399 goto Exit;
1401 if (dwDevType != 0L) { // actually compare it with DeviceType from IdentResponse
1402 if (AmiGetDwordFromLe(&pIdentResponse_p->m_le_dwDeviceType) != dwDevType) { // wrong DeviceType
1403 NmtState = kEplNmtCsNotActive;
1404 wErrorCode = EPL_E_NMT_BPO1_DEVICE_TYPE;
1408 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
1409 NmtState,
1410 wErrorCode,
1411 kEplNmtMnuIntNodeEventIdentResponse);
1414 Exit:
1415 return Ret;
1418 //---------------------------------------------------------------------------
1420 // Function: EplNmtMnuCbStatusResponse
1422 // Description: callback funktion for StatusResponse
1424 // Parameters: uiNodeId_p = node ID for which IdentReponse was received
1425 // pIdentResponse_p = pointer to IdentResponse
1426 // is NULL if node did not answer
1428 // Returns: tEplKernel = error code
1430 // State:
1432 //---------------------------------------------------------------------------
1434 static tEplKernel PUBLIC EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p,
1435 tEplStatusResponse *
1436 pStatusResponse_p)
1438 tEplKernel Ret = kEplSuccessful;
1440 if (pStatusResponse_p == NULL) { // node did not answer
1441 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, kEplNmtCsNotActive, EPL_E_NMT_NO_STATUS_RES, // was EPL_E_NO_ERROR
1442 kEplNmtMnuIntNodeEventNoStatusResponse);
1443 } else { // node answered StatusRequest
1444 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
1445 (tEplNmtState)
1446 (AmiGetByteFromLe
1447 (&pStatusResponse_p->
1448 m_le_bNmtStatus) |
1449 EPL_NMT_TYPE_CS),
1450 EPL_E_NO_ERROR,
1451 kEplNmtMnuIntNodeEventStatusResponse);
1454 return Ret;
1457 //---------------------------------------------------------------------------
1459 // Function: EplNmtMnuStartBootStep1
1461 // Description: starts BootStep1
1463 // Parameters: (none)
1465 // Returns: tEplKernel = error code
1467 // State:
1469 //---------------------------------------------------------------------------
1471 static tEplKernel EplNmtMnuStartBootStep1(void)
1473 tEplKernel Ret = kEplSuccessful;
1474 unsigned int uiSubIndex;
1475 unsigned int uiLocalNodeId;
1476 DWORD dwNodeCfg;
1477 tEplObdSize ObdSize;
1479 // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32
1481 // start network scan
1482 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1483 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1484 // check 0x1F81
1485 uiLocalNodeId = EplObduGetNodeId();
1486 for (uiSubIndex = 1; uiSubIndex <= 254; uiSubIndex++) {
1487 ObdSize = 4;
1488 Ret =
1489 EplObduReadEntry(0x1F81, uiSubIndex, &dwNodeCfg, &ObdSize);
1490 if (Ret != kEplSuccessful) {
1491 goto Exit;
1493 if (uiSubIndex != uiLocalNodeId) {
1494 // reset flags "not scanned" and "isochronous"
1495 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags &=
1496 ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON |
1497 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED);
1499 if (uiSubIndex == EPL_C_ADR_DIAG_DEF_NODE_ID) { // diagnostic node must be scanned by MN in any case
1500 dwNodeCfg |=
1501 (EPL_NODEASSIGN_NODE_IS_CN |
1502 EPL_NODEASSIGN_NODE_EXISTS);
1503 // and it must be isochronously accessed
1504 dwNodeCfg &= ~EPL_NODEASSIGN_ASYNCONLY_NODE;
1506 // save node config in local node info structure
1507 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_dwNodeCfg =
1508 dwNodeCfg;
1509 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_NodeState =
1510 kEplNmtMnuNodeStateUnknown;
1512 if ((dwNodeCfg & (EPL_NODEASSIGN_NODE_IS_CN | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // node is configured as CN
1513 // identify the node
1514 Ret =
1515 EplIdentuRequestIdentResponse(uiSubIndex,
1516 EplNmtMnuCbIdentResponse);
1517 if (Ret != kEplSuccessful) {
1518 goto Exit;
1520 // set flag "not scanned"
1521 EPL_NMTMNU_GET_NODEINFO(uiSubIndex)->m_wFlags |=
1522 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1523 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1524 // signal slave counter shall be decremented if IdentRequest was sent once to a CN
1526 if ((dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1527 EplNmtMnuInstance_g.
1528 m_uiMandatorySlaveCount++;
1529 // mandatory slave counter shall be decremented if mandatory CN was configured successfully
1532 } else { // subindex of MN
1533 if ((dwNodeCfg & (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // MN shall send PRes
1534 tEplDllNodeInfo DllNodeInfo;
1536 EPL_MEMSET(&DllNodeInfo, 0,
1537 sizeof(DllNodeInfo));
1538 DllNodeInfo.m_uiNodeId = uiLocalNodeId;
1540 Ret = EplDlluCalAddNode(&DllNodeInfo);
1545 Exit:
1546 return Ret;
1549 //---------------------------------------------------------------------------
1551 // Function: EplNmtMnuStartBootStep2
1553 // Description: starts BootStep2.
1554 // That means add nodes to isochronous phase and send
1555 // NMT EnableReadyToOp.
1557 // Parameters: (none)
1559 // Returns: tEplKernel = error code
1561 // State:
1563 //---------------------------------------------------------------------------
1565 static tEplKernel EplNmtMnuStartBootStep2(void)
1567 tEplKernel Ret = kEplSuccessful;
1568 unsigned int uiIndex;
1569 tEplNmtMnuNodeInfo *pNodeInfo;
1571 if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
1572 // add nodes to isochronous phase and send NMT EnableReadyToOp
1573 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1574 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1575 // reset flag that application was informed about possible state change
1576 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1578 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1579 for (uiIndex = 1;
1580 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1581 uiIndex++, pNodeInfo++) {
1582 if (pNodeInfo->m_NodeState ==
1583 kEplNmtMnuNodeStateConfigured) {
1584 Ret =
1585 EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1586 if (Ret != kEplSuccessful) {
1587 goto Exit;
1589 // set flag "not scanned"
1590 pNodeInfo->m_wFlags |=
1591 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1593 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1594 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1596 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1597 EplNmtMnuInstance_g.
1598 m_uiMandatorySlaveCount++;
1600 // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp
1605 Exit:
1606 return Ret;
1609 //---------------------------------------------------------------------------
1611 // Function: EplNmtMnuNodeBootStep2
1613 // Description: starts BootStep2 for the specified node.
1614 // This means the CN is added to isochronous phase if not
1615 // async-only and it gets the NMT command EnableReadyToOp.
1616 // The CN must be in node state Configured, when it enters
1617 // BootStep2. When BootStep2 finishes, the CN is in node state
1618 // ReadyToOp.
1619 // If TimeoutReadyToOp in object 0x1F89/5 is configured,
1620 // TimerHdlLonger will be started with this timeout.
1622 // Parameters: uiNodeId_p = node ID
1623 // pNodeInfo_p = pointer to internal node info structure
1625 // Returns: tEplKernel = error code
1627 // State:
1629 //---------------------------------------------------------------------------
1631 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
1632 tEplNmtMnuNodeInfo * pNodeInfo_p)
1634 tEplKernel Ret = kEplSuccessful;
1635 tEplDllNodeInfo DllNodeInfo;
1636 DWORD dwNodeCfg;
1637 tEplObdSize ObdSize;
1638 tEplTimerArg TimerArg;
1640 dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
1641 if ((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0) { // add node to isochronous phase
1642 DllNodeInfo.m_uiNodeId = uiNodeId_p;
1643 ObdSize = 4;
1644 Ret =
1645 EplObduReadEntry(0x1F92, uiNodeId_p,
1646 &DllNodeInfo.m_dwPresTimeout, &ObdSize);
1647 if (Ret != kEplSuccessful) {
1648 goto Exit;
1651 ObdSize = 2;
1652 Ret =
1653 EplObduReadEntry(0x1F8B, uiNodeId_p,
1654 &DllNodeInfo.m_wPreqPayloadLimit,
1655 &ObdSize);
1656 if (Ret != kEplSuccessful) {
1657 goto Exit;
1660 ObdSize = 2;
1661 Ret =
1662 EplObduReadEntry(0x1F8D, uiNodeId_p,
1663 &DllNodeInfo.m_wPresPayloadLimit,
1664 &ObdSize);
1665 if (Ret != kEplSuccessful) {
1666 goto Exit;
1669 pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON;
1671 Ret = EplDlluCalAddNode(&DllNodeInfo);
1672 if (Ret != kEplSuccessful) {
1673 goto Exit;
1678 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1679 uiNodeId_p,
1680 kEplNmtCmdEnableReadyToOperate);
1682 Ret =
1683 EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate);
1684 if (Ret != kEplSuccessful) {
1685 goto Exit;
1688 if (EplNmtMnuInstance_g.m_ulTimeoutReadyToOp != 0L) { // start timer
1689 // when the timer expires the CN must be ReadyToOp
1690 EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
1691 TimerArg);
1692 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1693 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1694 Ret =
1695 EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1696 EplNmtMnuInstance_g.
1697 m_ulTimeoutReadyToOp, TimerArg);
1700 Exit:
1701 return Ret;
1704 //---------------------------------------------------------------------------
1706 // Function: EplNmtMnuStartCheckCom
1708 // Description: starts CheckCommunication
1710 // Parameters: (none)
1712 // Returns: tEplKernel = error code
1714 // State:
1716 //---------------------------------------------------------------------------
1718 static tEplKernel EplNmtMnuStartCheckCom(void)
1720 tEplKernel Ret = kEplSuccessful;
1721 unsigned int uiIndex;
1722 tEplNmtMnuNodeInfo *pNodeInfo;
1724 if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
1725 // wait some time and check that no communication error occurs
1726 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1727 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1728 // reset flag that application was informed about possible state change
1729 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1731 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1732 for (uiIndex = 1;
1733 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1734 uiIndex++, pNodeInfo++) {
1735 if (pNodeInfo->m_NodeState ==
1736 kEplNmtMnuNodeStateReadyToOp) {
1737 Ret = EplNmtMnuNodeCheckCom(uiIndex, pNodeInfo);
1738 if (Ret == kEplReject) { // timer was started
1739 // wait until it expires
1740 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1741 EplNmtMnuInstance_g.
1742 m_uiMandatorySlaveCount++;
1744 } else if (Ret != kEplSuccessful) {
1745 goto Exit;
1747 // set flag "not scanned"
1748 pNodeInfo->m_wFlags |=
1749 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1751 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1752 // signal slave counter shall be decremented if timeout elapsed and regardless of an error
1753 // mandatory slave counter shall be decremented if timeout elapsed and no error occured
1758 Ret = kEplSuccessful;
1760 Exit:
1761 return Ret;
1764 //---------------------------------------------------------------------------
1766 // Function: EplNmtMnuNodeCheckCom
1768 // Description: checks communication of the specified node.
1769 // That means wait some time and if no error occured everything
1770 // is OK.
1772 // Parameters: uiNodeId_p = node ID
1773 // pNodeInfo_p = pointer to internal node info structure
1775 // Returns: tEplKernel = error code
1777 // State:
1779 //---------------------------------------------------------------------------
1781 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
1782 tEplNmtMnuNodeInfo * pNodeInfo_p)
1784 tEplKernel Ret = kEplSuccessful;
1785 DWORD dwNodeCfg;
1786 tEplTimerArg TimerArg;
1788 dwNodeCfg = pNodeInfo_p->m_dwNodeCfg;
1789 if (((dwNodeCfg & EPL_NODEASSIGN_ASYNCONLY_NODE) == 0)
1790 && (EplNmtMnuInstance_g.m_ulTimeoutCheckCom != 0L)) { // CN is not async-only and timeout for CheckCom was set
1792 // check communication,
1793 // that means wait some time and if no error occured everything is OK;
1795 // start timer (when the timer expires the CN must be still ReadyToOp)
1796 EPL_NMTMNU_SET_FLAGS_TIMERARG_LONGER(pNodeInfo_p, uiNodeId_p,
1797 TimerArg);
1798 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1799 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1800 Ret =
1801 EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1802 EplNmtMnuInstance_g.
1803 m_ulTimeoutCheckCom, TimerArg);
1805 // update mandatory slave counter, because timer was started
1806 if (Ret == kEplSuccessful) {
1807 Ret = kEplReject;
1809 } else { // timer was not started
1810 // assume everything is OK
1811 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked;
1814 //Exit:
1815 return Ret;
1818 //---------------------------------------------------------------------------
1820 // Function: EplNmtMnuStartNodes
1822 // Description: really starts all nodes which are ReadyToOp and CheckCom did not fail
1824 // Parameters: (none)
1826 // Returns: tEplKernel = error code
1828 // State:
1830 //---------------------------------------------------------------------------
1832 static tEplKernel EplNmtMnuStartNodes(void)
1834 tEplKernel Ret = kEplSuccessful;
1835 unsigned int uiIndex;
1836 tEplNmtMnuNodeInfo *pNodeInfo;
1838 if ((EplNmtMnuInstance_g.m_wFlags & EPL_NMTMNU_FLAG_HALTED) == 0) { // boot process is not halted
1839 // send NMT command Start Node
1840 EplNmtMnuInstance_g.m_uiMandatorySlaveCount = 0;
1841 EplNmtMnuInstance_g.m_uiSignalSlaveCount = 0;
1842 // reset flag that application was informed about possible state change
1843 EplNmtMnuInstance_g.m_wFlags &= ~EPL_NMTMNU_FLAG_APP_INFORMED;
1845 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo;
1846 for (uiIndex = 1;
1847 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1848 uiIndex++, pNodeInfo++) {
1849 if (pNodeInfo->m_NodeState ==
1850 kEplNmtMnuNodeStateComChecked) {
1851 if ((EplNmtMnuInstance_g.
1852 m_dwNmtStartup & EPL_NMTST_STARTALLNODES)
1853 == 0) {
1854 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1855 uiIndex,
1856 kEplNmtCmdStartNode);
1858 Ret =
1859 EplNmtMnuSendNmtCommand(uiIndex,
1860 kEplNmtCmdStartNode);
1861 if (Ret != kEplSuccessful) {
1862 goto Exit;
1866 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN
1867 EplNmtMnuInstance_g.
1868 m_uiMandatorySlaveCount++;
1870 // set flag "not scanned"
1871 pNodeInfo->m_wFlags |=
1872 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1874 EplNmtMnuInstance_g.m_uiSignalSlaveCount++;
1875 // signal slave counter shall be decremented if StatusRequest was sent once to a CN
1876 // mandatory slave counter shall be decremented if mandatory CN is OPERATIONAL
1880 // $$$ inform application if EPL_NMTST_NO_STARTNODE is set
1882 if ((EplNmtMnuInstance_g.
1883 m_dwNmtStartup & EPL_NMTST_STARTALLNODES) != 0) {
1884 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, EPL_C_ADR_BROADCAST,
1885 kEplNmtCmdStartNode);
1887 Ret =
1888 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
1889 kEplNmtCmdStartNode);
1890 if (Ret != kEplSuccessful) {
1891 goto Exit;
1896 Exit:
1897 return Ret;
1900 //---------------------------------------------------------------------------
1902 // Function: EplNmtMnuProcessInternalEvent
1904 // Description: processes internal node events
1906 // Parameters: uiNodeId_p = node ID
1907 // NodeNmtState_p = NMT state of CN
1908 // NodeEvent_p = occured events
1910 // Returns: tEplKernel = error code
1913 // State:
1915 //---------------------------------------------------------------------------
1917 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
1918 tEplNmtState NodeNmtState_p,
1919 WORD wErrorCode_p,
1920 tEplNmtMnuIntNodeEvent
1921 NodeEvent_p)
1923 tEplKernel Ret = kEplSuccessful;
1924 tEplNmtState NmtState;
1925 tEplNmtMnuNodeInfo *pNodeInfo;
1926 tEplTimerArg TimerArg;
1928 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId_p);
1929 NmtState = EplNmtuGetNmtState();
1930 if (NmtState <= kEplNmtMsNotActive) { // MN is not active
1931 goto Exit;
1934 switch (NodeEvent_p) {
1935 case kEplNmtMnuIntNodeEventIdentResponse:
1937 BYTE bNmtState;
1939 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1940 uiNodeId_p,
1941 pNodeInfo->m_NodeState);
1943 if (pNodeInfo->m_NodeState !=
1944 kEplNmtMnuNodeStateResetConf) {
1945 pNodeInfo->m_NodeState =
1946 kEplNmtMnuNodeStateIdentified;
1948 // reset flags ISOCHRON and NMT_CMD_ISSUED
1949 pNodeInfo->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON
1951 EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED);
1953 if ((NmtState == kEplNmtMsPreOperational1)
1955 ((pNodeInfo->
1956 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
1957 0)) {
1958 // decrement only signal slave count
1959 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
1960 pNodeInfo->m_wFlags &=
1961 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
1963 // update object 0x1F8F NMT_MNNodeExpState_AU8 to PreOp1 (even if local state >= PreOp2)
1964 bNmtState = (BYTE) (kEplNmtCsPreOperational1 & 0xFF);
1965 Ret =
1966 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
1969 // check NMT state of CN
1970 Ret =
1971 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
1972 NodeNmtState_p, wErrorCode_p,
1973 NmtState);
1974 if (Ret != kEplSuccessful) {
1975 if (Ret == kEplReject) {
1976 Ret = kEplSuccessful;
1978 break;
1980 // request StatusResponse immediately,
1981 // because we want a fast boot-up of CNs
1982 Ret =
1983 EplStatusuRequestStatusResponse(uiNodeId_p,
1984 EplNmtMnuCbStatusResponse);
1985 if (Ret != kEplSuccessful) {
1986 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1987 uiNodeId_p,
1988 Ret);
1990 if (Ret == kEplInvalidOperation) { // the only situation when this should happen is, when
1991 // StatusResponse was already requested from within
1992 // the StatReq timer event.
1993 // so ignore this error.
1994 Ret = kEplSuccessful;
1995 } else {
1996 break;
2000 if (pNodeInfo->m_NodeState !=
2001 kEplNmtMnuNodeStateResetConf) {
2002 // inform application
2003 Ret =
2004 EplNmtMnuInstance_g.
2005 m_pfnCbNodeEvent(uiNodeId_p,
2006 kEplNmtNodeEventFound,
2007 NodeNmtState_p,
2008 EPL_E_NO_ERROR,
2009 (pNodeInfo->
2010 m_dwNodeCfg &
2011 EPL_NODEASSIGN_MANDATORY_CN)
2012 != 0);
2013 if (Ret == kEplReject) { // interrupt boot process on user request
2014 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2015 (NodeEvent_p, uiNodeId_p,
2016 ((pNodeInfo->m_NodeState << 8)
2017 | Ret));
2019 Ret = kEplSuccessful;
2020 break;
2021 } else if (Ret != kEplSuccessful) {
2022 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2023 (NodeEvent_p, uiNodeId_p,
2024 ((pNodeInfo->m_NodeState << 8)
2025 | Ret));
2027 break;
2030 // continue BootStep1
2033 case kEplNmtMnuIntNodeEventBoot:
2036 // $$$ check identification (vendor ID, product code, revision no, serial no)
2038 if (pNodeInfo->m_NodeState ==
2039 kEplNmtMnuNodeStateIdentified) {
2040 // $$$ check software
2042 // check/start configuration
2043 // inform application
2044 Ret =
2045 EplNmtMnuInstance_g.
2046 m_pfnCbNodeEvent(uiNodeId_p,
2047 kEplNmtNodeEventCheckConf,
2048 NodeNmtState_p,
2049 EPL_E_NO_ERROR,
2050 (pNodeInfo->
2051 m_dwNodeCfg &
2052 EPL_NODEASSIGN_MANDATORY_CN)
2053 != 0);
2054 if (Ret == kEplReject) { // interrupt boot process on user request
2055 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2056 (kEplNmtMnuIntNodeEventBoot,
2057 uiNodeId_p,
2058 ((pNodeInfo->m_NodeState << 8)
2059 | Ret));
2061 Ret = kEplSuccessful;
2062 break;
2063 } else if (Ret != kEplSuccessful) {
2064 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2065 (kEplNmtMnuIntNodeEventBoot,
2066 uiNodeId_p,
2067 ((pNodeInfo->m_NodeState << 8)
2068 | Ret));
2070 break;
2072 } else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) { // wrong CN state
2073 // ignore event
2074 break;
2076 // $$$ d.k.: currently we assume configuration is OK
2078 // continue BootStep1
2081 case kEplNmtMnuIntNodeEventConfigured:
2083 if ((pNodeInfo->m_NodeState !=
2084 kEplNmtMnuNodeStateIdentified)
2085 && (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf)) { // wrong CN state
2086 // ignore event
2087 break;
2090 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateConfigured;
2092 if (NmtState == kEplNmtMsPreOperational1) {
2093 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // decrement mandatory CN counter
2094 EplNmtMnuInstance_g.
2095 m_uiMandatorySlaveCount--;
2097 } else {
2098 // put optional node to next step (BootStep2)
2099 Ret =
2100 EplNmtMnuNodeBootStep2(uiNodeId_p,
2101 pNodeInfo);
2103 break;
2106 case kEplNmtMnuIntNodeEventNoIdentResponse:
2108 if ((NmtState == kEplNmtMsPreOperational1)
2110 ((pNodeInfo->
2111 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2112 0)) {
2113 // decrement only signal slave count
2114 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2115 pNodeInfo->m_wFlags &=
2116 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2119 if (pNodeInfo->m_NodeState !=
2120 kEplNmtMnuNodeStateResetConf) {
2121 pNodeInfo->m_NodeState =
2122 kEplNmtMnuNodeStateUnknown;
2124 // $$$ d.k. check start time for 0x1F89/2 MNTimeoutPreOp1_U32
2125 // $$$ d.k. check individual timeout 0x1F89/6 MNIdentificationTimeout_U32
2126 // if mandatory node and timeout elapsed -> halt boot procedure
2127 // trigger IdentRequest again (if >= PreOp2, after delay)
2128 if (NmtState >= kEplNmtMsPreOperational2) { // start timer
2129 EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
2130 (pNodeInfo, uiNodeId_p, TimerArg);
2131 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2132 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_IDENTREQ | uiNodeId_p;
2134 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventNoIdentResponse,
2135 uiNodeId_p,
2136 ((pNodeInfo->m_NodeState << 8)
2137 | 0x80
2138 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2139 | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2141 Ret =
2142 EplTimeruModifyTimerMs(&pNodeInfo->
2143 m_TimerHdlStatReq,
2144 EplNmtMnuInstance_g.
2145 m_ulStatusRequestDelay,
2146 TimerArg);
2147 } else { // trigger IdentRequest immediately
2148 Ret =
2149 EplIdentuRequestIdentResponse(uiNodeId_p,
2150 EplNmtMnuCbIdentResponse);
2152 break;
2155 case kEplNmtMnuIntNodeEventStatusResponse:
2157 if ((NmtState >= kEplNmtMsPreOperational2)
2159 ((pNodeInfo->
2160 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2161 0)) {
2162 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2163 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2164 pNodeInfo->m_wFlags &=
2165 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2167 // check NMT state of CN
2168 Ret =
2169 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2170 NodeNmtState_p, wErrorCode_p,
2171 NmtState);
2172 if (Ret != kEplSuccessful) {
2173 if (Ret == kEplReject) {
2174 Ret = kEplSuccessful;
2176 break;
2179 if (NmtState == kEplNmtMsPreOperational1) {
2180 // request next StatusResponse immediately
2181 Ret =
2182 EplStatusuRequestStatusResponse(uiNodeId_p,
2183 EplNmtMnuCbStatusResponse);
2184 if (Ret != kEplSuccessful) {
2185 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2186 (NodeEvent_p, uiNodeId_p, Ret);
2189 } else if ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_ISOCHRON) == 0) { // start timer
2190 // not isochronously accessed CN (e.g. async-only or stopped CN)
2191 EPL_NMTMNU_SET_FLAGS_TIMERARG_STATREQ(pNodeInfo,
2192 uiNodeId_p,
2193 TimerArg);
2194 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2195 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p;
2197 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventStatusResponse,
2198 uiNodeId_p,
2199 ((pNodeInfo->m_NodeState << 8)
2200 | 0x80
2201 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2202 | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2204 Ret =
2205 EplTimeruModifyTimerMs(&pNodeInfo->
2206 m_TimerHdlStatReq,
2207 EplNmtMnuInstance_g.
2208 m_ulStatusRequestDelay,
2209 TimerArg);
2212 break;
2215 case kEplNmtMnuIntNodeEventNoStatusResponse:
2217 // function CheckNmtState sets node state to unknown if necessary
2219 if ((NmtState >= kEplNmtMsPreOperational2)
2220 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
2222 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2223 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2224 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2227 // check NMT state of CN
2228 Ret =
2229 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2230 NodeNmtState_p, wErrorCode_p,
2231 NmtState);
2232 if (Ret != kEplSuccessful) {
2233 if (Ret == kEplReject) {
2234 Ret = kEplSuccessful;
2236 break;
2239 break;
2242 case kEplNmtMnuIntNodeEventError:
2243 { // currently only issued on kEplNmtNodeCommandConfErr
2245 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
2246 // ignore event
2247 break;
2249 // check NMT state of CN
2250 Ret =
2251 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2252 kEplNmtCsNotActive,
2253 wErrorCode_p, NmtState);
2254 if (Ret != kEplSuccessful) {
2255 if (Ret == kEplReject) {
2256 Ret = kEplSuccessful;
2258 break;
2261 break;
2264 case kEplNmtMnuIntNodeEventExecReset:
2266 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
2267 // ignore event
2268 break;
2271 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf;
2273 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2274 uiNodeId_p,
2275 (((NodeNmtState_p &
2276 0xFF) << 8)
2278 kEplNmtCmdResetConfiguration));
2280 // send NMT reset configuration to CN for activation of configuration
2281 Ret =
2282 EplNmtMnuSendNmtCommand(uiNodeId_p,
2283 kEplNmtCmdResetConfiguration);
2285 break;
2288 case kEplNmtMnuIntNodeEventHeartbeat:
2291 if ((NmtState >= kEplNmtMsPreOperational2)
2292 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0))
2294 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2295 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2296 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2299 // check NMT state of CN
2300 Ret =
2301 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2302 NodeNmtState_p, wErrorCode_p,
2303 NmtState);
2304 if (Ret != kEplSuccessful) {
2305 if (Ret == kEplReject) {
2306 Ret = kEplSuccessful;
2308 break;
2311 break;
2314 case kEplNmtMnuIntNodeEventTimerIdentReq:
2316 EPL_DBGLVL_NMTMN_TRACE1
2317 ("TimerStatReq->IdentReq(%02X)\n", uiNodeId_p);
2318 // trigger IdentRequest again
2319 Ret =
2320 EplIdentuRequestIdentResponse(uiNodeId_p,
2321 EplNmtMnuCbIdentResponse);
2322 if (Ret != kEplSuccessful) {
2323 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2324 uiNodeId_p,
2325 (((NodeNmtState_p & 0xFF) << 8)
2326 | Ret));
2327 if (Ret == kEplInvalidOperation) { // this can happen because of a bug in EplTimeruLinuxKernel.c
2328 // so ignore this error.
2329 Ret = kEplSuccessful;
2333 break;
2336 case kEplNmtMnuIntNodeEventTimerStateMon:
2338 // reset NMT state change flag
2339 // because from now on the CN must have the correct NMT state
2340 pNodeInfo->m_wFlags &=
2341 ~EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
2343 // continue with normal StatReq processing
2346 case kEplNmtMnuIntNodeEventTimerStatReq:
2348 EPL_DBGLVL_NMTMN_TRACE1("TimerStatReq->StatReq(%02X)\n",
2349 uiNodeId_p);
2350 // request next StatusResponse
2351 Ret =
2352 EplStatusuRequestStatusResponse(uiNodeId_p,
2353 EplNmtMnuCbStatusResponse);
2354 if (Ret != kEplSuccessful) {
2355 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2356 uiNodeId_p,
2357 (((NodeNmtState_p & 0xFF) << 8)
2358 | Ret));
2359 if (Ret == kEplInvalidOperation) { // the only situation when this should happen is, when
2360 // StatusResponse was already requested while processing
2361 // event IdentResponse.
2362 // so ignore this error.
2363 Ret = kEplSuccessful;
2367 break;
2370 case kEplNmtMnuIntNodeEventTimerLonger:
2372 switch (pNodeInfo->m_NodeState) {
2373 case kEplNmtMnuNodeStateConfigured:
2374 { // node should be ReadyToOp but it is not
2376 // check NMT state which shall be intentionally wrong, so that ERROR_TREATMENT will be started
2377 Ret =
2378 EplNmtMnuCheckNmtState(uiNodeId_p,
2379 pNodeInfo,
2380 kEplNmtCsNotActive,
2381 EPL_E_NMT_BPO2,
2382 NmtState);
2383 if (Ret != kEplSuccessful) {
2384 if (Ret == kEplReject) {
2385 Ret = kEplSuccessful;
2387 break;
2390 break;
2393 case kEplNmtMnuNodeStateReadyToOp:
2394 { // CheckCom finished successfully
2396 pNodeInfo->m_NodeState =
2397 kEplNmtMnuNodeStateComChecked;
2399 if ((pNodeInfo->
2400 m_wFlags &
2401 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED)
2402 != 0) {
2403 // decrement only signal slave count if checked once for ReadyToOp, CheckCom, Operational
2404 EplNmtMnuInstance_g.
2405 m_uiSignalSlaveCount--;
2406 pNodeInfo->m_wFlags &=
2407 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2410 if ((pNodeInfo->
2411 m_dwNodeCfg &
2412 EPL_NODEASSIGN_MANDATORY_CN) !=
2413 0) {
2414 // decrement mandatory slave counter
2415 EplNmtMnuInstance_g.
2416 m_uiMandatorySlaveCount--;
2418 if (NmtState != kEplNmtMsReadyToOperate) {
2419 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2420 (NodeEvent_p, uiNodeId_p,
2421 (((NodeNmtState_p & 0xFF)
2422 << 8)
2423 | kEplNmtCmdStartNode));
2425 // start optional CN
2426 Ret =
2427 EplNmtMnuSendNmtCommand
2428 (uiNodeId_p,
2429 kEplNmtCmdStartNode);
2431 break;
2434 default:
2436 break;
2439 break;
2442 case kEplNmtMnuIntNodeEventNmtCmdSent:
2444 BYTE bNmtState;
2446 // update expected NMT state with the one that results
2447 // from the sent NMT command
2448 bNmtState = (BYTE) (NodeNmtState_p & 0xFF);
2450 // write object 0x1F8F NMT_MNNodeExpState_AU8
2451 Ret =
2452 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
2454 if (Ret != kEplSuccessful) {
2455 goto Exit;
2458 if (NodeNmtState_p == kEplNmtCsNotActive) { // restart processing with IdentRequest
2459 EPL_NMTMNU_SET_FLAGS_TIMERARG_IDENTREQ
2460 (pNodeInfo, uiNodeId_p, TimerArg);
2461 } else { // monitor NMT state change with StatusRequest after
2462 // the corresponding delay;
2463 // until then wrong NMT states will be ignored
2464 EPL_NMTMNU_SET_FLAGS_TIMERARG_STATE_MON
2465 (pNodeInfo, uiNodeId_p, TimerArg);
2467 // set NMT state change flag
2468 pNodeInfo->m_wFlags |=
2469 EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED;
2472 Ret =
2473 EplTimeruModifyTimerMs(&pNodeInfo->
2474 m_TimerHdlStatReq,
2475 EplNmtMnuInstance_g.
2476 m_ulStatusRequestDelay,
2477 TimerArg);
2479 // finish processing, because NmtState_p is the expected and not the current state
2480 goto Exit;
2483 default:
2485 break;
2489 // check if network is ready to change local NMT state and this was not done before
2490 if ((EplNmtMnuInstance_g.m_wFlags & (EPL_NMTMNU_FLAG_HALTED | EPL_NMTMNU_FLAG_APP_INFORMED)) == 0) { // boot process is not halted
2491 switch (NmtState) {
2492 case kEplNmtMsPreOperational1:
2494 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2496 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs scanned once and all mandatory CNs configured successfully
2497 EplNmtMnuInstance_g.m_wFlags |=
2498 EPL_NMTMNU_FLAG_APP_INFORMED;
2499 // inform application
2500 Ret =
2501 EplNmtMnuInstance_g.
2502 m_pfnCbBootEvent
2503 (kEplNmtBootEventBootStep1Finish,
2504 NmtState, EPL_E_NO_ERROR);
2505 if (Ret != kEplSuccessful) {
2506 if (Ret == kEplReject) {
2507 // wait for application
2508 Ret = kEplSuccessful;
2510 break;
2512 // enter PreOp2
2513 Ret =
2514 EplNmtuNmtEvent
2515 (kEplNmtEventAllMandatoryCNIdent);
2517 break;
2520 case kEplNmtMsPreOperational2:
2522 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2524 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs checked once for ReadyToOp and all mandatory CNs are ReadyToOp
2525 EplNmtMnuInstance_g.m_wFlags |=
2526 EPL_NMTMNU_FLAG_APP_INFORMED;
2527 // inform application
2528 Ret =
2529 EplNmtMnuInstance_g.
2530 m_pfnCbBootEvent
2531 (kEplNmtBootEventBootStep2Finish,
2532 NmtState, EPL_E_NO_ERROR);
2533 if (Ret != kEplSuccessful) {
2534 if (Ret == kEplReject) {
2535 // wait for application
2536 Ret = kEplSuccessful;
2538 break;
2540 // enter ReadyToOp
2541 Ret =
2542 EplNmtuNmtEvent
2543 (kEplNmtEventEnterReadyToOperate);
2545 break;
2548 case kEplNmtMsReadyToOperate:
2550 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2552 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all CNs checked for errorless communication
2553 EplNmtMnuInstance_g.m_wFlags |=
2554 EPL_NMTMNU_FLAG_APP_INFORMED;
2555 // inform application
2556 Ret =
2557 EplNmtMnuInstance_g.
2558 m_pfnCbBootEvent
2559 (kEplNmtBootEventCheckComFinish,
2560 NmtState, EPL_E_NO_ERROR);
2561 if (Ret != kEplSuccessful) {
2562 if (Ret == kEplReject) {
2563 // wait for application
2564 Ret = kEplSuccessful;
2566 break;
2568 // enter Operational
2569 Ret =
2570 EplNmtuNmtEvent
2571 (kEplNmtEventEnterMsOperational);
2573 break;
2576 case kEplNmtMsOperational:
2578 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount ==
2580 && (EplNmtMnuInstance_g.m_uiMandatorySlaveCount == 0)) { // all optional CNs scanned once and all mandatory CNs are OPERATIONAL
2581 EplNmtMnuInstance_g.m_wFlags |=
2582 EPL_NMTMNU_FLAG_APP_INFORMED;
2583 // inform application
2584 Ret =
2585 EplNmtMnuInstance_g.
2586 m_pfnCbBootEvent
2587 (kEplNmtBootEventOperational,
2588 NmtState, EPL_E_NO_ERROR);
2589 if (Ret != kEplSuccessful) {
2590 if (Ret == kEplReject) {
2591 // ignore error code
2592 Ret = kEplSuccessful;
2594 break;
2597 break;
2600 default:
2602 break;
2607 Exit:
2608 return Ret;
2611 //---------------------------------------------------------------------------
2613 // Function: EplNmtMnuCheckNmtState
2615 // Description: checks the NMT state, i.e. evaluates it with object 0x1F8F
2616 // NMT_MNNodeExpState_AU8 and updates object 0x1F8E
2617 // NMT_MNNodeCurrState_AU8.
2618 // It manipulates m_NodeState in internal node info structure.
2620 // Parameters: uiNodeId_p = node ID
2621 // NodeNmtState_p = NMT state of CN
2623 // Returns: tEplKernel = error code
2624 // kEplReject = CN was in wrong state and has been reset
2626 // State:
2628 //---------------------------------------------------------------------------
2630 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
2631 tEplNmtMnuNodeInfo * pNodeInfo_p,
2632 tEplNmtState NodeNmtState_p,
2633 WORD wErrorCode_p,
2634 tEplNmtState LocalNmtState_p)
2636 tEplKernel Ret = kEplSuccessful;
2637 tEplObdSize ObdSize;
2638 BYTE bNmtState;
2639 BYTE bNmtStatePrev;
2640 tEplNmtState ExpNmtState;
2642 ObdSize = 1;
2643 // read object 0x1F8F NMT_MNNodeExpState_AU8
2644 Ret = EplObduReadEntry(0x1F8F, uiNodeId_p, &bNmtState, &ObdSize);
2645 if (Ret != kEplSuccessful) {
2646 goto Exit;
2648 // compute expected NMT state
2649 ExpNmtState = (tEplNmtState) (bNmtState | EPL_NMT_TYPE_CS);
2650 // compute BYTE of current NMT state
2651 bNmtState = ((BYTE) NodeNmtState_p & 0xFF);
2653 if (ExpNmtState == kEplNmtCsNotActive) { // ignore the current state, because the CN shall be not active
2654 Ret = kEplReject;
2655 goto Exit;
2656 } else if ((ExpNmtState == kEplNmtCsPreOperational2)
2657 && (NodeNmtState_p == kEplNmtCsReadyToOperate)) { // CN switched to ReadyToOp
2658 // delete timer for timeout handling
2659 Ret = EplTimeruDeleteTimer(&pNodeInfo_p->m_TimerHdlLonger);
2660 if (Ret != kEplSuccessful) {
2661 goto Exit;
2663 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateReadyToOp;
2665 // update object 0x1F8F NMT_MNNodeExpState_AU8 to ReadyToOp
2666 Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1);
2667 if (Ret != kEplSuccessful) {
2668 goto Exit;
2671 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter
2672 EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
2674 if (LocalNmtState_p >= kEplNmtMsReadyToOperate) { // start procedure CheckCommunication for this node
2675 Ret = EplNmtMnuNodeCheckCom(uiNodeId_p, pNodeInfo_p);
2676 if (Ret != kEplSuccessful) {
2677 goto Exit;
2680 if ((LocalNmtState_p == kEplNmtMsOperational)
2681 && (pNodeInfo_p->m_NodeState ==
2682 kEplNmtMnuNodeStateComChecked)) {
2683 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, uiNodeId_p,
2684 (((NodeNmtState_p & 0xFF) << 8)
2686 kEplNmtCmdStartNode));
2688 // immediately start optional CN, because communication is always OK (e.g. async-only CN)
2689 Ret =
2690 EplNmtMnuSendNmtCommand(uiNodeId_p,
2691 kEplNmtCmdStartNode);
2692 if (Ret != kEplSuccessful) {
2693 goto Exit;
2698 } else if ((ExpNmtState == kEplNmtCsReadyToOperate)
2699 && (NodeNmtState_p == kEplNmtCsOperational)) { // CN switched to OPERATIONAL
2700 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateOperational;
2702 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter
2703 EplNmtMnuInstance_g.m_uiMandatorySlaveCount--;
2706 } else if ((ExpNmtState != NodeNmtState_p)
2707 && !((ExpNmtState == kEplNmtCsPreOperational1)
2708 && (NodeNmtState_p == kEplNmtCsPreOperational2))) { // CN is not in expected NMT state (without the exceptions above)
2709 WORD wbeErrorCode;
2711 if ((pNodeInfo_p->
2712 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0) {
2713 // decrement only signal slave count if checked once
2714 EplNmtMnuInstance_g.m_uiSignalSlaveCount--;
2715 pNodeInfo_p->m_wFlags &=
2716 ~EPL_NMTMNU_NODE_FLAG_NOT_SCANNED;
2719 if (pNodeInfo_p->m_NodeState == kEplNmtMnuNodeStateUnknown) { // CN is already in state unknown, which means that it got
2720 // NMT reset command earlier
2721 goto Exit;
2723 // -> CN is in wrong NMT state
2724 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateUnknown;
2726 if (wErrorCode_p == 0) { // assume wrong NMT state error
2727 if ((pNodeInfo_p->m_wFlags & EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED) != 0) { // NMT command has been just issued;
2728 // ignore wrong NMT state until timer expires;
2729 // other errors like LOSS_PRES_TH are still processed
2730 goto Exit;
2733 wErrorCode_p = EPL_E_NMT_WRONG_STATE;
2736 BENCHMARK_MOD_07_TOGGLE(9);
2738 // $$$ start ERROR_TREATMENT and inform application
2739 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2740 kEplNmtNodeEventError,
2741 NodeNmtState_p,
2742 wErrorCode_p,
2743 (pNodeInfo_p->
2744 m_dwNodeCfg &
2745 EPL_NODEASSIGN_MANDATORY_CN)
2746 != 0);
2747 if (Ret != kEplSuccessful) {
2748 goto Exit;
2751 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
2752 uiNodeId_p,
2753 (((NodeNmtState_p & 0xFF) << 8)
2754 | kEplNmtCmdResetNode));
2756 // reset CN
2757 // store error code in NMT command data for diagnostic purpose
2758 AmiSetWordToLe(&wbeErrorCode, wErrorCode_p);
2759 Ret =
2760 EplNmtMnuSendNmtCommandEx(uiNodeId_p, kEplNmtCmdResetNode,
2761 &wbeErrorCode,
2762 sizeof(wbeErrorCode));
2763 if (Ret == kEplSuccessful) {
2764 Ret = kEplReject;
2767 goto Exit;
2769 // check if NMT_MNNodeCurrState_AU8 has to be changed
2770 ObdSize = 1;
2771 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtStatePrev, &ObdSize);
2772 if (Ret != kEplSuccessful) {
2773 goto Exit;
2775 if (bNmtState != bNmtStatePrev) {
2776 // update object 0x1F8E NMT_MNNodeCurrState_AU8
2777 Ret = EplObduWriteEntry(0x1F8E, uiNodeId_p, &bNmtState, 1);
2778 if (Ret != kEplSuccessful) {
2779 goto Exit;
2781 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2782 kEplNmtNodeEventNmtState,
2783 NodeNmtState_p,
2784 wErrorCode_p,
2785 (pNodeInfo_p->
2786 m_dwNodeCfg &
2787 EPL_NODEASSIGN_MANDATORY_CN)
2788 != 0);
2789 if (Ret != kEplSuccessful) {
2790 goto Exit;
2794 Exit:
2795 return Ret;
2798 //---------------------------------------------------------------------------
2800 // Function: EplNmtMnuReset
2802 // Description: reset internal structures, e.g. timers
2804 // Parameters: void
2806 // Returns: tEplKernel = error code
2808 // State:
2810 //---------------------------------------------------------------------------
2812 static tEplKernel EplNmtMnuReset(void)
2814 tEplKernel Ret;
2815 int iIndex;
2817 Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState);
2819 for (iIndex = 1; iIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
2820 iIndex++) {
2821 // delete timer handles
2822 Ret =
2823 EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2824 m_TimerHdlStatReq);
2825 Ret =
2826 EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2827 m_TimerHdlLonger);
2830 return Ret;
2833 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2835 // EOF