//------------------------------------------------------------------------------ static tOplkError cbCnPresFallbackTimeout(void) { tOplkError ret = kErrorOk; tNmtState nmtState; UINT32 arg; TGT_DLLK_DECLARE_FLAGS; TGT_DLLK_ENTER_CRITICAL_SECTION(); nmtState = dllkInstance_g.nmtState; if (nmtState <= kNmtGsResetConfiguration) goto Exit; ret = dllkframe_presChainingDisable(); Exit: if (ret != kErrorOk) { BENCHMARK_MOD_02_TOGGLE(7); arg = dllkInstance_g.dllState | (kNmtEventDllCeFrameTimeout << 8); // Error event for API layer ret = eventk_postError(kEventSourceDllk, ret, sizeof(arg), &arg); } TGT_DLLK_LEAVE_CRITICAL_SECTION(); return ret; }
//------------------------------------------------------------------------------ static tOplkError processNmtStateChange(tNmtState newNmtState_p, tNmtState oldNmtState_p, tNmtEvent nmtEvent_p) { tOplkError ret = kErrorOk; #if !defined(CONFIG_INCLUDE_NMT_RMN) UNUSED_PARAMETER(nmtEvent_p); #endif switch (newNmtState_p) { case kNmtGsOff: case kNmtGsInitialising: dllkInstance_g.socTime.relTime = 0; // set EC flag in Flag 1, so the MN can detect a reboot and // will initialize the Error Signaling. dllkInstance_g.flag1 = PLK_FRAME_FLAG1_EC; dllkInstance_g.nmtState = newNmtState_p; if (oldNmtState_p > kNmtGsResetConfiguration) { ret = dllknode_cleanupLocalNode(oldNmtState_p); // deinitialize DLL and destroy frames } break; case kNmtGsResetApplication: case kNmtGsResetCommunication: case kNmtGsResetConfiguration: // at first, update NMT state in instance structure to disable frame processing dllkInstance_g.nmtState = newNmtState_p; if (oldNmtState_p > kNmtGsResetConfiguration) { ret = dllknode_cleanupLocalNode(oldNmtState_p); // deinitialize DLL and destroy frames } break; // node listens for POWERLINK frames and check timeout case kNmtMsNotActive: case kNmtCsNotActive: case kNmtRmsNotActive: if (oldNmtState_p <= kNmtGsResetConfiguration) { // setup DLL and create frames ret = dllknode_setupLocalNode(newNmtState_p); } break; // node processes only async frames case kNmtCsPreOperational1: #if CONFIG_TIMER_USE_HIGHRES != FALSE if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlCycle)) != kErrorOk) return ret; #endif #if defined(CONFIG_INCLUDE_NMT_RMN) if (dllkInstance_g.fRedundancy) { ret = edrvcyclic_stopCycle(FALSE); if (ret != kErrorOk) return ret; hrestimer_modifyTimer(&dllkInstance_g.timerHdlSwitchOver, dllkInstance_g.dllConfigParam.reducedSwitchOverTimeMn * 1000ULL, dllk_cbTimerSwitchOver, 0L, FALSE); } #endif // deactivate sync generation if ((ret = controlTimeSync(FALSE)) != kErrorOk) return ret; #if (CONFIG_DLL_PROCESS_SYNC == DLL_PROCESS_SYNC_ON_TIMER) if ((ret = synctimer_stopSync()) != kErrorOk) return ret; #endif #if CONFIG_DLL_PRES_CHAINING_CN != FALSE if ((ret = dllkframe_presChainingDisable()) != kErrorOk) return ret; #endif // update IdentRes and StatusRes ret = dllkframe_updateFrameStatusRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_STATUSRES + dllkInstance_g.curTxBufferOffsetStatusRes], newNmtState_p); if (ret != kErrorOk) return ret; ret = dllkframe_updateFrameIdentRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_IDENTRES + dllkInstance_g.curTxBufferOffsetIdentRes], newNmtState_p); if (ret != kErrorOk) return ret; // enable IdentRes and StatusRes #if (CONFIG_EDRV_AUTO_RESPONSE != FALSE) // enable corresponding Rx filter dllkInstance_g.aFilter[DLLK_FILTER_SOA_STATREQ].fEnable = TRUE; ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_SOA_STATREQ, EDRV_FILTER_CHANGE_STATE); if (ret != kErrorOk) return ret; // enable corresponding Rx filter dllkInstance_g.aFilter[DLLK_FILTER_SOA_IDREQ].fEnable = TRUE; ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_SOA_IDREQ, EDRV_FILTER_CHANGE_STATE); if (ret != kErrorOk) return ret; #if CONFIG_DLL_PRES_CHAINING_CN != FALSE // enable SyncReq Rx filter dllkInstance_g.aFilter[DLLK_FILTER_SOA_SYNCREQ].fEnable = TRUE; ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_SOA_SYNCREQ, EDRV_FILTER_CHANGE_STATE); if (ret != kErrorOk) return ret; #endif #endif // update PRes (for sudden changes to PreOp2) ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES + (dllkInstance_g.curTxBufferOffsetCycle ^ 1)], kNmtCsPreOperational2); if (ret != kErrorOk) return ret; ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES + dllkInstance_g.curTxBufferOffsetCycle], kNmtCsPreOperational2); if (ret != kErrorOk) return ret; // enable PRes (for sudden changes to PreOp2) #if (CONFIG_EDRV_AUTO_RESPONSE != FALSE) // enable corresponding Rx filter dllkInstance_g.aFilter[DLLK_FILTER_PREQ].fEnable = TRUE; dllkInstance_g.aFilter[DLLK_FILTER_PREQ].pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES]; ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_PREQ, EDRV_FILTER_CHANGE_STATE | EDRV_FILTER_CHANGE_AUTO_RESPONSE); if (ret != kErrorOk) return ret; #endif break; // node processes isochronous and asynchronous frames case kNmtCsPreOperational2: // signal update of IdentRes and StatusRes on SoA dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH; // enable PRes (necessary if coming from Stopped) #if (CONFIG_EDRV_AUTO_RESPONSE != FALSE) // enable corresponding Rx filter dllkInstance_g.aFilter[DLLK_FILTER_PREQ].fEnable = TRUE; dllkInstance_g.aFilter[DLLK_FILTER_PREQ].pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES]; ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_PREQ, EDRV_FILTER_CHANGE_STATE | EDRV_FILTER_CHANGE_AUTO_RESPONSE); if (ret != kErrorOk) return ret; #endif break; #if defined (CONFIG_INCLUDE_NMT_MN) case kNmtMsPreOperational1: #if CONFIG_TIMER_USE_HIGHRES != FALSE ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlCycle); if (ret != kErrorOk) return ret; #endif /// deactivate sync generation if ((ret = controlTimeSync(FALSE)) != kErrorOk) return ret; ret = edrvcyclic_stopCycle(FALSE); if (ret != kErrorOk) return ret; #if defined(CONFIG_INCLUDE_NMT_RMN) if (dllkInstance_g.fRedundancy) { if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlSwitchOver)) != kErrorOk) return ret; if (oldNmtState_p == kNmtRmsNotActive) { // send AMNI ret = edrv_sendTxBuffer(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_AMNI]); if (ret != kErrorOk) return ret; } // initialize cycle counter if (dllkInstance_g.dllConfigParam.fAsyncOnly == FALSE) { dllkInstance_g.cycleCount = 0; } else { // it is an async-only CN -> fool changeState() to think that PRes was not expected dllkInstance_g.cycleCount = 1; } } #endif // update IdentRes and StatusRes ret = dllkframe_updateFrameIdentRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_IDENTRES + dllkInstance_g.curTxBufferOffsetIdentRes], newNmtState_p); if (ret != kErrorOk) return ret; ret = dllkframe_updateFrameStatusRes(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_STATUSRES + dllkInstance_g.curTxBufferOffsetStatusRes], newNmtState_p); break; case kNmtMsReadyToOperate: /// activate sync generation if ((ret = controlTimeSync(TRUE)) != kErrorOk) return ret; break; case kNmtMsPreOperational2: case kNmtMsOperational: // signal update of IdentRes and StatusRes on SoA dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH; #if defined(CONFIG_INCLUDE_NMT_RMN) if (dllkInstance_g.fRedundancy && (oldNmtState_p == kNmtCsOperational)) { dllkInstance_g.dllState = kDllMsWaitSocTrig; if ((ret = hrestimer_deleteTimer(&dllkInstance_g.timerHdlSwitchOver)) != kErrorOk) return ret; dllkInstance_g.socTime.relTime += dllkInstance_g.dllConfigParam.cycleLen; // initialize SoAReq number for ProcessSync (cycle preparation) dllkInstance_g.syncLastSoaReq = dllkInstance_g.curLastSoaReq; // trigger synchronous task for cycle preparation dllkInstance_g.fSyncProcessed = TRUE; ret = dllk_postEvent(kEventTypeSync); } #endif break; #endif case kNmtCsReadyToOperate: /// activate sync generation if ((ret = controlTimeSync(TRUE)) != kErrorOk) return ret; // signal update of IdentRes and StatusRes on SoA dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH; break; case kNmtCsOperational: // signal update of IdentRes and StatusRes on SoA dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH; #if defined(CONFIG_INCLUDE_NMT_RMN) if (dllkInstance_g.fRedundancy && (oldNmtState_p == kNmtMsOperational)) { dllkInstance_g.dllState = kDllCsWaitSoc; ret = edrvcyclic_stopCycle(TRUE); if (ret != kErrorOk) return ret; hrestimer_modifyTimer(&dllkInstance_g.timerHdlSwitchOver, dllkInstance_g.dllConfigParam.switchOverTimeMn * 1000ULL, dllk_cbTimerSwitchOver, 0L, FALSE); if ((nmtEvent_p == kNmtEventGoToStandby) || (nmtEvent_p == kNmtEventGoToStandbyDelayed)) { // save event, so cbCyclicError can start switch-over timeout // appropriately dllkInstance_g.nmtEventGoToStandby = nmtEvent_p; } } #endif break; // node stopped by MN case kNmtCsStopped: // signal update of IdentRes and StatusRes on SoA dllkInstance_g.updateTxFrame = DLLK_UPDATE_BOTH; #if (CONFIG_EDRV_AUTO_RESPONSE != FALSE) // disable auto-response for PRes filter dllkInstance_g.aFilter[DLLK_FILTER_PREQ].pTxBuffer = NULL; ret = edrv_changeRxFilter(dllkInstance_g.aFilter, DLLK_FILTER_COUNT, DLLK_FILTER_PREQ, EDRV_FILTER_CHANGE_AUTO_RESPONSE); if (ret != kErrorOk) return ret; #endif // update PRes ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES + (dllkInstance_g.curTxBufferOffsetCycle ^ 1)], newNmtState_p); if (ret != kErrorOk) return ret; ret = dllkframe_updateFramePres(&dllkInstance_g.pTxBuffer[DLLK_TXFRAME_PRES + dllkInstance_g.curTxBufferOffsetCycle], newNmtState_p); if (ret != kErrorOk) return ret; break; // no POWERLINK cycle -> normal ethernet communication case kNmtMsBasicEthernet: case kNmtCsBasicEthernet: // Fill Async Tx Buffer, because state BasicEthernet was entered ret = processFillTx(kDllAsyncReqPrioGeneric, newNmtState_p); if (ret != kErrorOk) return ret; break; default: return kErrorNmtInvalidState; break; } // update NMT state in instance structure. This is done after updating all // Tx frames, so no frame will be transmitted by callback function, when it // is not up to date yet. dllkInstance_g.nmtState = newNmtState_p; return ret; }