tEplKernel PUBLIC EplLinCbSync(void) { tEplKernel EplRet = kEplSuccessful; int iErr; // check if user process waits for sync if (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL) { // pass control to application, i.e. EplApiProcessImageExchangeIn() atomic_set(&AtomicSyncState_g, EVENT_STATE_READY); wake_up_interruptible(&WaitQueuePI_In_g); // now, the application processes the sync event // wait for call of EplApiProcessImageExchangeOut() iErr = wait_event_interruptible(WaitQueueCbSync_g, (atomic_read(&AtomicSyncState_g) == EVENT_STATE_IOCTL) || (atomic_read(&AtomicSyncState_g) == EVENT_STATE_TERM)); if ((iErr != 0) || (atomic_read(&AtomicEventState_g) == EVENT_STATE_IOCTL)) { // waiting was interrupted by signal or application called wrong function EplRet = kEplShutdown; } } else { // application is currently not waiting for sync // continue without interruption // TPDO are set valid by caller (i.e. EplEventkProcess()) } TGT_DBG_SIGNAL_TRACE_POINT(1); return EplRet; }
static void EplEventuRxSignalHandlerCb ( tShbInstance pShbRxInstance_p, unsigned long ulDataSize_p) { tEplEvent *pEplEvent; tShbError ShbError; BYTE* pabDataBuffer; TGT_DBG_SIGNAL_TRACE_POINT(21); pabDataBuffer = &EplEventuInstance_g.m_abRxBuffer[0]; // copy data from event queue ShbError = ShbCirReadDataBlock (pShbRxInstance_p, pabDataBuffer, sizeof(EplEventuInstance_g.m_abRxBuffer), &ulDataSize_p); if(ShbError != kShbOk) { EplEventuPostError(kEplEventSourceEventu, kEplEventReadError, sizeof (ShbError), &ShbError); // error goto exit goto Exit; } // resolve the pointer to the event structure pEplEvent = (tEplEvent *) pabDataBuffer; // set Datasize pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent)); if(pEplEvent->m_uiSize > 0) { // set pointer to argument pEplEvent->m_pArg = &pabDataBuffer[sizeof(tEplEvent)]; } else { //set pointer to NULL pEplEvent->m_pArg = NULL; } BENCHMARK_MOD_28_SET(1); // call processfunction EplEventuProcess(pEplEvent); BENCHMARK_MOD_28_RESET(1); Exit: return; }
static void EplEventkRxSignalHandlerCb ( tShbInstance pShbRxInstance_p, unsigned long ulDataSize_p) { tEplEvent *pEplEvent; tShbError ShbError; //unsigned long ulBlockCount; //unsigned long ulDataSize; BYTE abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; // d.k.: abDataBuffer contains the complete tEplEvent structure // and behind this the argument TGT_DBG_SIGNAL_TRACE_POINT(20); BENCHMARK_MOD_27_RESET(0); // copy data from event queue ShbError = ShbCirReadDataBlock (pShbRxInstance_p, &abDataBuffer[0], sizeof(abDataBuffer), &ulDataSize_p); if(ShbError != kShbOk) { // error goto exit goto Exit; } // resolve the pointer to the event structure pEplEvent = (tEplEvent *) abDataBuffer; // set Datasize pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent)); if(pEplEvent->m_uiSize > 0) { // set pointer to argument pEplEvent->m_pArg = &abDataBuffer[sizeof(tEplEvent)]; } else { //set pointer to NULL pEplEvent->m_pArg = NULL; } BENCHMARK_MOD_27_SET(0); // call processfunction EplEventkProcess(pEplEvent); Exit: return; }
tEplKernel PUBLIC EplEventkProcess(tEplEvent* pEvent_p) { tEplKernel Ret; tEplEventSource EventSource; Ret = kEplSuccessful; #if (EPL_USE_SHAREDBUFF != FALSE) \ && (EPL_EVENT_USE_KERNEL_QUEUE != FALSE) // error handling if event queue is full if (EplEventkInstance_g.m_uiUserToKernelFullCount > 0) { // UserToKernel event queue has run out of space -> kEplNmtEventInternComError #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) tEplEvent Event; tEplNmtEvent NmtEvent; #endif // directly call NMTk process function, because event queue is full #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) NmtEvent = kEplNmtEventInternComError; Event.m_EventSink = kEplEventSinkNmtk; Event.m_NetTime.m_dwNanoSec = 0; Event.m_NetTime.m_dwSec = 0; Event.m_EventType = kEplEventTypeNmtEvent; Event.m_pArg = &NmtEvent; Event.m_uiSize = sizeof(NmtEvent); Ret = EplNmtkProcess(&Event); #endif // NMT state machine changed to reset (i.e. NMT_GS_RESET_COMMUNICATION) // now, it is safe to reset the counter and empty the event queue ShbCirResetBuffer (EplEventkInstance_g.m_pShbUserToKernelInstance, 1000, NULL); EplEventkInstance_g.m_uiUserToKernelFullCount = 0; TGT_DBG_SIGNAL_TRACE_POINT(22); // also discard the current event (it doesn't matter if we lose another event) goto Exit; } #endif // check m_EventSink switch(pEvent_p->m_EventSink) { // NMT-Kernel-Modul case kEplEventSinkNmtk: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) Ret = EplNmtkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceNmtk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif BENCHMARK_MOD_27_RESET(0); #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) if ((pEvent_p->m_EventType == kEplEventTypeNmtEvent) && (*((tEplNmtEvent*)pEvent_p->m_pArg) == kEplNmtEventDllCeSoa)) { BENCHMARK_MOD_27_SET(0); #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) // forward SoA event to DLLk module for cycle preprocessing Ret = EplDllkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceDllk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif BENCHMARK_MOD_27_RESET(0); } #endif break; } // events for Dllk module case kEplEventSinkDllk: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceDllk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif break; } // events for DllkCal module case kEplEventSinkDllkCal: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkCalProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceDllk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif break; } #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) // events for PDO CAL module case kEplEventSinkPdokCal: { Ret = EplPdokCalProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourcePdok; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } break; } #endif #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) // events for Error handler module case kEplEventSinkErrk: { // only call error handler if DLL is present Ret = EplErrorHandlerkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceErrk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } break; } #endif // unknown sink default: { Ret = kEplEventUnknownSink; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(pEvent_p->m_EventSink), &pEvent_p->m_EventSink); } } // end of switch(pEvent_p->m_EventSink) #if (EPL_USE_SHAREDBUFF != FALSE) \ && (EPL_EVENT_USE_KERNEL_QUEUE != FALSE) Exit: #endif return Ret; }
static void EplEventuRxSignalHandlerCb(tShbInstance pShbRxInstance_p, unsigned long ulDataSize_p) { tEplEvent *pEplEvent; tShbError ShbError; //unsigned long ulBlockCount; //unsigned long ulDataSize; u8 abDataBuffer[sizeof(tEplEvent) + EPL_MAX_EVENT_ARG_SIZE]; // d.k.: abDataBuffer contains the complete tEplEvent structure // and behind this the argument TGT_DBG_SIGNAL_TRACE_POINT(21); // d.k. not needed because it is already done in SharedBuff /* do { BENCHMARK_MOD_28_SET(1); // 4 µs until reset // get messagesize ShbError = ShbCirGetReadDataSize (pShbRxInstance_p, &ulDataSize); if(ShbError != kShbOk) { // error goto exit goto Exit; } BENCHMARK_MOD_28_RESET(1); // 14 µs until set */ // copy data from event queue ShbError = ShbCirReadDataBlock(pShbRxInstance_p, &abDataBuffer[0], sizeof(abDataBuffer), &ulDataSize_p); if (ShbError != kShbOk) { // error goto exit goto Exit; } // resolve the pointer to the event structure pEplEvent = (tEplEvent *) abDataBuffer; // set Datasize pEplEvent->m_uiSize = (ulDataSize_p - sizeof(tEplEvent)); if (pEplEvent->m_uiSize > 0) { // set pointer to argument pEplEvent->m_pArg = &abDataBuffer[sizeof(tEplEvent)]; } else { //set pointer to NULL pEplEvent->m_pArg = NULL; } BENCHMARK_MOD_28_SET(1); // call processfunction EplEventuProcess(pEplEvent); BENCHMARK_MOD_28_RESET(1); // read number of left messages to process // d.k. not needed because it is already done in SharedBuff /* ShbError = ShbCirGetReadBlockCount (pShbRxInstance_p, &ulBlockCount); if (ShbError != kShbOk) { // error goto exit goto Exit; } } while (ulBlockCount > 0); */ Exit: return; }
//------------------------------------------------------------------------------ tOplkError dllknode_setupAsyncPhase(tNmtState nmtState_p, UINT nextTxBufferOffset_p, UINT32 nextTimeOffsetNs_p, UINT* pIndex_p) { tOplkError ret = kErrorOk; tEdrvTxBuffer* pTxBuffer; pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_SOA + nextTxBufferOffset_p]; pTxBuffer->timeOffsetNs = nextTimeOffsetNs_p; // switch SoAReq buffer dllkInstance_g.syncLastSoaReq++; if (dllkInstance_g.syncLastSoaReq >= DLLK_SOAREQ_COUNT) { dllkInstance_g.syncLastSoaReq = 0; } // $$$ d.k. fEnableInvitation_p = ((NmtState_p != kNmtMsPreOperational1) || // (dllkInstance_g.cycleCount >= C_DLL_PREOP1_START_CYCLES)) // currently, processSync is not called in PreOp1 ret = dllkframe_updateFrameSoa(pTxBuffer, nmtState_p, TRUE, dllkInstance_g.syncLastSoaReq); dllkInstance_g.ppTxBufferList[*pIndex_p] = pTxBuffer; (*pIndex_p)++; // check if we are invited in SoA if (dllkInstance_g.aLastTargetNodeId[dllkInstance_g.syncLastSoaReq] == dllkInstance_g.dllConfigParam.nodeId) { // Note: The Tx buffers exist / are ready! // This is checked in dllk_updateFrameSoa() switch (dllkInstance_g.aLastReqServiceId[dllkInstance_g.syncLastSoaReq]) { case kDllReqServiceStatus: // StatusRequest pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_STATUSRES + dllkInstance_g.curTxBufferOffsetStatusRes]; dllkInstance_g.ppTxBufferList[*pIndex_p] = pTxBuffer; (*pIndex_p)++; TGT_DBG_SIGNAL_TRACE_POINT(8); break; case kDllReqServiceIdent: // IdentRequest pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_IDENTRES + dllkInstance_g.curTxBufferOffsetIdentRes]; dllkInstance_g.ppTxBufferList[*pIndex_p] = pTxBuffer; (*pIndex_p)++; TGT_DBG_SIGNAL_TRACE_POINT(7); break; case kDllReqServiceNmtRequest: // NmtRequest pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_NMTREQ + dllkInstance_g.curTxBufferOffsetNmtReq]; dllkInstance_g.ppTxBufferList[*pIndex_p] = pTxBuffer; (*pIndex_p)++; dllkInstance_g.curTxBufferOffsetNmtReq ^= 1; break; case kDllReqServiceUnspecified: // unspecified invite pTxBuffer = &dllkInstance_g.pTxBuffer[DLLK_TXFRAME_NONPLK + dllkInstance_g.curTxBufferOffsetNonPlk]; dllkInstance_g.ppTxBufferList[*pIndex_p] = pTxBuffer; (*pIndex_p)++; dllkInstance_g.curTxBufferOffsetNonPlk ^= 1; break; default: break; } // Asnd frame will be sent, remove the request dllkInstance_g.aLastReqServiceId[dllkInstance_g.syncLastSoaReq] = kDllReqServiceNo; } return ret; }
tEplKernel EplEventkProcess(tEplEvent *pEvent_p) { tEplKernel Ret; tEplEventSource EventSource; Ret = kEplSuccessful; // error handling if event queue is full if (EplEventkInstance_g.m_uiUserToKernelFullCount > 0) { // UserToKernel event queue has run out of space -> kEplNmtEventInternComError #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) tEplEvent Event; tEplNmtEvent NmtEvent; #endif #ifndef EPL_NO_FIFO tShbError ShbError; #endif // directly call NMTk process function, because event queue is full #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) NmtEvent = kEplNmtEventInternComError; Event.m_EventSink = kEplEventSinkNmtk; Event.m_NetTime.m_dwNanoSec = 0; Event.m_NetTime.m_dwSec = 0; Event.m_EventType = kEplEventTypeNmtEvent; Event.m_pArg = &NmtEvent; Event.m_uiSize = sizeof(NmtEvent); Ret = EplNmtkProcess(&Event); #endif // NMT state machine changed to reset (i.e. NMT_GS_RESET_COMMUNICATION) // now, it is safe to reset the counter and empty the event queue #ifndef EPL_NO_FIFO ShbError = ShbCirResetBuffer(EplEventkInstance_g. m_pShbUserToKernelInstance, 1000, NULL); #endif EplEventkInstance_g.m_uiUserToKernelFullCount = 0; TGT_DBG_SIGNAL_TRACE_POINT(22); // also discard the current event (it doesn't matter if we lose another event) goto Exit; } // check m_EventSink switch (pEvent_p->m_EventSink) { case kEplEventSinkSync: { if (EplEventkInstance_g.m_pfnCbSync != NULL) { Ret = EplEventkInstance_g.m_pfnCbSync(); if (Ret == kEplSuccessful) { #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) // mark TPDOs as valid Ret = EplPdokCalSetTpdosValid(TRUE); #endif } else if ((Ret != kEplReject) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceSyncCb; // Error event for API layer EplEventkPostError (kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } } break; } // NMT-Kernel-Modul case kEplEventSinkNmtk: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMTK)) != 0) Ret = EplNmtkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceNmtk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) if ((pEvent_p->m_EventType == kEplEventTypeNmtEvent) && ((*((tEplNmtEvent *) pEvent_p->m_pArg) == kEplNmtEventDllCeSoa) #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0) || (*((tEplNmtEvent *) pEvent_p->m_pArg) == kEplNmtEventDllMeSoaSent) #endif )) { // forward SoA event to error handler Ret = EplErrorHandlerkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceErrk; // Error event for API layer EplEventkPostError (kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) // forward SoA event to PDO module pEvent_p->m_EventType = kEplEventTypePdoSoa; Ret = EplPdokProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourcePdok; // Error event for API layer EplEventkPostError (kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif } break; #endif } // events for Dllk module case kEplEventSinkDllk: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceDllk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif break; } // events for DllkCal module case kEplEventSinkDllkCal: { #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplDllkCalProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceDllk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif break; } // case kEplEventSinkPdok: { // PDO-Module #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0) Ret = EplPdokProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourcePdok; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } #endif break; } // events for Error handler module case kEplEventSinkErrk: { // only call error handler if DLL is present #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) != 0) Ret = EplErrorHandlerkProcess(pEvent_p); if ((Ret != kEplSuccessful) && (Ret != kEplShutdown)) { EventSource = kEplEventSourceErrk; // Error event for API layer EplEventkPostError(kEplEventSourceEventk, Ret, sizeof(EventSource), &EventSource); } break; #endif } // unknown sink default: { Ret = kEplEventUnknownSink; } } // end of switch(pEvent_p->m_EventSink) Exit: return Ret; }