//------------------------------------------------------------------------------ static tOplkError timerHdlCycleCb(tTimerEventArg* pEventArg_p) { tOplkError ret = kErrorOk; #if CONFIG_EDRV_CYCLIC_USE_DIAGNOSTICS != FALSE UINT32 cycleTime; UINT32 usedCycleTime; UINT32 spareCycleTime; ULONGLONG startNewCycleTimeStamp; #endif if (pEventArg_p->timerHdl != edrvcyclicInstance_l.timerHdlCycle) { // zombie callback // just exit goto Exit; } #if CONFIG_EDRV_CYCLIC_USE_DIAGNOSTICS != FALSE startNewCycleTimeStamp = target_getCurrentTimestamp(); #endif if (edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferEntry] != NULL) { ret = kErrorEdrvTxListNotFinishedYet; goto Exit; } edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferList] = NULL; // enter new cycle -> switch Tx buffer list edrvcyclicInstance_l.curTxBufferList ^= edrvcyclicInstance_l.maxTxBufferCount; edrvcyclicInstance_l.curTxBufferEntry = edrvcyclicInstance_l.curTxBufferList; if (edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferEntry] == NULL) { ret = kErrorEdrvCurTxListEmpty; goto Exit; } ret = processTxBufferList(); if (ret != kErrorOk) { goto Exit; } if (edrvcyclicInstance_l.pfnSyncCb != NULL) { ret = edrvcyclicInstance_l.pfnSyncCb(); } #if CONFIG_EDRV_CYCLIC_USE_DIAGNOSTICS != FALSE if (edrvcyclicInstance_l.startCycleTimeStamp != 0) { // calculate time diffs of previous cycle cycleTime = (UINT32)(startNewCycleTimeStamp - edrvcyclicInstance_l.startCycleTimeStamp); if (edrvcyclicInstance_l.diagnostics.cycleTimeMin > cycleTime) { edrvcyclicInstance_l.diagnostics.cycleTimeMin = cycleTime; } if (edrvcyclicInstance_l.diagnostics.cycleTimeMax < cycleTime) { edrvcyclicInstance_l.diagnostics.cycleTimeMax = cycleTime; } if (edrvcyclicInstance_l.lastSlotTimeStamp != 0) { usedCycleTime = (UINT32)(edrvcyclicInstance_l.lastSlotTimeStamp - edrvcyclicInstance_l.startCycleTimeStamp); spareCycleTime = (UINT32)(startNewCycleTimeStamp - edrvcyclicInstance_l.lastSlotTimeStamp); if (edrvcyclicInstance_l.diagnostics.usedCycleTimeMin > usedCycleTime) { edrvcyclicInstance_l.diagnostics.usedCycleTimeMin = usedCycleTime; } if (edrvcyclicInstance_l.diagnostics.usedCycleTimeMax < usedCycleTime) { edrvcyclicInstance_l.diagnostics.usedCycleTimeMax = usedCycleTime; } if (edrvcyclicInstance_l.diagnostics.spareCycleTimeMin > spareCycleTime) { edrvcyclicInstance_l.diagnostics.spareCycleTimeMin = spareCycleTime; } if (edrvcyclicInstance_l.diagnostics.spareCycleTimeMax < spareCycleTime) { edrvcyclicInstance_l.diagnostics.spareCycleTimeMax = spareCycleTime; } } else { usedCycleTime = 0; spareCycleTime = cycleTime; } edrvcyclicInstance_l.diagnostics.cycleTimeMeanSum += cycleTime; edrvcyclicInstance_l.diagnostics.usedCycleTimeMeanSum += usedCycleTime; edrvcyclicInstance_l.diagnostics.spareCycleTimeMeanSum += spareCycleTime; edrvcyclicInstance_l.diagnostics.cycleCount++; // sample previous cycle if deviations exceed threshold if ((edrvcyclicInstance_l.diagnostics.sampleNum == 0) || /* sample first cycle for start time */ (abs(cycleTime - edrvcyclicInstance_l.cycleTimeUs * 1000) > EDRV_CYCLIC_SAMPLE_TH_CYCLE_TIME_DIFF_US * 1000) || (spareCycleTime < EDRV_CYCLIC_SAMPLE_TH_SPARE_TIME_US * 1000)) { UINT uiSampleNo = edrvcyclicInstance_l.sampleCount; edrvcyclicInstance_l.diagnostics.aSampleTimeStamp[uiSampleNo] = edrvcyclicInstance_l.startCycleTimeStamp; edrvcyclicInstance_l.diagnostics.aCycleTime[uiSampleNo] = cycleTime; edrvcyclicInstance_l.diagnostics.aUsedCycleTime[uiSampleNo] = usedCycleTime; edrvcyclicInstance_l.diagnostics.aSpareCycleTime[uiSampleNo] = spareCycleTime; edrvcyclicInstance_l.diagnostics.sampleNum++; if (edrvcyclicInstance_l.diagnostics.sampleBufferedNum != EDRV_CYCLIC_SAMPLE_NUM) { edrvcyclicInstance_l.diagnostics.sampleBufferedNum++; } edrvcyclicInstance_l.sampleCount++; if (edrvcyclicInstance_l.sampleCount == EDRV_CYCLIC_SAMPLE_NUM) { edrvcyclicInstance_l.sampleCount = 1; } } } edrvcyclicInstance_l.startCycleTimeStamp = startNewCycleTimeStamp; edrvcyclicInstance_l.lastSlotTimeStamp = 0; #endif Exit: if (ret != kErrorOk) { if (edrvcyclicInstance_l.pfnErrorCb != NULL) { ret = edrvcyclicInstance_l.pfnErrorCb(ret, NULL); } } #if (EDRV_USE_TTTX == TRUE) edrvcyclicInstance_l.nextCycleTime += (edrvcyclicInstance_l.cycleTimeUs * 1000ULL); #endif return ret; }
//------------------------------------------------------------------------------ static tOplkError processTxBufferList(BOOL fCallSyncCb_p) { tOplkError ret = kErrorOk; tEdrvTxBuffer* pTxBuffer = NULL; #if (EDRV_USE_TTTX == TRUE) BOOL fFirstPacket = TRUE; UINT64 launchTime; UINT64 cycleMin; UINT64 cycleMax; UINT64 currentMacTime = 0; #endif #if (EDRV_USE_TTTX == TRUE) edrv_getMacTime(¤tMacTime); if (!edrvcyclicInstance_l.fNextCycleValid) { edrvcyclicInstance_l.nextCycleTime = currentMacTime + EDRV_SHIFT; launchTime = edrvcyclicInstance_l.nextCycleTime; edrvcyclicInstance_l.fNextCycleValid = TRUE; } else { launchTime = edrvcyclicInstance_l.nextCycleTime; if (currentMacTime > launchTime) { ret = kErrorEdrvTxListNotFinishedYet; goto Exit; } } cycleMin = launchTime; cycleMax = launchTime + (edrvcyclicInstance_l.cycleTimeUs * 1000ULL); while ((pTxBuffer = edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferEntry]) != NULL) { if (pTxBuffer == NULL) { ret = kErrorEdrvBufNotExisting; goto Exit; } if (fFirstPacket) { pTxBuffer->launchTime = launchTime; fFirstPacket = FALSE; } else { launchTime = launchTime + (UINT64)pTxBuffer->timeOffsetNs; pTxBuffer->launchTime = launchTime; } if ((pTxBuffer->launchTime - cycleMin) > (cycleMax - cycleMin)) { ret = kErrorEdrvTxListNotFinishedYet; goto Exit; } ret = edrv_sendTxBuffer(pTxBuffer); if (ret != kErrorOk) goto Exit; pTxBuffer->launchTime = 0; edrvcyclicInstance_l.curTxBufferEntry++; if (fCallSyncCb_p) { if (edrvcyclicInstance_l.pfnSyncCb != NULL) { ret = edrvcyclicInstance_l.pfnSyncCb(); } fCallSyncCb_p = FALSE; } } #else while ((pTxBuffer = edrvcyclicInstance_l.ppTxBufferList[edrvcyclicInstance_l.curTxBufferEntry]) != NULL) { if (pTxBuffer->timeOffsetNs == 0) { ret = edrv_sendTxBuffer(pTxBuffer); if (ret != kErrorOk) { goto Exit; } } else { ret = hrestimer_modifyTimer(&edrvcyclicInstance_l.timerHdlSlot, pTxBuffer->timeOffsetNs, timerHdlSlotCb, 0L, FALSE); break; } edrvcyclicInstance_l.curTxBufferEntry++; if (fCallSyncCb_p) { if (edrvcyclicInstance_l.pfnSyncCb != NULL) { ret = edrvcyclicInstance_l.pfnSyncCb(); } fCallSyncCb_p = FALSE; } } #endif Exit: if (ret != kErrorOk) { if (edrvcyclicInstance_l.pfnErrorCb != NULL) { ret = edrvcyclicInstance_l.pfnErrorCb(ret, pTxBuffer); } } return ret; }