Staging: epl: fix up some non-ANSI functions
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / epl / EplNmtMnu.c
bloba9ba55aec82cf2ecf6a7d396e5927d102ae20c8a
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 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)
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 u32 m_dwNodeCfg; // subindex from 0x1F81
215 u16 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 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 //---------------------------------------------------------------------------
235 // local vars
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,
255 u16 wErrorCode_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,
274 u16 wErrorCode_p,
275 tEplNmtMnuIntNodeEvent
276 NodeEvent_p);
278 static tEplKernel EplNmtMnuReset(void);
280 //=========================================================================//
281 // //
282 // P U B L I C F U N C T I O N S //
283 // //
284 //=========================================================================//
286 //---------------------------------------------------------------------------
288 // Function: EplNmtMnuInit
290 // Description: init first instance of the module
294 // Parameters:
297 // Returns: tEplKernel = errorcode
300 // State:
302 //---------------------------------------------------------------------------
304 tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
305 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
307 tEplKernel Ret;
309 Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p);
311 return Ret;
314 //---------------------------------------------------------------------------
316 // Function: EplNmtMnuAddInstance
318 // Description: init other instances of the module
322 // Parameters:
325 // Returns: tEplKernel = errorcode
328 // State:
330 //---------------------------------------------------------------------------
332 tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p,
333 tEplNmtMnuCbBootEvent pfnCbBootEvent_p)
335 tEplKernel Ret;
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;
344 goto Exit;
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
353 Ret =
354 EplDlluCalRegAsndService(kEplDllAsndNmtRequest,
355 EplNmtMnuCbNmtRequest,
356 kEplDllAsndFilterLocal);
358 Exit:
359 return Ret;
363 //---------------------------------------------------------------------------
365 // Function: EplNmtMnuDelInstance
367 // Description: delete instance
371 // Parameters:
374 // Returns: tEplKernel = errorcode
377 // State:
379 //---------------------------------------------------------------------------
381 tEplKernel EplNmtMnuDelInstance(void)
383 tEplKernel Ret;
385 Ret = kEplSuccessful;
387 // deregister NmtMnResponse callback function
388 Ret =
389 EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL,
390 kEplDllAsndFilterNone);
392 Ret = EplNmtMnuReset();
394 return Ret;
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
409 // State:
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;
426 goto Exit;
429 if ((pNmtCommandData_p != NULL)
430 && (uiDataSize_p >
431 (EPL_C_DLL_MINSIZE_NMTCMDEXT - EPL_C_DLL_MINSIZE_NMTCMD))) {
432 Ret = kEplNmtInvalidParam;
433 goto Exit;
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.
438 // build frame
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,
448 uiDataSize_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);
456 // send NMT-Request
457 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLU)) != 0)
458 Ret = EplDlluCalAsyncSend(&FrameInfo, // pointer to frameinfo
459 kEplDllAsyncReqPrioNmt); // priority
460 #endif
461 if (Ret != kEplSuccessful) {
462 goto Exit;
465 EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p,
466 uiNodeId_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
476 goto Exit;
479 case kEplNmtCmdStopNode:
481 fSoftDeleteNode = TRUE;
482 break;
485 case kEplNmtCmdResetNode:
486 case kEplNmtCmdResetCommunication:
487 case kEplNmtCmdResetConfiguration:
488 case kEplNmtCmdSwReset:
490 break;
493 default:
494 goto Exit;
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
507 for (uiNodeId_p = 1;
508 uiNodeId_p <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
509 uiNodeId_p++) {
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
516 Ret =
517 EplDlluCalSoftDeleteNode
518 (uiNodeId_p);
524 Exit:
525 return Ret;
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
539 // State:
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);
550 //Exit:
551 return Ret;
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
565 // State:
567 //---------------------------------------------------------------------------
569 tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p,
570 tEplNmtNodeCommand NodeCommand_p)
572 tEplKernel Ret = kEplSuccessful;
573 tEplNmtMnuIntNodeEvent NodeEvent;
574 tEplObdSize ObdSize;
575 u8 bNmtState;
576 u16 wErrorCode = EPL_E_NO_ERROR;
578 if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) {
579 Ret = kEplInvalidNodeId;
580 goto Exit;
583 switch (NodeCommand_p) {
584 case kEplNmtNodeCommandBoot:
586 NodeEvent = kEplNmtMnuIntNodeEventBoot;
587 break;
590 case kEplNmtNodeCommandConfOk:
592 NodeEvent = kEplNmtMnuIntNodeEventConfigured;
593 break;
596 case kEplNmtNodeCommandConfErr:
598 NodeEvent = kEplNmtMnuIntNodeEventError;
599 wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY;
600 break;
603 case kEplNmtNodeCommandConfReset:
605 NodeEvent = kEplNmtMnuIntNodeEventExecReset;
606 break;
609 default:
610 { // invalid node command
611 goto Exit;
615 // fetch current NMT state
616 ObdSize = 1;
617 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize);
618 if (Ret != kEplSuccessful) {
619 goto Exit;
622 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p,
623 (tEplNmtState) (bNmtState |
624 EPL_NMT_TYPE_CS),
625 wErrorCode, NodeEvent);
627 Exit:
628 return Ret;
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
642 // State:
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:
654 break;
656 // first init of the hardware
657 case kEplNmtGsInitialising:
658 break;
660 // init of the manufacturer-specific profile area and the
661 // standardised device profile area
662 case kEplNmtGsResetApplication:
664 break;
667 // init of the communication profile area
668 case kEplNmtGsResetCommunication:
670 break;
673 // build the configuration with infos from OD
674 case kEplNmtGsResetConfiguration:
676 u32 dwTimeout;
677 tEplObdSize ObdSize;
679 // read object 0x1F80 NMT_StartUp_U32
680 ObdSize = 4;
681 Ret =
682 EplObduReadEntry(0x1F80, 0,
683 &EplNmtMnuInstance_g.
684 m_dwNmtStartup, &ObdSize);
685 if (Ret != kEplSuccessful) {
686 break;
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) {
692 break;
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 ==
705 0L) {
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) {
713 break;
715 if (dwTimeout != 0L) {
716 // convert [us] to [ms]
717 dwTimeout /= 1000L;
718 if (dwTimeout == 0L) {
719 dwTimeout = 1L; // at least 1 ms
721 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp =
722 dwTimeout;
723 } else {
724 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L;
726 break;
729 //-----------------------------------------------------------
730 // CN part of the state machine
732 // node liste for EPL-Frames and check timeout
733 case kEplNmtCsNotActive:
735 break;
738 // node process only async frames
739 case kEplNmtCsPreOperational1:
741 break;
744 // node process isochronus and asynchronus frames
745 case kEplNmtCsPreOperational2:
747 break;
750 // node should be configured und application is ready
751 case kEplNmtCsReadyToOperate:
753 break;
756 // normal work state
757 case kEplNmtCsOperational:
759 break;
762 // node stopped by MN
763 // -> only process asynchronus frames
764 case kEplNmtCsStopped:
766 break;
769 // no EPL cycle
770 // -> normal ethernet communication
771 case kEplNmtCsBasicEthernet:
773 break;
776 //-----------------------------------------------------------
777 // MN part of the state machine
779 // node listens for EPL-Frames and check timeout
780 case kEplNmtMsNotActive:
782 break;
785 // node processes only async frames
786 case kEplNmtMsPreOperational1:
788 u32 dwTimeout;
789 tEplTimerArg TimerArg;
790 tEplObdSize ObdSize;
791 tEplEvent Event;
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();
800 // reset timers
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));
818 Event.m_pArg = NULL;
819 Event.m_uiSize = 0;
820 Ret = EplEventuPost(&Event);
821 if (Ret != kEplSuccessful) {
822 break;
824 // reset all nodes
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,
831 EPL_C_ADR_BROADCAST,
832 kEplNmtCmdResetNode);
834 Ret =
835 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
836 kEplNmtCmdResetNode);
837 if (Ret != kEplSuccessful) {
838 break;
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) {
848 break;
850 if (dwTimeout != 0L) {
851 dwTimeout /= 1000L;
852 if (dwTimeout == 0L) {
853 dwTimeout = 1L; // at least 1 ms
855 TimerArg.m_EventSink = kEplEventSinkNmtMnu;
856 TimerArg.m_ulArg = 0;
857 Ret =
858 EplTimeruModifyTimerMs(&EplNmtMnuInstance_g.
859 m_TimerHdlNmtState,
860 dwTimeout, TimerArg);
862 break;
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
873 break;
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();
883 break;
886 // normal work state
887 case kEplNmtMsOperational:
889 // send StartNode to CNs
890 // wait for NMT state change of CNs
891 Ret = EplNmtMnuStartNodes();
892 break;
895 // no EPL cycle
896 // -> normal ethernet communication
897 case kEplNmtMsBasicEthernet:
899 break;
902 default:
904 // TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n");
908 return Ret;
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
924 // State:
926 //---------------------------------------------------------------------------
928 tEplKernel EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p)
930 tEplKernel Ret = kEplSuccessful;
932 return Ret;
935 //---------------------------------------------------------------------------
937 // Function: EplNmtuProcessEvent
939 // Description: processes events from event queue
941 // Parameters: pEvent_p = pointer to event
943 // Returns: tEplKernel = errorcode
945 // State:
947 //---------------------------------------------------------------------------
949 EPLDLLEXPORT tEplKernel EplNmtMnuProcessEvent(tEplEvent *pEvent_p)
951 tEplKernel Ret;
953 Ret = kEplSuccessful;
955 // process event
956 switch (pEvent_p->m_EventType) {
957 // timer event
958 case kEplEventTypeTimer:
960 tEplTimerEventArg *pTimerEventArg =
961 (tEplTimerEventArg *) pEvent_p->m_pArg;
962 unsigned int uiNodeId;
964 uiNodeId =
965 (unsigned int)(pTimerEventArg->
966 m_ulArg &
967 EPL_NMTMNU_TIMERARG_NODE_MASK);
968 if (uiNodeId != 0) {
969 tEplObdSize ObdSize;
970 u8 bNmtState;
971 tEplNmtMnuNodeInfo *pNodeInfo;
973 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId);
975 ObdSize = 1;
976 Ret =
977 EplObduReadEntry(0x1F8E, uiNodeId,
978 &bNmtState, &ObdSize);
979 if (Ret != kEplSuccessful) {
980 break;
983 if ((pTimerEventArg->
984 m_ulArg & EPL_NMTMNU_TIMERARG_IDENTREQ) !=
985 0L) {
986 if ((pNodeInfo->
987 m_wFlags &
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
991 // so discard it
992 EPL_NMTMNU_DBG_POST_TRACE_VALUE
993 (kEplNmtMnuIntNodeEventTimerIdentReq,
994 uiNodeId,
995 ((pNodeInfo->
996 m_NodeState << 8)
997 | 0xFF));
999 break;
1002 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerIdentReq,
1003 uiNodeId,
1004 ((pNodeInfo->m_NodeState << 8)
1005 | 0x80
1006 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1007 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1009 Ret =
1010 EplNmtMnuProcessInternalEvent
1011 (uiNodeId,
1012 (tEplNmtState) (bNmtState |
1013 EPL_NMT_TYPE_CS),
1014 EPL_E_NO_ERROR,
1015 kEplNmtMnuIntNodeEventTimerIdentReq);
1018 else if ((pTimerEventArg->
1019 m_ulArg & EPL_NMTMNU_TIMERARG_STATREQ)
1020 != 0L) {
1021 if ((pNodeInfo->
1022 m_wFlags &
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
1026 // so discard it
1027 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1028 (kEplNmtMnuIntNodeEventTimerStatReq,
1029 uiNodeId,
1030 ((pNodeInfo->
1031 m_NodeState << 8)
1032 | 0xFF));
1034 break;
1037 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1038 uiNodeId,
1039 ((pNodeInfo->m_NodeState << 8)
1040 | 0x80
1041 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1042 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1044 Ret =
1045 EplNmtMnuProcessInternalEvent
1046 (uiNodeId,
1047 (tEplNmtState) (bNmtState |
1048 EPL_NMT_TYPE_CS),
1049 EPL_E_NO_ERROR,
1050 kEplNmtMnuIntNodeEventTimerStatReq);
1053 else if ((pTimerEventArg->
1054 m_ulArg &
1055 EPL_NMTMNU_TIMERARG_STATE_MON) !=
1056 0L) {
1057 if ((pNodeInfo->
1058 m_wFlags &
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
1062 // so discard it
1063 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1064 (kEplNmtMnuIntNodeEventTimerStateMon,
1065 uiNodeId,
1066 ((pNodeInfo->
1067 m_NodeState << 8)
1068 | 0xFF));
1070 break;
1073 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerStatReq,
1074 uiNodeId,
1075 ((pNodeInfo->m_NodeState << 8)
1076 | 0x80
1077 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
1078 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
1080 Ret =
1081 EplNmtMnuProcessInternalEvent
1082 (uiNodeId,
1083 (tEplNmtState) (bNmtState |
1084 EPL_NMT_TYPE_CS),
1085 EPL_E_NO_ERROR,
1086 kEplNmtMnuIntNodeEventTimerStateMon);
1089 else if ((pTimerEventArg->
1090 m_ulArg & EPL_NMTMNU_TIMERARG_LONGER)
1091 != 0L) {
1092 if ((pNodeInfo->
1093 m_wFlags &
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
1097 // so discard it
1098 EPL_NMTMNU_DBG_POST_TRACE_VALUE
1099 (kEplNmtMnuIntNodeEventTimerLonger,
1100 uiNodeId,
1101 ((pNodeInfo->
1102 m_NodeState << 8)
1103 | 0xFF));
1105 break;
1108 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventTimerLonger,
1109 uiNodeId,
1110 ((pNodeInfo->m_NodeState << 8)
1111 | 0x80
1112 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_LONGER) >> 6)
1113 | ((pTimerEventArg->m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_LO) >> 8)));
1115 Ret =
1116 EplNmtMnuProcessInternalEvent
1117 (uiNodeId,
1118 (tEplNmtState) (bNmtState |
1119 EPL_NMT_TYPE_CS),
1120 EPL_E_NO_ERROR,
1121 kEplNmtMnuIntNodeEventTimerLonger);
1124 } else { // global timer event
1126 break;
1129 case kEplEventTypeHeartbeat:
1131 tEplHeartbeatEvent *pHeartbeatEvent =
1132 (tEplHeartbeatEvent *) pEvent_p->m_pArg;
1134 Ret =
1135 EplNmtMnuProcessInternalEvent(pHeartbeatEvent->
1136 m_uiNodeId,
1137 pHeartbeatEvent->
1138 m_NmtState,
1139 pHeartbeatEvent->
1140 m_wErrorCode,
1141 kEplNmtMnuIntNodeEventHeartbeat);
1142 break;
1145 case kEplEventTypeNmtMnuNmtCmdSent:
1147 tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg;
1148 unsigned int uiNodeId;
1149 tEplNmtCommand NmtCommand;
1150 u8 bNmtState;
1152 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
1153 NmtCommand =
1154 (tEplNmtCommand) AmiGetByteFromLe(&pFrame->m_Data.
1155 m_Asnd.m_Payload.
1156 m_NmtCommandService.
1157 m_le_bNmtCommandId);
1159 switch (NmtCommand) {
1160 case kEplNmtCmdStartNode:
1161 bNmtState =
1162 (u8) (kEplNmtCsOperational & 0xFF);
1163 break;
1165 case kEplNmtCmdStopNode:
1166 bNmtState = (u8) (kEplNmtCsStopped & 0xFF);
1167 break;
1169 case kEplNmtCmdEnterPreOperational2:
1170 bNmtState =
1171 (u8) (kEplNmtCsPreOperational2 & 0xFF);
1172 break;
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
1177 bNmtState =
1178 (u8) (kEplNmtCsPreOperational2 & 0xFF);
1179 break;
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
1188 break;
1190 default:
1191 goto Exit;
1194 // process as internal event which update expected NMT state in OD
1195 if (uiNodeId != EPL_C_ADR_BROADCAST) {
1196 Ret = EplNmtMnuProcessInternalEvent(uiNodeId,
1197 (tEplNmtState)
1198 (bNmtState |
1199 EPL_NMT_TYPE_CS),
1201 kEplNmtMnuIntNodeEventNmtCmdSent);
1203 } else { // process internal event for all active nodes (except myself)
1205 for (uiNodeId = 1;
1206 uiNodeId <=
1207 tabentries(EplNmtMnuInstance_g.
1208 m_aNodeInfo); uiNodeId++) {
1209 if ((EPL_NMTMNU_GET_NODEINFO(uiNodeId)->
1210 m_dwNodeCfg &
1211 (EPL_NODEASSIGN_NODE_IS_CN |
1212 EPL_NODEASSIGN_NODE_EXISTS)) !=
1213 0) {
1214 Ret =
1215 EplNmtMnuProcessInternalEvent
1216 (uiNodeId,
1217 (tEplNmtState) (bNmtState |
1218 EPL_NMT_TYPE_CS),
1220 kEplNmtMnuIntNodeEventNmtCmdSent);
1222 if (Ret != kEplSuccessful) {
1223 goto Exit;
1229 break;
1232 default:
1234 Ret = kEplNmtInvalidEvent;
1239 Exit:
1240 return Ret;
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
1254 // State:
1256 //---------------------------------------------------------------------------
1258 tEplKernel EplNmtMnuGetDiagnosticInfo(unsigned int *puiMandatorySlaveCount_p,
1259 unsigned int *puiSignalSlaveCount_p,
1260 u16 *pwFlags_p)
1262 tEplKernel Ret = kEplSuccessful;
1264 if ((puiMandatorySlaveCount_p == NULL)
1265 || (puiSignalSlaveCount_p == NULL)
1266 || (pwFlags_p == NULL)) {
1267 Ret = kEplNmtInvalidParam;
1268 goto Exit;
1271 *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount;
1272 *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount;
1273 *pwFlags_p = EplNmtMnuInstance_g.m_wFlags;
1275 Exit:
1276 return Ret;
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
1290 // State:
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)
1311 goto Exit;
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
1319 Exit:
1320 return Ret;
1324 //=========================================================================//
1325 // //
1326 // P R I V A T E F U N C T I O N S //
1327 // //
1328 //=========================================================================//
1330 //---------------------------------------------------------------------------
1332 // Function: EplNmtMnuCbNmtRequest
1334 // Description: callback funktion for NmtRequest
1336 // Parameters: pFrameInfo_p = Frame with the NmtRequest
1338 // Returns: tEplKernel = error code
1341 // State:
1343 //---------------------------------------------------------------------------
1345 static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p)
1347 tEplKernel Ret = kEplSuccessful;
1349 // $$$ perform NMTRequest
1350 return Ret;
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
1365 // State:
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;
1379 u32 dwDevType;
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)
1389 ObdSize = 4;
1390 Ret =
1391 EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize);
1392 if (Ret != kEplSuccessful) {
1393 goto Exit;
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,
1403 NmtState,
1404 wErrorCode,
1405 kEplNmtMnuIntNodeEventIdentResponse);
1408 Exit:
1409 return Ret;
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
1424 // State:
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,
1438 (tEplNmtState)
1439 (AmiGetByteFromLe
1440 (&pStatusResponse_p->
1441 m_le_bNmtStatus) |
1442 EPL_NMT_TYPE_CS),
1443 EPL_E_NO_ERROR,
1444 kEplNmtMnuIntNodeEventStatusResponse);
1447 return Ret;
1450 //---------------------------------------------------------------------------
1452 // Function: EplNmtMnuStartBootStep1
1454 // Description: starts BootStep1
1456 // Parameters: (none)
1458 // Returns: tEplKernel = error code
1460 // State:
1462 //---------------------------------------------------------------------------
1464 static tEplKernel EplNmtMnuStartBootStep1(void)
1466 tEplKernel Ret = kEplSuccessful;
1467 unsigned int uiSubIndex;
1468 unsigned int uiLocalNodeId;
1469 u32 dwNodeCfg;
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;
1477 // check 0x1F81
1478 uiLocalNodeId = EplObduGetNodeId();
1479 for (uiSubIndex = 1; uiSubIndex <= 254; uiSubIndex++) {
1480 ObdSize = 4;
1481 Ret =
1482 EplObduReadEntry(0x1F81, uiSubIndex, &dwNodeCfg, &ObdSize);
1483 if (Ret != kEplSuccessful) {
1484 goto Exit;
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
1493 dwNodeCfg |=
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 =
1501 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
1507 Ret =
1508 EplIdentuRequestIdentResponse(uiSubIndex,
1509 EplNmtMnuCbIdentResponse);
1510 if (Ret != kEplSuccessful) {
1511 goto Exit;
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);
1538 Exit:
1539 return Ret;
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
1554 // State:
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;
1572 for (uiIndex = 1;
1573 uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
1574 uiIndex++, pNodeInfo++) {
1575 if (pNodeInfo->m_NodeState ==
1576 kEplNmtMnuNodeStateConfigured) {
1577 Ret =
1578 EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo);
1579 if (Ret != kEplSuccessful) {
1580 goto Exit;
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
1598 Exit:
1599 return Ret;
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
1611 // ReadyToOp.
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
1620 // State:
1622 //---------------------------------------------------------------------------
1624 static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p,
1625 tEplNmtMnuNodeInfo * pNodeInfo_p)
1627 tEplKernel Ret = kEplSuccessful;
1628 tEplDllNodeInfo DllNodeInfo;
1629 u32 dwNodeCfg;
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;
1636 ObdSize = 4;
1637 Ret =
1638 EplObduReadEntry(0x1F92, uiNodeId_p,
1639 &DllNodeInfo.m_dwPresTimeout, &ObdSize);
1640 if (Ret != kEplSuccessful) {
1641 goto Exit;
1644 ObdSize = 2;
1645 Ret =
1646 EplObduReadEntry(0x1F8B, uiNodeId_p,
1647 &DllNodeInfo.m_wPreqPayloadLimit,
1648 &ObdSize);
1649 if (Ret != kEplSuccessful) {
1650 goto Exit;
1653 ObdSize = 2;
1654 Ret =
1655 EplObduReadEntry(0x1F8D, uiNodeId_p,
1656 &DllNodeInfo.m_wPresPayloadLimit,
1657 &ObdSize);
1658 if (Ret != kEplSuccessful) {
1659 goto Exit;
1662 pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON;
1664 Ret = EplDlluCalAddNode(&DllNodeInfo);
1665 if (Ret != kEplSuccessful) {
1666 goto Exit;
1671 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1672 uiNodeId_p,
1673 kEplNmtCmdEnableReadyToOperate);
1675 Ret =
1676 EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate);
1677 if (Ret != kEplSuccessful) {
1678 goto Exit;
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,
1684 TimerArg);
1685 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1686 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1687 Ret =
1688 EplTimeruModifyTimerMs(&pNodeInfo_p->m_TimerHdlLonger,
1689 EplNmtMnuInstance_g.
1690 m_ulTimeoutReadyToOp, TimerArg);
1693 Exit:
1694 return Ret;
1697 //---------------------------------------------------------------------------
1699 // Function: EplNmtMnuStartCheckCom
1701 // Description: starts CheckCommunication
1703 // Parameters: (none)
1705 // Returns: tEplKernel = error code
1707 // State:
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;
1725 for (uiIndex = 1;
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) {
1738 goto Exit;
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;
1753 Exit:
1754 return Ret;
1757 //---------------------------------------------------------------------------
1759 // Function: EplNmtMnuNodeCheckCom
1761 // Description: checks communication of the specified node.
1762 // That means wait some time and if no error occured everything
1763 // is OK.
1765 // Parameters: uiNodeId_p = node ID
1766 // pNodeInfo_p = pointer to internal node info structure
1768 // Returns: tEplKernel = error code
1770 // State:
1772 //---------------------------------------------------------------------------
1774 static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p,
1775 tEplNmtMnuNodeInfo * pNodeInfo_p)
1777 tEplKernel Ret = kEplSuccessful;
1778 u32 dwNodeCfg;
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,
1790 TimerArg);
1791 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
1792 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_LONGER | uiNodeId_p;
1793 Ret =
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) {
1800 Ret = kEplReject;
1802 } else { // timer was not started
1803 // assume everything is OK
1804 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked;
1807 //Exit:
1808 return Ret;
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
1821 // State:
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;
1839 for (uiIndex = 1;
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)
1846 == 0) {
1847 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
1848 uiIndex,
1849 kEplNmtCmdStartNode);
1851 Ret =
1852 EplNmtMnuSendNmtCommand(uiIndex,
1853 kEplNmtCmdStartNode);
1854 if (Ret != kEplSuccessful) {
1855 goto Exit;
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);
1880 Ret =
1881 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST,
1882 kEplNmtCmdStartNode);
1883 if (Ret != kEplSuccessful) {
1884 goto Exit;
1889 Exit:
1890 return Ret;
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
1906 // State:
1908 //---------------------------------------------------------------------------
1910 static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p,
1911 tEplNmtState NodeNmtState_p,
1912 u16 wErrorCode_p,
1913 tEplNmtMnuIntNodeEvent
1914 NodeEvent_p)
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
1924 goto Exit;
1927 switch (NodeEvent_p) {
1928 case kEplNmtMnuIntNodeEventIdentResponse:
1930 u8 bNmtState;
1932 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1933 uiNodeId_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)
1948 ((pNodeInfo->
1949 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
1950 0)) {
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);
1958 Ret =
1959 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
1962 // check NMT state of CN
1963 Ret =
1964 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
1965 NodeNmtState_p, wErrorCode_p,
1966 NmtState);
1967 if (Ret != kEplSuccessful) {
1968 if (Ret == kEplReject) {
1969 Ret = kEplSuccessful;
1971 break;
1973 // request StatusResponse immediately,
1974 // because we want a fast boot-up of CNs
1975 Ret =
1976 EplStatusuRequestStatusResponse(uiNodeId_p,
1977 EplNmtMnuCbStatusResponse);
1978 if (Ret != kEplSuccessful) {
1979 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
1980 uiNodeId_p,
1981 Ret);
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;
1988 } else {
1989 break;
1993 if (pNodeInfo->m_NodeState !=
1994 kEplNmtMnuNodeStateResetConf) {
1995 // inform application
1996 Ret =
1997 EplNmtMnuInstance_g.
1998 m_pfnCbNodeEvent(uiNodeId_p,
1999 kEplNmtNodeEventFound,
2000 NodeNmtState_p,
2001 EPL_E_NO_ERROR,
2002 (pNodeInfo->
2003 m_dwNodeCfg &
2004 EPL_NODEASSIGN_MANDATORY_CN)
2005 != 0);
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)
2010 | Ret));
2012 Ret = kEplSuccessful;
2013 break;
2014 } else if (Ret != kEplSuccessful) {
2015 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2016 (NodeEvent_p, uiNodeId_p,
2017 ((pNodeInfo->m_NodeState << 8)
2018 | Ret));
2020 break;
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
2037 Ret =
2038 EplNmtMnuInstance_g.
2039 m_pfnCbNodeEvent(uiNodeId_p,
2040 kEplNmtNodeEventCheckConf,
2041 NodeNmtState_p,
2042 EPL_E_NO_ERROR,
2043 (pNodeInfo->
2044 m_dwNodeCfg &
2045 EPL_NODEASSIGN_MANDATORY_CN)
2046 != 0);
2047 if (Ret == kEplReject) { // interrupt boot process on user request
2048 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2049 (kEplNmtMnuIntNodeEventBoot,
2050 uiNodeId_p,
2051 ((pNodeInfo->m_NodeState << 8)
2052 | Ret));
2054 Ret = kEplSuccessful;
2055 break;
2056 } else if (Ret != kEplSuccessful) {
2057 EPL_NMTMNU_DBG_POST_TRACE_VALUE
2058 (kEplNmtMnuIntNodeEventBoot,
2059 uiNodeId_p,
2060 ((pNodeInfo->m_NodeState << 8)
2061 | Ret));
2063 break;
2065 } else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) { // wrong CN state
2066 // ignore event
2067 break;
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
2079 // ignore event
2080 break;
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--;
2090 } else {
2091 // put optional node to next step (BootStep2)
2092 Ret =
2093 EplNmtMnuNodeBootStep2(uiNodeId_p,
2094 pNodeInfo);
2096 break;
2099 case kEplNmtMnuIntNodeEventNoIdentResponse:
2101 if ((NmtState == kEplNmtMsPreOperational1)
2103 ((pNodeInfo->
2104 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2105 0)) {
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,
2128 uiNodeId_p,
2129 ((pNodeInfo->m_NodeState << 8)
2130 | 0x80
2131 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2132 | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2134 Ret =
2135 EplTimeruModifyTimerMs(&pNodeInfo->
2136 m_TimerHdlStatReq,
2137 EplNmtMnuInstance_g.
2138 m_ulStatusRequestDelay,
2139 TimerArg);
2140 } else { // trigger IdentRequest immediately
2141 Ret =
2142 EplIdentuRequestIdentResponse(uiNodeId_p,
2143 EplNmtMnuCbIdentResponse);
2145 break;
2148 case kEplNmtMnuIntNodeEventStatusResponse:
2150 if ((NmtState >= kEplNmtMsPreOperational2)
2152 ((pNodeInfo->
2153 m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) !=
2154 0)) {
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
2161 Ret =
2162 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2163 NodeNmtState_p, wErrorCode_p,
2164 NmtState);
2165 if (Ret != kEplSuccessful) {
2166 if (Ret == kEplReject) {
2167 Ret = kEplSuccessful;
2169 break;
2172 if (NmtState == kEplNmtMsPreOperational1) {
2173 // request next StatusResponse immediately
2174 Ret =
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,
2185 uiNodeId_p,
2186 TimerArg);
2187 // TimerArg.m_EventSink = kEplEventSinkNmtMnu;
2188 // TimerArg.m_ulArg = EPL_NMTMNU_TIMERARG_STATREQ | uiNodeId_p;
2190 EPL_NMTMNU_DBG_POST_TRACE_VALUE(kEplNmtMnuIntNodeEventStatusResponse,
2191 uiNodeId_p,
2192 ((pNodeInfo->m_NodeState << 8)
2193 | 0x80
2194 | ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_COUNT_STATREQ) >> 6)
2195 | ((TimerArg.m_ulArg & EPL_NMTMNU_TIMERARG_COUNT_SR) >> 8)));
2197 Ret =
2198 EplTimeruModifyTimerMs(&pNodeInfo->
2199 m_TimerHdlStatReq,
2200 EplNmtMnuInstance_g.
2201 m_ulStatusRequestDelay,
2202 TimerArg);
2205 break;
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
2221 Ret =
2222 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2223 NodeNmtState_p, wErrorCode_p,
2224 NmtState);
2225 if (Ret != kEplSuccessful) {
2226 if (Ret == kEplReject) {
2227 Ret = kEplSuccessful;
2229 break;
2232 break;
2235 case kEplNmtMnuIntNodeEventError:
2236 { // currently only issued on kEplNmtNodeCommandConfErr
2238 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
2239 // ignore event
2240 break;
2242 // check NMT state of CN
2243 Ret =
2244 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2245 kEplNmtCsNotActive,
2246 wErrorCode_p, NmtState);
2247 if (Ret != kEplSuccessful) {
2248 if (Ret == kEplReject) {
2249 Ret = kEplSuccessful;
2251 break;
2254 break;
2257 case kEplNmtMnuIntNodeEventExecReset:
2259 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state
2260 // ignore event
2261 break;
2264 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf;
2266 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2267 uiNodeId_p,
2268 (((NodeNmtState_p &
2269 0xFF) << 8)
2271 kEplNmtCmdResetConfiguration));
2273 // send NMT reset configuration to CN for activation of configuration
2274 Ret =
2275 EplNmtMnuSendNmtCommand(uiNodeId_p,
2276 kEplNmtCmdResetConfiguration);
2278 break;
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
2293 Ret =
2294 EplNmtMnuCheckNmtState(uiNodeId_p, pNodeInfo,
2295 NodeNmtState_p, wErrorCode_p,
2296 NmtState);
2297 if (Ret != kEplSuccessful) {
2298 if (Ret == kEplReject) {
2299 Ret = kEplSuccessful;
2301 break;
2304 break;
2307 case kEplNmtMnuIntNodeEventTimerIdentReq:
2309 EPL_DBGLVL_NMTMN_TRACE1
2310 ("TimerStatReq->IdentReq(%02X)\n", uiNodeId_p);
2311 // trigger IdentRequest again
2312 Ret =
2313 EplIdentuRequestIdentResponse(uiNodeId_p,
2314 EplNmtMnuCbIdentResponse);
2315 if (Ret != kEplSuccessful) {
2316 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2317 uiNodeId_p,
2318 (((NodeNmtState_p & 0xFF) << 8)
2319 | Ret));
2320 if (Ret == kEplInvalidOperation) { // this can happen because of a bug in EplTimeruLinuxKernel.c
2321 // so ignore this error.
2322 Ret = kEplSuccessful;
2326 break;
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",
2342 uiNodeId_p);
2343 // request next StatusResponse
2344 Ret =
2345 EplStatusuRequestStatusResponse(uiNodeId_p,
2346 EplNmtMnuCbStatusResponse);
2347 if (Ret != kEplSuccessful) {
2348 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p,
2349 uiNodeId_p,
2350 (((NodeNmtState_p & 0xFF) << 8)
2351 | Ret));
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;
2360 break;
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
2370 Ret =
2371 EplNmtMnuCheckNmtState(uiNodeId_p,
2372 pNodeInfo,
2373 kEplNmtCsNotActive,
2374 EPL_E_NMT_BPO2,
2375 NmtState);
2376 if (Ret != kEplSuccessful) {
2377 if (Ret == kEplReject) {
2378 Ret = kEplSuccessful;
2380 break;
2383 break;
2386 case kEplNmtMnuNodeStateReadyToOp:
2387 { // CheckCom finished successfully
2389 pNodeInfo->m_NodeState =
2390 kEplNmtMnuNodeStateComChecked;
2392 if ((pNodeInfo->
2393 m_wFlags &
2394 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED)
2395 != 0) {
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;
2403 if ((pNodeInfo->
2404 m_dwNodeCfg &
2405 EPL_NODEASSIGN_MANDATORY_CN) !=
2406 0) {
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)
2415 << 8)
2416 | kEplNmtCmdStartNode));
2418 // start optional CN
2419 Ret =
2420 EplNmtMnuSendNmtCommand
2421 (uiNodeId_p,
2422 kEplNmtCmdStartNode);
2424 break;
2427 default:
2429 break;
2432 break;
2435 case kEplNmtMnuIntNodeEventNmtCmdSent:
2437 u8 bNmtState;
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
2444 Ret =
2445 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState,
2447 if (Ret != kEplSuccessful) {
2448 goto Exit;
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;
2465 Ret =
2466 EplTimeruModifyTimerMs(&pNodeInfo->
2467 m_TimerHdlStatReq,
2468 EplNmtMnuInstance_g.
2469 m_ulStatusRequestDelay,
2470 TimerArg);
2472 // finish processing, because NmtState_p is the expected and not the current state
2473 goto Exit;
2476 default:
2478 break;
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
2484 switch (NmtState) {
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
2493 Ret =
2494 EplNmtMnuInstance_g.
2495 m_pfnCbBootEvent
2496 (kEplNmtBootEventBootStep1Finish,
2497 NmtState, EPL_E_NO_ERROR);
2498 if (Ret != kEplSuccessful) {
2499 if (Ret == kEplReject) {
2500 // wait for application
2501 Ret = kEplSuccessful;
2503 break;
2505 // enter PreOp2
2506 Ret =
2507 EplNmtuNmtEvent
2508 (kEplNmtEventAllMandatoryCNIdent);
2510 break;
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
2521 Ret =
2522 EplNmtMnuInstance_g.
2523 m_pfnCbBootEvent
2524 (kEplNmtBootEventBootStep2Finish,
2525 NmtState, EPL_E_NO_ERROR);
2526 if (Ret != kEplSuccessful) {
2527 if (Ret == kEplReject) {
2528 // wait for application
2529 Ret = kEplSuccessful;
2531 break;
2533 // enter ReadyToOp
2534 Ret =
2535 EplNmtuNmtEvent
2536 (kEplNmtEventEnterReadyToOperate);
2538 break;
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
2549 Ret =
2550 EplNmtMnuInstance_g.
2551 m_pfnCbBootEvent
2552 (kEplNmtBootEventCheckComFinish,
2553 NmtState, EPL_E_NO_ERROR);
2554 if (Ret != kEplSuccessful) {
2555 if (Ret == kEplReject) {
2556 // wait for application
2557 Ret = kEplSuccessful;
2559 break;
2561 // enter Operational
2562 Ret =
2563 EplNmtuNmtEvent
2564 (kEplNmtEventEnterMsOperational);
2566 break;
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
2577 Ret =
2578 EplNmtMnuInstance_g.
2579 m_pfnCbBootEvent
2580 (kEplNmtBootEventOperational,
2581 NmtState, EPL_E_NO_ERROR);
2582 if (Ret != kEplSuccessful) {
2583 if (Ret == kEplReject) {
2584 // ignore error code
2585 Ret = kEplSuccessful;
2587 break;
2590 break;
2593 default:
2595 break;
2600 Exit:
2601 return Ret;
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
2619 // State:
2621 //---------------------------------------------------------------------------
2623 static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p,
2624 tEplNmtMnuNodeInfo * pNodeInfo_p,
2625 tEplNmtState NodeNmtState_p,
2626 u16 wErrorCode_p,
2627 tEplNmtState LocalNmtState_p)
2629 tEplKernel Ret = kEplSuccessful;
2630 tEplObdSize ObdSize;
2631 u8 bNmtState;
2632 u8 bNmtStatePrev;
2633 tEplNmtState ExpNmtState;
2635 ObdSize = 1;
2636 // read object 0x1F8F NMT_MNNodeExpState_AU8
2637 Ret = EplObduReadEntry(0x1F8F, uiNodeId_p, &bNmtState, &ObdSize);
2638 if (Ret != kEplSuccessful) {
2639 goto Exit;
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
2647 Ret = kEplReject;
2648 goto Exit;
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) {
2654 goto Exit;
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) {
2661 goto Exit;
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) {
2670 goto Exit;
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)
2682 Ret =
2683 EplNmtMnuSendNmtCommand(uiNodeId_p,
2684 kEplNmtCmdStartNode);
2685 if (Ret != kEplSuccessful) {
2686 goto Exit;
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)
2702 u16 wbeErrorCode;
2704 if ((pNodeInfo_p->
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
2714 goto Exit;
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
2723 goto Exit;
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,
2734 NodeNmtState_p,
2735 wErrorCode_p,
2736 (pNodeInfo_p->
2737 m_dwNodeCfg &
2738 EPL_NODEASSIGN_MANDATORY_CN)
2739 != 0);
2740 if (Ret != kEplSuccessful) {
2741 goto Exit;
2744 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0,
2745 uiNodeId_p,
2746 (((NodeNmtState_p & 0xFF) << 8)
2747 | kEplNmtCmdResetNode));
2749 // reset CN
2750 // store error code in NMT command data for diagnostic purpose
2751 AmiSetWordToLe(&wbeErrorCode, wErrorCode_p);
2752 Ret =
2753 EplNmtMnuSendNmtCommandEx(uiNodeId_p, kEplNmtCmdResetNode,
2754 &wbeErrorCode,
2755 sizeof(wbeErrorCode));
2756 if (Ret == kEplSuccessful) {
2757 Ret = kEplReject;
2760 goto Exit;
2762 // check if NMT_MNNodeCurrState_AU8 has to be changed
2763 ObdSize = 1;
2764 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtStatePrev, &ObdSize);
2765 if (Ret != kEplSuccessful) {
2766 goto Exit;
2768 if (bNmtState != bNmtStatePrev) {
2769 // update object 0x1F8E NMT_MNNodeCurrState_AU8
2770 Ret = EplObduWriteEntry(0x1F8E, uiNodeId_p, &bNmtState, 1);
2771 if (Ret != kEplSuccessful) {
2772 goto Exit;
2774 Ret = EplNmtMnuInstance_g.m_pfnCbNodeEvent(uiNodeId_p,
2775 kEplNmtNodeEventNmtState,
2776 NodeNmtState_p,
2777 wErrorCode_p,
2778 (pNodeInfo_p->
2779 m_dwNodeCfg &
2780 EPL_NODEASSIGN_MANDATORY_CN)
2781 != 0);
2782 if (Ret != kEplSuccessful) {
2783 goto Exit;
2787 Exit:
2788 return Ret;
2791 //---------------------------------------------------------------------------
2793 // Function: EplNmtMnuReset
2795 // Description: reset internal structures, e.g. timers
2797 // Parameters: void
2799 // Returns: tEplKernel = error code
2801 // State:
2803 //---------------------------------------------------------------------------
2805 static tEplKernel EplNmtMnuReset(void)
2807 tEplKernel Ret;
2808 int iIndex;
2810 Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState);
2812 for (iIndex = 1; iIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo);
2813 iIndex++) {
2814 // delete timer handles
2815 Ret =
2816 EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2817 m_TimerHdlStatReq);
2818 Ret =
2819 EplTimeruDeleteTimer(&EPL_NMTMNU_GET_NODEINFO(iIndex)->
2820 m_TimerHdlLonger);
2823 return Ret;
2826 #endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
2828 // EOF