Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.31 2828 lines 86 kB view raw
1/**************************************************************************** 2 3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29 4 www.systec-electronic.com 5 6 Project: openPOWERLINK 7 8 Description: source file for NMT-MN-Module 9 10 License: 11 12 Redistribution and use in source and binary forms, with or without 13 modification, are permitted provided that the following conditions 14 are met: 15 16 1. Redistributions of source code must retain the above copyright 17 notice, this list of conditions and the following disclaimer. 18 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. 22 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. 27 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. 40 41 Severability Clause: 42 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. 49 50 ------------------------------------------------------------------------- 51 52 $RCSfile: EplNmtMnu.c,v $ 53 54 $Author: D.Krueger $ 55 56 $Revision: 1.18 $ $Date: 2008/11/19 09:52:24 $ 57 58 $State: Exp $ 59 60 Build Environment: 61 GCC V3.4 62 63 ------------------------------------------------------------------------- 64 65 Revision History: 66 67 2006/06/09 k.t.: start of the implementation 68 69****************************************************************************/ 70 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" 78 79#if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) 80 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 84 85//=========================================================================// 86// // 87// P R I V A T E D E F I N I T I O N S // 88// // 89//=========================================================================// 90 91//--------------------------------------------------------------------------- 92// const defines 93//--------------------------------------------------------------------------- 94 95// TracePoint support for realtime-debugging 96#ifdef _DBG_TRACE_POINTS_ 97void TgtDbgSignalTracePoint(u8 bTracePointNumber_p); 98void 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) 108 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. 122 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. 132 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; 141 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; 150 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; 159 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; 168 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 172 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]) 176 177//--------------------------------------------------------------------------- 178// local types 179//--------------------------------------------------------------------------- 180 181typedef 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, 196 197} tEplNmtMnuIntNodeEvent; 198 199typedef 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 207 208} tEplNmtMnuNodeState; 209 210typedef 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 216 217} tEplNmtMnuNodeInfo; 218 219typedef 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; 231 232} tEplNmtMnuInstance; 233 234//--------------------------------------------------------------------------- 235// local vars 236//--------------------------------------------------------------------------- 237 238static tEplNmtMnuInstance EplNmtMnuInstance_g; 239 240//--------------------------------------------------------------------------- 241// local function prototypes 242//--------------------------------------------------------------------------- 243 244static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p); 245 246static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, 247 tEplIdentResponse *pIdentResponse_p); 248 249static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p, 250 tEplStatusResponse *pStatusResponse_p); 251 252static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p, 253 tEplNmtMnuNodeInfo * pNodeInfo_p, 254 tEplNmtState NodeNmtState_p, 255 u16 wErrorCode_p, 256 tEplNmtState LocalNmtState_p); 257 258static tEplKernel EplNmtMnuStartBootStep1(void); 259 260static tEplKernel EplNmtMnuStartBootStep2(void); 261 262static tEplKernel EplNmtMnuStartCheckCom(void); 263 264static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p, 265 tEplNmtMnuNodeInfo * pNodeInfo_p); 266 267static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p, 268 tEplNmtMnuNodeInfo * pNodeInfo_p); 269 270static tEplKernel EplNmtMnuStartNodes(void); 271 272static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, 273 tEplNmtState NodeNmtState_p, 274 u16 wErrorCode_p, 275 tEplNmtMnuIntNodeEvent 276 NodeEvent_p); 277 278static tEplKernel EplNmtMnuReset(void); 279 280//=========================================================================// 281// // 282// P U B L I C F U N C T I O N S // 283// // 284//=========================================================================// 285 286//--------------------------------------------------------------------------- 287// 288// Function: EplNmtMnuInit 289// 290// Description: init first instance of the module 291// 292// 293// 294// Parameters: 295// 296// 297// Returns: tEplKernel = errorcode 298// 299// 300// State: 301// 302//--------------------------------------------------------------------------- 303 304tEplKernel EplNmtMnuInit(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, 305 tEplNmtMnuCbBootEvent pfnCbBootEvent_p) 306{ 307 tEplKernel Ret; 308 309 Ret = EplNmtMnuAddInstance(pfnCbNodeEvent_p, pfnCbBootEvent_p); 310 311 return Ret; 312} 313 314//--------------------------------------------------------------------------- 315// 316// Function: EplNmtMnuAddInstance 317// 318// Description: init other instances of the module 319// 320// 321// 322// Parameters: 323// 324// 325// Returns: tEplKernel = errorcode 326// 327// 328// State: 329// 330//--------------------------------------------------------------------------- 331 332tEplKernel EplNmtMnuAddInstance(tEplNmtMnuCbNodeEvent pfnCbNodeEvent_p, 333 tEplNmtMnuCbBootEvent pfnCbBootEvent_p) 334{ 335 tEplKernel Ret; 336 337 Ret = kEplSuccessful; 338 339 // reset instance structure 340 EPL_MEMSET(&EplNmtMnuInstance_g, 0, sizeof(EplNmtMnuInstance_g)); 341 342 if ((pfnCbNodeEvent_p == NULL) || (pfnCbBootEvent_p == NULL)) { 343 Ret = kEplNmtInvalidParam; 344 goto Exit; 345 } 346 EplNmtMnuInstance_g.m_pfnCbNodeEvent = pfnCbNodeEvent_p; 347 EplNmtMnuInstance_g.m_pfnCbBootEvent = pfnCbBootEvent_p; 348 349 // initialize StatusRequest delay 350 EplNmtMnuInstance_g.m_ulStatusRequestDelay = 5000L; 351 352 // register NmtMnResponse callback function 353 Ret = 354 EplDlluCalRegAsndService(kEplDllAsndNmtRequest, 355 EplNmtMnuCbNmtRequest, 356 kEplDllAsndFilterLocal); 357 358 Exit: 359 return Ret; 360 361} 362 363//--------------------------------------------------------------------------- 364// 365// Function: EplNmtMnuDelInstance 366// 367// Description: delete instance 368// 369// 370// 371// Parameters: 372// 373// 374// Returns: tEplKernel = errorcode 375// 376// 377// State: 378// 379//--------------------------------------------------------------------------- 380 381tEplKernel EplNmtMnuDelInstance(void) 382{ 383 tEplKernel Ret; 384 385 Ret = kEplSuccessful; 386 387 // deregister NmtMnResponse callback function 388 Ret = 389 EplDlluCalRegAsndService(kEplDllAsndNmtRequest, NULL, 390 kEplDllAsndFilterNone); 391 392 Ret = EplNmtMnuReset(); 393 394 return Ret; 395 396} 397 398//--------------------------------------------------------------------------- 399// 400// Function: EplNmtMnuSendNmtCommandEx 401// 402// Description: sends the specified NMT command to the specified node. 403// 404// Parameters: uiNodeId_p = node ID to which the NMT command will be sent 405// NmtCommand_p = NMT command 406// 407// Returns: tEplKernel = error code 408// 409// State: 410// 411//--------------------------------------------------------------------------- 412 413tEplKernel EplNmtMnuSendNmtCommandEx(unsigned int uiNodeId_p, 414 tEplNmtCommand NmtCommand_p, 415 void *pNmtCommandData_p, 416 unsigned int uiDataSize_p) 417{ 418 tEplKernel Ret = kEplSuccessful; 419 tEplFrameInfo FrameInfo; 420 u8 abBuffer[EPL_C_DLL_MINSIZE_NMTCMDEXT]; 421 tEplFrame *pFrame = (tEplFrame *) abBuffer; 422 BOOL fSoftDeleteNode = FALSE; 423 424 if ((uiNodeId_p == 0) || (uiNodeId_p > EPL_C_ADR_BROADCAST)) { // invalid node ID specified 425 Ret = kEplInvalidNodeId; 426 goto Exit; 427 } 428 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; 434 } 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. 437 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); 449 } 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); 455 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; 463 } 464 465 EPL_DBGLVL_NMTMN_TRACE2("NMTCmd(%02X->%02X)\n", NmtCommand_p, 466 uiNodeId_p); 467 468 switch (NmtCommand_p) { 469 case kEplNmtCmdStartNode: 470 case kEplNmtCmdEnterPreOperational2: 471 case kEplNmtCmdEnableReadyToOperate: 472 { 473 // nothing left to do, 474 // because any further processing is done 475 // when the NMT command is actually sent 476 goto Exit; 477 } 478 479 case kEplNmtCmdStopNode: 480 { 481 fSoftDeleteNode = TRUE; 482 break; 483 } 484 485 case kEplNmtCmdResetNode: 486 case kEplNmtCmdResetCommunication: 487 case kEplNmtCmdResetConfiguration: 488 case kEplNmtCmdSwReset: 489 { 490 break; 491 } 492 493 default: 494 goto Exit; 495 } 496 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); 505 } 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); 519 } 520 } 521 } 522 } 523 524 Exit: 525 return Ret; 526} 527 528//--------------------------------------------------------------------------- 529// 530// Function: EplNmtMnuSendNmtCommand 531// 532// Description: sends the specified NMT command to the specified node. 533// 534// Parameters: uiNodeId_p = node ID to which the NMT command will be sent 535// NmtCommand_p = NMT command 536// 537// Returns: tEplKernel = error code 538// 539// State: 540// 541//--------------------------------------------------------------------------- 542 543tEplKernel EplNmtMnuSendNmtCommand(unsigned int uiNodeId_p, 544 tEplNmtCommand NmtCommand_p) 545{ 546 tEplKernel Ret = kEplSuccessful; 547 548 Ret = EplNmtMnuSendNmtCommandEx(uiNodeId_p, NmtCommand_p, NULL, 0); 549 550//Exit: 551 return Ret; 552} 553 554//--------------------------------------------------------------------------- 555// 556// Function: EplNmtMnuTriggerStateChange 557// 558// Description: triggers the specified node command for the specified node. 559// 560// Parameters: uiNodeId_p = node ID for which the node command will be executed 561// NodeCommand_p = node command 562// 563// Returns: tEplKernel = error code 564// 565// State: 566// 567//--------------------------------------------------------------------------- 568 569tEplKernel EplNmtMnuTriggerStateChange(unsigned int uiNodeId_p, 570 tEplNmtNodeCommand NodeCommand_p) 571{ 572 tEplKernel Ret = kEplSuccessful; 573 tEplNmtMnuIntNodeEvent NodeEvent; 574 tEplObdSize ObdSize; 575 u8 bNmtState; 576 u16 wErrorCode = EPL_E_NO_ERROR; 577 578 if ((uiNodeId_p == 0) || (uiNodeId_p >= EPL_C_ADR_BROADCAST)) { 579 Ret = kEplInvalidNodeId; 580 goto Exit; 581 } 582 583 switch (NodeCommand_p) { 584 case kEplNmtNodeCommandBoot: 585 { 586 NodeEvent = kEplNmtMnuIntNodeEventBoot; 587 break; 588 } 589 590 case kEplNmtNodeCommandConfOk: 591 { 592 NodeEvent = kEplNmtMnuIntNodeEventConfigured; 593 break; 594 } 595 596 case kEplNmtNodeCommandConfErr: 597 { 598 NodeEvent = kEplNmtMnuIntNodeEventError; 599 wErrorCode = EPL_E_NMT_BPO1_CF_VERIFY; 600 break; 601 } 602 603 case kEplNmtNodeCommandConfReset: 604 { 605 NodeEvent = kEplNmtMnuIntNodeEventExecReset; 606 break; 607 } 608 609 default: 610 { // invalid node command 611 goto Exit; 612 } 613 } 614 615 // fetch current NMT state 616 ObdSize = 1; 617 Ret = EplObduReadEntry(0x1F8E, uiNodeId_p, &bNmtState, &ObdSize); 618 if (Ret != kEplSuccessful) { 619 goto Exit; 620 } 621 622 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, 623 (tEplNmtState) (bNmtState | 624 EPL_NMT_TYPE_CS), 625 wErrorCode, NodeEvent); 626 627 Exit: 628 return Ret; 629} 630 631//--------------------------------------------------------------------------- 632// 633// Function: EplNmtMnuCbNmtStateChange 634// 635// Description: callback function for NMT state changes 636// 637// Parameters: NmtStateChange_p = NMT state change event 638// 639// Returns: tEplKernel = error code 640// 641// 642// State: 643// 644//--------------------------------------------------------------------------- 645 646tEplKernel EplNmtMnuCbNmtStateChange(tEplEventNmtStateChange NmtStateChange_p) 647{ 648 tEplKernel Ret = kEplSuccessful; 649 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; 655 656 // first init of the hardware 657 case kEplNmtGsInitialising: 658 break; 659 660 // init of the manufacturer-specific profile area and the 661 // standardised device profile area 662 case kEplNmtGsResetApplication: 663 { 664 break; 665 } 666 667 // init of the communication profile area 668 case kEplNmtGsResetCommunication: 669 { 670 break; 671 } 672*/ 673 // build the configuration with infos from OD 674 case kEplNmtGsResetConfiguration: 675 { 676 u32 dwTimeout; 677 tEplObdSize ObdSize; 678 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; 687 } 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; 693 } 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 700 } 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 707 } 708 } 709 // fetch ReadyToOp Timeout from OD 710 ObdSize = sizeof(dwTimeout); 711 Ret = EplObduReadEntry(0x1F89, 5, &dwTimeout, &ObdSize); 712 if (Ret != kEplSuccessful) { 713 break; 714 } 715 if (dwTimeout != 0L) { 716 // convert [us] to [ms] 717 dwTimeout /= 1000L; 718 if (dwTimeout == 0L) { 719 dwTimeout = 1L; // at least 1 ms 720 } 721 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 722 dwTimeout; 723 } else { 724 EplNmtMnuInstance_g.m_ulTimeoutReadyToOp = 0L; 725 } 726 break; 727 } 728/* 729 //----------------------------------------------------------- 730 // CN part of the state machine 731 732 // node liste for EPL-Frames and check timeout 733 case kEplNmtCsNotActive: 734 { 735 break; 736 } 737 738 // node process only async frames 739 case kEplNmtCsPreOperational1: 740 { 741 break; 742 } 743 744 // node process isochronus and asynchronus frames 745 case kEplNmtCsPreOperational2: 746 { 747 break; 748 } 749 750 // node should be configured und application is ready 751 case kEplNmtCsReadyToOperate: 752 { 753 break; 754 } 755 756 // normal work state 757 case kEplNmtCsOperational: 758 { 759 break; 760 } 761 762 // node stopped by MN 763 // -> only process asynchronus frames 764 case kEplNmtCsStopped: 765 { 766 break; 767 } 768 769 // no EPL cycle 770 // -> normal ethernet communication 771 case kEplNmtCsBasicEthernet: 772 { 773 break; 774 } 775*/ 776 //----------------------------------------------------------- 777 // MN part of the state machine 778 779 // node listens for EPL-Frames and check timeout 780 case kEplNmtMsNotActive: 781 { 782 break; 783 } 784 785 // node processes only async frames 786 case kEplNmtMsPreOperational1: 787 { 788 u32 dwTimeout; 789 tEplTimerArg TimerArg; 790 tEplObdSize ObdSize; 791 tEplEvent Event; 792 793 // clear global flags, e.g. reenable boot process 794 EplNmtMnuInstance_g.m_wFlags = 0; 795 796 // reset IdentResponses and running IdentRequests and StatusRequests 797 Ret = EplIdentuReset(); 798 Ret = EplStatusuReset(); 799 800 // reset timers 801 Ret = EplNmtMnuReset(); 802 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(). 806/* 807 EPL_MEMSET(EplNmtMnuInstance_g.m_aNodeInfo, 808 0, 809 sizeof (EplNmtMnuInstance_g.m_aNodeInfo)); 810*/ 811 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; 823 } 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); 829 830 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, 831 EPL_C_ADR_BROADCAST, 832 kEplNmtCmdResetNode); 833 834 Ret = 835 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST, 836 kEplNmtCmdResetNode); 837 if (Ret != kEplSuccessful) { 838 break; 839 } 840 } 841 // start network scan 842 Ret = EplNmtMnuStartBootStep1(); 843 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; 849 } 850 if (dwTimeout != 0L) { 851 dwTimeout /= 1000L; 852 if (dwTimeout == 0L) { 853 dwTimeout = 1L; // at least 1 ms 854 } 855 TimerArg.m_EventSink = kEplEventSinkNmtMnu; 856 TimerArg.m_ulArg = 0; 857 Ret = 858 EplTimeruModifyTimerMs(&EplNmtMnuInstance_g. 859 m_TimerHdlNmtState, 860 dwTimeout, TimerArg); 861 } 862 break; 863 } 864 865 // node processes isochronous and asynchronous frames 866 case kEplNmtMsPreOperational2: 867 { 868 // add identified CNs to isochronous phase 869 // send EnableReadyToOp to all identified CNs 870 Ret = EplNmtMnuStartBootStep2(); 871 872 // wait for NMT state change of CNs 873 break; 874 } 875 876 // node should be configured und application is ready 877 case kEplNmtMsReadyToOperate: 878 { 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; 884 } 885 886 // normal work state 887 case kEplNmtMsOperational: 888 { 889 // send StartNode to CNs 890 // wait for NMT state change of CNs 891 Ret = EplNmtMnuStartNodes(); 892 break; 893 } 894 895 // no EPL cycle 896 // -> normal ethernet communication 897 case kEplNmtMsBasicEthernet: 898 { 899 break; 900 } 901 902 default: 903 { 904// TRACE0("EplNmtMnuCbNmtStateChange(): unhandled NMT state\n"); 905 } 906 } 907 908 return Ret; 909} 910 911//--------------------------------------------------------------------------- 912// 913// Function: EplNmtMnuCbCheckEvent 914// 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. 918// 919// Parameters: NmtEvent_p = outstanding NMT event for approval 920// 921// Returns: tEplKernel = error code 922// kEplReject = reject the NMT event 923// 924// State: 925// 926//--------------------------------------------------------------------------- 927 928tEplKernel EplNmtMnuCbCheckEvent(tEplNmtEvent NmtEvent_p) 929{ 930 tEplKernel Ret = kEplSuccessful; 931 932 return Ret; 933} 934 935//--------------------------------------------------------------------------- 936// 937// Function: EplNmtuProcessEvent 938// 939// Description: processes events from event queue 940// 941// Parameters: pEvent_p = pointer to event 942// 943// Returns: tEplKernel = errorcode 944// 945// State: 946// 947//--------------------------------------------------------------------------- 948 949tEplKernel EplNmtMnuProcessEvent(tEplEvent *pEvent_p) 950{ 951 tEplKernel Ret; 952 953 Ret = kEplSuccessful; 954 955 // process event 956 switch (pEvent_p->m_EventType) { 957 // timer event 958 case kEplEventTypeTimer: 959 { 960 tEplTimerEventArg *pTimerEventArg = 961 (tEplTimerEventArg *) pEvent_p->m_pArg; 962 unsigned int uiNodeId; 963 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; 972 973 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId); 974 975 ObdSize = 1; 976 Ret = 977 EplObduReadEntry(0x1F8E, uiNodeId, 978 &bNmtState, &ObdSize); 979 if (Ret != kEplSuccessful) { 980 break; 981 } 982 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)); 998 999 break; 1000 } 1001/* 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))); 1008*/ 1009 Ret = 1010 EplNmtMnuProcessInternalEvent 1011 (uiNodeId, 1012 (tEplNmtState) (bNmtState | 1013 EPL_NMT_TYPE_CS), 1014 EPL_E_NO_ERROR, 1015 kEplNmtMnuIntNodeEventTimerIdentReq); 1016 } 1017 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)); 1033 1034 break; 1035 } 1036/* 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))); 1043*/ 1044 Ret = 1045 EplNmtMnuProcessInternalEvent 1046 (uiNodeId, 1047 (tEplNmtState) (bNmtState | 1048 EPL_NMT_TYPE_CS), 1049 EPL_E_NO_ERROR, 1050 kEplNmtMnuIntNodeEventTimerStatReq); 1051 } 1052 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)); 1069 1070 break; 1071 } 1072/* 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))); 1079*/ 1080 Ret = 1081 EplNmtMnuProcessInternalEvent 1082 (uiNodeId, 1083 (tEplNmtState) (bNmtState | 1084 EPL_NMT_TYPE_CS), 1085 EPL_E_NO_ERROR, 1086 kEplNmtMnuIntNodeEventTimerStateMon); 1087 } 1088 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)); 1104 1105 break; 1106 } 1107/* 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))); 1114*/ 1115 Ret = 1116 EplNmtMnuProcessInternalEvent 1117 (uiNodeId, 1118 (tEplNmtState) (bNmtState | 1119 EPL_NMT_TYPE_CS), 1120 EPL_E_NO_ERROR, 1121 kEplNmtMnuIntNodeEventTimerLonger); 1122 } 1123 1124 } else { // global timer event 1125 } 1126 break; 1127 } 1128 1129 case kEplEventTypeHeartbeat: 1130 { 1131 tEplHeartbeatEvent *pHeartbeatEvent = 1132 (tEplHeartbeatEvent *) pEvent_p->m_pArg; 1133 1134 Ret = 1135 EplNmtMnuProcessInternalEvent(pHeartbeatEvent-> 1136 m_uiNodeId, 1137 pHeartbeatEvent-> 1138 m_NmtState, 1139 pHeartbeatEvent-> 1140 m_wErrorCode, 1141 kEplNmtMnuIntNodeEventHeartbeat); 1142 break; 1143 } 1144 1145 case kEplEventTypeNmtMnuNmtCmdSent: 1146 { 1147 tEplFrame *pFrame = (tEplFrame *) pEvent_p->m_pArg; 1148 unsigned int uiNodeId; 1149 tEplNmtCommand NmtCommand; 1150 u8 bNmtState; 1151 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); 1158 1159 switch (NmtCommand) { 1160 case kEplNmtCmdStartNode: 1161 bNmtState = 1162 (u8) (kEplNmtCsOperational & 0xFF); 1163 break; 1164 1165 case kEplNmtCmdStopNode: 1166 bNmtState = (u8) (kEplNmtCsStopped & 0xFF); 1167 break; 1168 1169 case kEplNmtCmdEnterPreOperational2: 1170 bNmtState = 1171 (u8) (kEplNmtCsPreOperational2 & 0xFF); 1172 break; 1173 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; 1180 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; 1189 1190 default: 1191 goto Exit; 1192 } 1193 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), 1200 0, 1201 kEplNmtMnuIntNodeEventNmtCmdSent); 1202 1203 } else { // process internal event for all active nodes (except myself) 1204 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), 1219 0, 1220 kEplNmtMnuIntNodeEventNmtCmdSent); 1221 1222 if (Ret != kEplSuccessful) { 1223 goto Exit; 1224 } 1225 } 1226 } 1227 } 1228 1229 break; 1230 } 1231 1232 default: 1233 { 1234 Ret = kEplNmtInvalidEvent; 1235 } 1236 1237 } 1238 1239 Exit: 1240 return Ret; 1241} 1242 1243//--------------------------------------------------------------------------- 1244// 1245// Function: EplNmtMnuGetRunningTimerStatReq 1246// 1247// Description: returns a bit field with running StatReq timers 1248// just for debugging purposes 1249// 1250// Parameters: (none) 1251// 1252// Returns: tEplKernel = error code 1253// 1254// State: 1255// 1256//--------------------------------------------------------------------------- 1257 1258tEplKernel EplNmtMnuGetDiagnosticInfo(unsigned int *puiMandatorySlaveCount_p, 1259 unsigned int *puiSignalSlaveCount_p, 1260 u16 *pwFlags_p) 1261{ 1262 tEplKernel Ret = kEplSuccessful; 1263 1264 if ((puiMandatorySlaveCount_p == NULL) 1265 || (puiSignalSlaveCount_p == NULL) 1266 || (pwFlags_p == NULL)) { 1267 Ret = kEplNmtInvalidParam; 1268 goto Exit; 1269 } 1270 1271 *puiMandatorySlaveCount_p = EplNmtMnuInstance_g.m_uiMandatorySlaveCount; 1272 *puiSignalSlaveCount_p = EplNmtMnuInstance_g.m_uiSignalSlaveCount; 1273 *pwFlags_p = EplNmtMnuInstance_g.m_wFlags; 1274 1275 Exit: 1276 return Ret; 1277} 1278 1279//--------------------------------------------------------------------------- 1280// 1281// Function: EplNmtMnuGetRunningTimerStatReq 1282// 1283// Description: returns a bit field with running StatReq timers 1284// just for debugging purposes 1285// 1286// Parameters: (none) 1287// 1288// Returns: tEplKernel = error code 1289// 1290// State: 1291// 1292//--------------------------------------------------------------------------- 1293/* 1294u32 EplNmtMnuGetRunningTimerStatReq(void) 1295{ 1296tEplKernel Ret = kEplSuccessful; 1297unsigned int uiIndex; 1298tEplNmtMnuNodeInfo* pNodeInfo; 1299 1300 pNodeInfo = EplNmtMnuInstance_g.m_aNodeInfo; 1301 for (uiIndex = 1; uiIndex <= tabentries(EplNmtMnuInstance_g.m_aNodeInfo); uiIndex++, pNodeInfo++) 1302 { 1303 if (pNodeInfo->m_NodeState == kEplNmtMnuNodeStateConfigured) 1304 { 1305 // reset flag "scanned once" 1306 pNodeInfo->m_wFlags &= ~EPL_NMTMNU_NODE_FLAG_SCANNED; 1307 1308 Ret = EplNmtMnuNodeBootStep2(uiIndex, pNodeInfo); 1309 if (Ret != kEplSuccessful) 1310 { 1311 goto Exit; 1312 } 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 1316 } 1317 } 1318 1319Exit: 1320 return Ret; 1321} 1322*/ 1323 1324//=========================================================================// 1325// // 1326// P R I V A T E F U N C T I O N S // 1327// // 1328//=========================================================================// 1329 1330//--------------------------------------------------------------------------- 1331// 1332// Function: EplNmtMnuCbNmtRequest 1333// 1334// Description: callback funktion for NmtRequest 1335// 1336// Parameters: pFrameInfo_p = Frame with the NmtRequest 1337// 1338// Returns: tEplKernel = error code 1339// 1340// 1341// State: 1342// 1343//--------------------------------------------------------------------------- 1344 1345static tEplKernel EplNmtMnuCbNmtRequest(tEplFrameInfo *pFrameInfo_p) 1346{ 1347 tEplKernel Ret = kEplSuccessful; 1348 1349 // $$$ perform NMTRequest 1350 return Ret; 1351} 1352 1353//--------------------------------------------------------------------------- 1354// 1355// Function: EplNmtMnuCbIdentResponse 1356// 1357// Description: callback funktion for IdentResponse 1358// 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 1362// 1363// Returns: tEplKernel = error code 1364// 1365// State: 1366// 1367//--------------------------------------------------------------------------- 1368 1369static tEplKernel EplNmtMnuCbIdentResponse(unsigned int uiNodeId_p, 1370 tEplIdentResponse *pIdentResponse_p) 1371{ 1372 tEplKernel Ret = kEplSuccessful; 1373 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); 1385 1386 // check IdentResponse $$$ move to ProcessIntern, because this function may be called also if CN 1387 1388 // check DeviceType (0x1F84) 1389 ObdSize = 4; 1390 Ret = 1391 EplObduReadEntry(0x1F84, uiNodeId_p, &dwDevType, &ObdSize); 1392 if (Ret != kEplSuccessful) { 1393 goto Exit; 1394 } 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; 1399 } 1400 } 1401 1402 Ret = EplNmtMnuProcessInternalEvent(uiNodeId_p, 1403 NmtState, 1404 wErrorCode, 1405 kEplNmtMnuIntNodeEventIdentResponse); 1406 } 1407 1408 Exit: 1409 return Ret; 1410} 1411 1412//--------------------------------------------------------------------------- 1413// 1414// Function: EplNmtMnuCbStatusResponse 1415// 1416// Description: callback funktion for StatusResponse 1417// 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 1421// 1422// Returns: tEplKernel = error code 1423// 1424// State: 1425// 1426//--------------------------------------------------------------------------- 1427 1428static tEplKernel EplNmtMnuCbStatusResponse(unsigned int uiNodeId_p, 1429 tEplStatusResponse *pStatusResponse_p) 1430{ 1431 tEplKernel Ret = kEplSuccessful; 1432 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); 1445 } 1446 1447 return Ret; 1448} 1449 1450//--------------------------------------------------------------------------- 1451// 1452// Function: EplNmtMnuStartBootStep1 1453// 1454// Description: starts BootStep1 1455// 1456// Parameters: (none) 1457// 1458// Returns: tEplKernel = error code 1459// 1460// State: 1461// 1462//--------------------------------------------------------------------------- 1463 1464static tEplKernel EplNmtMnuStartBootStep1(void) 1465{ 1466 tEplKernel Ret = kEplSuccessful; 1467 unsigned int uiSubIndex; 1468 unsigned int uiLocalNodeId; 1469 u32 dwNodeCfg; 1470 tEplObdSize ObdSize; 1471 1472 // $$$ d.k.: save current time for 0x1F89/2 MNTimeoutPreOp1_U32 1473 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; 1485 } 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); 1491 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; 1498 } 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; 1504 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; 1512 } 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 1518 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 1523 } 1524 } 1525 } else { // subindex of MN 1526 if ((dwNodeCfg & (EPL_NODEASSIGN_MN_PRES | EPL_NODEASSIGN_NODE_EXISTS)) != 0) { // MN shall send PRes 1527 tEplDllNodeInfo DllNodeInfo; 1528 1529 EPL_MEMSET(&DllNodeInfo, 0, 1530 sizeof(DllNodeInfo)); 1531 DllNodeInfo.m_uiNodeId = uiLocalNodeId; 1532 1533 Ret = EplDlluCalAddNode(&DllNodeInfo); 1534 } 1535 } 1536 } 1537 1538 Exit: 1539 return Ret; 1540} 1541 1542//--------------------------------------------------------------------------- 1543// 1544// Function: EplNmtMnuStartBootStep2 1545// 1546// Description: starts BootStep2. 1547// That means add nodes to isochronous phase and send 1548// NMT EnableReadyToOp. 1549// 1550// Parameters: (none) 1551// 1552// Returns: tEplKernel = error code 1553// 1554// State: 1555// 1556//--------------------------------------------------------------------------- 1557 1558static tEplKernel EplNmtMnuStartBootStep2(void) 1559{ 1560 tEplKernel Ret = kEplSuccessful; 1561 unsigned int uiIndex; 1562 tEplNmtMnuNodeInfo *pNodeInfo; 1563 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; 1570 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; 1581 } 1582 // set flag "not scanned" 1583 pNodeInfo->m_wFlags |= 1584 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; 1585 1586 EplNmtMnuInstance_g.m_uiSignalSlaveCount++; 1587 // signal slave counter shall be decremented if StatusRequest was sent once to a CN 1588 1589 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN 1590 EplNmtMnuInstance_g. 1591 m_uiMandatorySlaveCount++; 1592 } 1593 // mandatory slave counter shall be decremented if mandatory CN is ReadyToOp 1594 } 1595 } 1596 } 1597 1598 Exit: 1599 return Ret; 1600} 1601 1602//--------------------------------------------------------------------------- 1603// 1604// Function: EplNmtMnuNodeBootStep2 1605// 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. 1614// 1615// Parameters: uiNodeId_p = node ID 1616// pNodeInfo_p = pointer to internal node info structure 1617// 1618// Returns: tEplKernel = error code 1619// 1620// State: 1621// 1622//--------------------------------------------------------------------------- 1623 1624static tEplKernel EplNmtMnuNodeBootStep2(unsigned int uiNodeId_p, 1625 tEplNmtMnuNodeInfo * pNodeInfo_p) 1626{ 1627 tEplKernel Ret = kEplSuccessful; 1628 tEplDllNodeInfo DllNodeInfo; 1629 u32 dwNodeCfg; 1630 tEplObdSize ObdSize; 1631 tEplTimerArg TimerArg; 1632 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; 1642 } 1643 1644 ObdSize = 2; 1645 Ret = 1646 EplObduReadEntry(0x1F8B, uiNodeId_p, 1647 &DllNodeInfo.m_wPreqPayloadLimit, 1648 &ObdSize); 1649 if (Ret != kEplSuccessful) { 1650 goto Exit; 1651 } 1652 1653 ObdSize = 2; 1654 Ret = 1655 EplObduReadEntry(0x1F8D, uiNodeId_p, 1656 &DllNodeInfo.m_wPresPayloadLimit, 1657 &ObdSize); 1658 if (Ret != kEplSuccessful) { 1659 goto Exit; 1660 } 1661 1662 pNodeInfo_p->m_wFlags |= EPL_NMTMNU_NODE_FLAG_ISOCHRON; 1663 1664 Ret = EplDlluCalAddNode(&DllNodeInfo); 1665 if (Ret != kEplSuccessful) { 1666 goto Exit; 1667 } 1668 1669 } 1670 1671 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, 1672 uiNodeId_p, 1673 kEplNmtCmdEnableReadyToOperate); 1674 1675 Ret = 1676 EplNmtMnuSendNmtCommand(uiNodeId_p, kEplNmtCmdEnableReadyToOperate); 1677 if (Ret != kEplSuccessful) { 1678 goto Exit; 1679 } 1680 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); 1691 } 1692 1693 Exit: 1694 return Ret; 1695} 1696 1697//--------------------------------------------------------------------------- 1698// 1699// Function: EplNmtMnuStartCheckCom 1700// 1701// Description: starts CheckCommunication 1702// 1703// Parameters: (none) 1704// 1705// Returns: tEplKernel = error code 1706// 1707// State: 1708// 1709//--------------------------------------------------------------------------- 1710 1711static tEplKernel EplNmtMnuStartCheckCom(void) 1712{ 1713 tEplKernel Ret = kEplSuccessful; 1714 unsigned int uiIndex; 1715 tEplNmtMnuNodeInfo *pNodeInfo; 1716 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; 1723 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++; 1736 } 1737 } else if (Ret != kEplSuccessful) { 1738 goto Exit; 1739 } 1740 // set flag "not scanned" 1741 pNodeInfo->m_wFlags |= 1742 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; 1743 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 1747 } 1748 } 1749 } 1750 1751 Ret = kEplSuccessful; 1752 1753 Exit: 1754 return Ret; 1755} 1756 1757//--------------------------------------------------------------------------- 1758// 1759// Function: EplNmtMnuNodeCheckCom 1760// 1761// Description: checks communication of the specified node. 1762// That means wait some time and if no error occured everything 1763// is OK. 1764// 1765// Parameters: uiNodeId_p = node ID 1766// pNodeInfo_p = pointer to internal node info structure 1767// 1768// Returns: tEplKernel = error code 1769// 1770// State: 1771// 1772//--------------------------------------------------------------------------- 1773 1774static tEplKernel EplNmtMnuNodeCheckCom(unsigned int uiNodeId_p, 1775 tEplNmtMnuNodeInfo * pNodeInfo_p) 1776{ 1777 tEplKernel Ret = kEplSuccessful; 1778 u32 dwNodeCfg; 1779 tEplTimerArg TimerArg; 1780 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 1784 1785 // check communication, 1786 // that means wait some time and if no error occured everything is OK; 1787 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); 1797 1798 // update mandatory slave counter, because timer was started 1799 if (Ret == kEplSuccessful) { 1800 Ret = kEplReject; 1801 } 1802 } else { // timer was not started 1803 // assume everything is OK 1804 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateComChecked; 1805 } 1806 1807//Exit: 1808 return Ret; 1809} 1810 1811//--------------------------------------------------------------------------- 1812// 1813// Function: EplNmtMnuStartNodes 1814// 1815// Description: really starts all nodes which are ReadyToOp and CheckCom did not fail 1816// 1817// Parameters: (none) 1818// 1819// Returns: tEplKernel = error code 1820// 1821// State: 1822// 1823//--------------------------------------------------------------------------- 1824 1825static tEplKernel EplNmtMnuStartNodes(void) 1826{ 1827 tEplKernel Ret = kEplSuccessful; 1828 unsigned int uiIndex; 1829 tEplNmtMnuNodeInfo *pNodeInfo; 1830 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; 1837 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); 1850 1851 Ret = 1852 EplNmtMnuSendNmtCommand(uiIndex, 1853 kEplNmtCmdStartNode); 1854 if (Ret != kEplSuccessful) { 1855 goto Exit; 1856 } 1857 } 1858 1859 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN 1860 EplNmtMnuInstance_g. 1861 m_uiMandatorySlaveCount++; 1862 } 1863 // set flag "not scanned" 1864 pNodeInfo->m_wFlags |= 1865 EPL_NMTMNU_NODE_FLAG_NOT_SCANNED; 1866 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 1870 } 1871 } 1872 1873 // $$$ inform application if EPL_NMTST_NO_STARTNODE is set 1874 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); 1879 1880 Ret = 1881 EplNmtMnuSendNmtCommand(EPL_C_ADR_BROADCAST, 1882 kEplNmtCmdStartNode); 1883 if (Ret != kEplSuccessful) { 1884 goto Exit; 1885 } 1886 } 1887 } 1888 1889 Exit: 1890 return Ret; 1891} 1892 1893//--------------------------------------------------------------------------- 1894// 1895// Function: EplNmtMnuProcessInternalEvent 1896// 1897// Description: processes internal node events 1898// 1899// Parameters: uiNodeId_p = node ID 1900// NodeNmtState_p = NMT state of CN 1901// NodeEvent_p = occured events 1902// 1903// Returns: tEplKernel = error code 1904// 1905// 1906// State: 1907// 1908//--------------------------------------------------------------------------- 1909 1910static tEplKernel EplNmtMnuProcessInternalEvent(unsigned int uiNodeId_p, 1911 tEplNmtState NodeNmtState_p, 1912 u16 wErrorCode_p, 1913 tEplNmtMnuIntNodeEvent 1914 NodeEvent_p) 1915{ 1916 tEplKernel Ret = kEplSuccessful; 1917 tEplNmtState NmtState; 1918 tEplNmtMnuNodeInfo *pNodeInfo; 1919 tEplTimerArg TimerArg; 1920 1921 pNodeInfo = EPL_NMTMNU_GET_NODEINFO(uiNodeId_p); 1922 NmtState = EplNmtuGetNmtState(); 1923 if (NmtState <= kEplNmtMsNotActive) { // MN is not active 1924 goto Exit; 1925 } 1926 1927 switch (NodeEvent_p) { 1928 case kEplNmtMnuIntNodeEventIdentResponse: 1929 { 1930 u8 bNmtState; 1931 1932 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, 1933 uiNodeId_p, 1934 pNodeInfo->m_NodeState); 1935 1936 if (pNodeInfo->m_NodeState != 1937 kEplNmtMnuNodeStateResetConf) { 1938 pNodeInfo->m_NodeState = 1939 kEplNmtMnuNodeStateIdentified; 1940 } 1941 // reset flags ISOCHRON and NMT_CMD_ISSUED 1942 pNodeInfo->m_wFlags &= ~(EPL_NMTMNU_NODE_FLAG_ISOCHRON 1943 | 1944 EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED); 1945 1946 if ((NmtState == kEplNmtMsPreOperational1) 1947 && 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; 1955 } 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, 1960 1); 1961 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; 1970 } 1971 break; 1972 } 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); 1982 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; 1990 } 1991 } 1992 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)); 2011 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)); 2019 2020 break; 2021 } 2022 } 2023 // continue BootStep1 2024 } 2025 2026 case kEplNmtMnuIntNodeEventBoot: 2027 { 2028 2029 // $$$ check identification (vendor ID, product code, revision no, serial no) 2030 2031 if (pNodeInfo->m_NodeState == 2032 kEplNmtMnuNodeStateIdentified) { 2033 // $$$ check software 2034 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)); 2053 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)); 2062 2063 break; 2064 } 2065 } else if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf) { // wrong CN state 2066 // ignore event 2067 break; 2068 } 2069 // $$$ d.k.: currently we assume configuration is OK 2070 2071 // continue BootStep1 2072 } 2073 2074 case kEplNmtMnuIntNodeEventConfigured: 2075 { 2076 if ((pNodeInfo->m_NodeState != 2077 kEplNmtMnuNodeStateIdentified) 2078 && (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateResetConf)) { // wrong CN state 2079 // ignore event 2080 break; 2081 } 2082 2083 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateConfigured; 2084 2085 if (NmtState == kEplNmtMsPreOperational1) { 2086 if ((pNodeInfo->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // decrement mandatory CN counter 2087 EplNmtMnuInstance_g. 2088 m_uiMandatorySlaveCount--; 2089 } 2090 } else { 2091 // put optional node to next step (BootStep2) 2092 Ret = 2093 EplNmtMnuNodeBootStep2(uiNodeId_p, 2094 pNodeInfo); 2095 } 2096 break; 2097 } 2098 2099 case kEplNmtMnuIntNodeEventNoIdentResponse: 2100 { 2101 if ((NmtState == kEplNmtMsPreOperational1) 2102 && 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; 2110 } 2111 2112 if (pNodeInfo->m_NodeState != 2113 kEplNmtMnuNodeStateResetConf) { 2114 pNodeInfo->m_NodeState = 2115 kEplNmtMnuNodeStateUnknown; 2116 } 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; 2126/* 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))); 2133*/ 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); 2144 } 2145 break; 2146 } 2147 2148 case kEplNmtMnuIntNodeEventStatusResponse: 2149 { 2150 if ((NmtState >= kEplNmtMsPreOperational2) 2151 && 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; 2159 } 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; 2168 } 2169 break; 2170 } 2171 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); 2180 } 2181 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; 2189/* 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))); 2196*/ 2197 Ret = 2198 EplTimeruModifyTimerMs(&pNodeInfo-> 2199 m_TimerHdlStatReq, 2200 EplNmtMnuInstance_g. 2201 m_ulStatusRequestDelay, 2202 TimerArg); 2203 } 2204 2205 break; 2206 } 2207 2208 case kEplNmtMnuIntNodeEventNoStatusResponse: 2209 { 2210 // function CheckNmtState sets node state to unknown if necessary 2211/* 2212 if ((NmtState >= kEplNmtMsPreOperational2) 2213 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) 2214 { 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; 2218 } 2219*/ 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; 2228 } 2229 break; 2230 } 2231 2232 break; 2233 } 2234 2235 case kEplNmtMnuIntNodeEventError: 2236 { // currently only issued on kEplNmtNodeCommandConfErr 2237 2238 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state 2239 // ignore event 2240 break; 2241 } 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; 2250 } 2251 break; 2252 } 2253 2254 break; 2255 } 2256 2257 case kEplNmtMnuIntNodeEventExecReset: 2258 { 2259 if (pNodeInfo->m_NodeState != kEplNmtMnuNodeStateIdentified) { // wrong CN state 2260 // ignore event 2261 break; 2262 } 2263 2264 pNodeInfo->m_NodeState = kEplNmtMnuNodeStateResetConf; 2265 2266 EPL_NMTMNU_DBG_POST_TRACE_VALUE(NodeEvent_p, 2267 uiNodeId_p, 2268 (((NodeNmtState_p & 2269 0xFF) << 8) 2270 | 2271 kEplNmtCmdResetConfiguration)); 2272 2273 // send NMT reset configuration to CN for activation of configuration 2274 Ret = 2275 EplNmtMnuSendNmtCommand(uiNodeId_p, 2276 kEplNmtCmdResetConfiguration); 2277 2278 break; 2279 } 2280 2281 case kEplNmtMnuIntNodeEventHeartbeat: 2282 { 2283/* 2284 if ((NmtState >= kEplNmtMsPreOperational2) 2285 && ((pNodeInfo->m_wFlags & EPL_NMTMNU_NODE_FLAG_NOT_SCANNED) != 0)) 2286 { 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; 2290 } 2291*/ 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; 2300 } 2301 break; 2302 } 2303 2304 break; 2305 } 2306 2307 case kEplNmtMnuIntNodeEventTimerIdentReq: 2308 { 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; 2323 } 2324 } 2325 2326 break; 2327 } 2328 2329 case kEplNmtMnuIntNodeEventTimerStateMon: 2330 { 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; 2335 2336 // continue with normal StatReq processing 2337 } 2338 2339 case kEplNmtMnuIntNodeEventTimerStatReq: 2340 { 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; 2357 } 2358 } 2359 2360 break; 2361 } 2362 2363 case kEplNmtMnuIntNodeEventTimerLonger: 2364 { 2365 switch (pNodeInfo->m_NodeState) { 2366 case kEplNmtMnuNodeStateConfigured: 2367 { // node should be ReadyToOp but it is not 2368 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; 2379 } 2380 break; 2381 } 2382 2383 break; 2384 } 2385 2386 case kEplNmtMnuNodeStateReadyToOp: 2387 { // CheckCom finished successfully 2388 2389 pNodeInfo->m_NodeState = 2390 kEplNmtMnuNodeStateComChecked; 2391 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; 2401 } 2402 2403 if ((pNodeInfo-> 2404 m_dwNodeCfg & 2405 EPL_NODEASSIGN_MANDATORY_CN) != 2406 0) { 2407 // decrement mandatory slave counter 2408 EplNmtMnuInstance_g. 2409 m_uiMandatorySlaveCount--; 2410 } 2411 if (NmtState != kEplNmtMsReadyToOperate) { 2412 EPL_NMTMNU_DBG_POST_TRACE_VALUE 2413 (NodeEvent_p, uiNodeId_p, 2414 (((NodeNmtState_p & 0xFF) 2415 << 8) 2416 | kEplNmtCmdStartNode)); 2417 2418 // start optional CN 2419 Ret = 2420 EplNmtMnuSendNmtCommand 2421 (uiNodeId_p, 2422 kEplNmtCmdStartNode); 2423 } 2424 break; 2425 } 2426 2427 default: 2428 { 2429 break; 2430 } 2431 } 2432 break; 2433 } 2434 2435 case kEplNmtMnuIntNodeEventNmtCmdSent: 2436 { 2437 u8 bNmtState; 2438 2439 // update expected NMT state with the one that results 2440 // from the sent NMT command 2441 bNmtState = (u8) (NodeNmtState_p & 0xFF); 2442 2443 // write object 0x1F8F NMT_MNNodeExpState_AU8 2444 Ret = 2445 EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 2446 1); 2447 if (Ret != kEplSuccessful) { 2448 goto Exit; 2449 } 2450 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); 2459 2460 // set NMT state change flag 2461 pNodeInfo->m_wFlags |= 2462 EPL_NMTMNU_NODE_FLAG_NMT_CMD_ISSUED; 2463 } 2464 2465 Ret = 2466 EplTimeruModifyTimerMs(&pNodeInfo-> 2467 m_TimerHdlStatReq, 2468 EplNmtMnuInstance_g. 2469 m_ulStatusRequestDelay, 2470 TimerArg); 2471 2472 // finish processing, because NmtState_p is the expected and not the current state 2473 goto Exit; 2474 } 2475 2476 default: 2477 { 2478 break; 2479 } 2480 } 2481 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: 2486 { 2487 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 2488 0) 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; 2502 } 2503 break; 2504 } 2505 // enter PreOp2 2506 Ret = 2507 EplNmtuNmtEvent 2508 (kEplNmtEventAllMandatoryCNIdent); 2509 } 2510 break; 2511 } 2512 2513 case kEplNmtMsPreOperational2: 2514 { 2515 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 2516 0) 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; 2530 } 2531 break; 2532 } 2533 // enter ReadyToOp 2534 Ret = 2535 EplNmtuNmtEvent 2536 (kEplNmtEventEnterReadyToOperate); 2537 } 2538 break; 2539 } 2540 2541 case kEplNmtMsReadyToOperate: 2542 { 2543 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 2544 0) 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; 2558 } 2559 break; 2560 } 2561 // enter Operational 2562 Ret = 2563 EplNmtuNmtEvent 2564 (kEplNmtEventEnterMsOperational); 2565 } 2566 break; 2567 } 2568 2569 case kEplNmtMsOperational: 2570 { 2571 if ((EplNmtMnuInstance_g.m_uiSignalSlaveCount == 2572 0) 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; 2586 } 2587 break; 2588 } 2589 } 2590 break; 2591 } 2592 2593 default: 2594 { 2595 break; 2596 } 2597 } 2598 } 2599 2600 Exit: 2601 return Ret; 2602} 2603 2604//--------------------------------------------------------------------------- 2605// 2606// Function: EplNmtMnuCheckNmtState 2607// 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. 2612// 2613// Parameters: uiNodeId_p = node ID 2614// NodeNmtState_p = NMT state of CN 2615// 2616// Returns: tEplKernel = error code 2617// kEplReject = CN was in wrong state and has been reset 2618// 2619// State: 2620// 2621//--------------------------------------------------------------------------- 2622 2623static tEplKernel EplNmtMnuCheckNmtState(unsigned int uiNodeId_p, 2624 tEplNmtMnuNodeInfo * pNodeInfo_p, 2625 tEplNmtState NodeNmtState_p, 2626 u16 wErrorCode_p, 2627 tEplNmtState LocalNmtState_p) 2628{ 2629 tEplKernel Ret = kEplSuccessful; 2630 tEplObdSize ObdSize; 2631 u8 bNmtState; 2632 u8 bNmtStatePrev; 2633 tEplNmtState ExpNmtState; 2634 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; 2640 } 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); 2645 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; 2655 } 2656 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateReadyToOp; 2657 2658 // update object 0x1F8F NMT_MNNodeExpState_AU8 to ReadyToOp 2659 Ret = EplObduWriteEntry(0x1F8F, uiNodeId_p, &bNmtState, 1); 2660 if (Ret != kEplSuccessful) { 2661 goto Exit; 2662 } 2663 2664 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter 2665 EplNmtMnuInstance_g.m_uiMandatorySlaveCount--; 2666 } 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; 2671 } 2672 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) 2678 | 2679 kEplNmtCmdStartNode)); 2680 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; 2687 } 2688 } 2689 } 2690 2691 } else if ((ExpNmtState == kEplNmtCsReadyToOperate) 2692 && (NodeNmtState_p == kEplNmtCsOperational)) { // CN switched to OPERATIONAL 2693 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateOperational; 2694 2695 if ((pNodeInfo_p->m_dwNodeCfg & EPL_NODEASSIGN_MANDATORY_CN) != 0) { // node is a mandatory CN -> decrement counter 2696 EplNmtMnuInstance_g.m_uiMandatorySlaveCount--; 2697 } 2698 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; 2703 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; 2710 } 2711 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; 2715 } 2716 // -> CN is in wrong NMT state 2717 pNodeInfo_p->m_NodeState = kEplNmtMnuNodeStateUnknown; 2718 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; 2724 } 2725 2726 wErrorCode_p = EPL_E_NMT_WRONG_STATE; 2727 } 2728 2729 BENCHMARK_MOD_07_TOGGLE(9); 2730 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; 2742 } 2743 2744 EPL_NMTMNU_DBG_POST_TRACE_VALUE(0, 2745 uiNodeId_p, 2746 (((NodeNmtState_p & 0xFF) << 8) 2747 | kEplNmtCmdResetNode)); 2748 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; 2758 } 2759 2760 goto Exit; 2761 } 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; 2767 } 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; 2773 } 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; 2784 } 2785 } 2786 2787 Exit: 2788 return Ret; 2789} 2790 2791//--------------------------------------------------------------------------- 2792// 2793// Function: EplNmtMnuReset 2794// 2795// Description: reset internal structures, e.g. timers 2796// 2797// Parameters: void 2798// 2799// Returns: tEplKernel = error code 2800// 2801// State: 2802// 2803//--------------------------------------------------------------------------- 2804 2805static tEplKernel EplNmtMnuReset(void) 2806{ 2807 tEplKernel Ret; 2808 int iIndex; 2809 2810 Ret = EplTimeruDeleteTimer(&EplNmtMnuInstance_g.m_TimerHdlNmtState); 2811 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); 2821 } 2822 2823 return Ret; 2824} 2825 2826#endif // #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) 2827 2828// EOF