//------------------------------------------------------------------------------ UINT32 timestamp_calcTimeDiff(tTimestamp* pTimeStampPrevious_p, tTimestamp* pTimeStampCurrent_p) { UINT32 timeDiffTicks; timeDiffTicks = pTimeStampCurrent_p->timeStamp - pTimeStampPrevious_p->timeStamp; return OMETH_TICKS_2_NS(timeDiffTicks); }
DWORD PUBLIC EplTgtTimeStampTimeDiffNs (tEplTgtTimeStamp* pTimeStampPredecessor_p, tEplTgtTimeStamp* pTimeStampSuccessor_p) { DWORD dwTimeDiffTicks; dwTimeDiffTicks = pTimeStampSuccessor_p->m_dwTimeStamp - pTimeStampPredecessor_p->m_dwTimeStamp; return OMETH_TICKS_2_NS(dwTimeDiffTicks); }
static tEplKernel EdrvCyclicProcessTxBufferList(void) { tEplKernel Ret = kEplSuccessful; tEdrvTxBuffer* pTxBuffer = NULL; DWORD udwAbsTime; //absolute time accumulator BOOL fFirstPkt = TRUE; //flag to identify first packet DWORD udwMacTimeEntry = EDRV_GET_MAC_TIME(); //MAC TIME AT FUNCTION CALL //DWORD udwMacTimePlusOffset = udwMacTimeEntry + EdrvCyclicInstance_l.m_dwTxProcDur; //plus offset DWORD udwCycleMin = 0; //absolute minimum cycle time DWORD udwCycleMax = 0; //absolute maximum cycle time DWORD udwNextOffNs = 0; //next earliest tx time DWORD udwNextTimerIrqNs = EdrvCyclicInstance_l.m_dwCycleLenUs * 1000UL; //time of next timer irq if( EdrvCyclicInstance_l.m_fNextCycleValid == FALSE ) { //use current time + negative shift to set a valid next cycle EdrvCyclicInstance_l.m_dwNextCycleTime = udwMacTimeEntry + OMETH_US_2_TICKS(EDRVCYC_NEG_SHIFT_US); //next timer IRQ correction udwNextTimerIrqNs -= OMETH_TICKS_2_NS(EdrvCyclicInstance_l.m_dwTxProcDur); EdrvCyclicInstance_l.m_fNextCycleValid = TRUE; } else { //cycle is valid, compensate next timer irq //calculate time difference of Next SoC - approx. entry of this function DWORD udwDiff; DWORD udwDiffNs; udwDiff = EdrvCyclicInstance_l.m_dwNextCycleTime - udwMacTimeEntry; if( udwDiff & 0x80000000UL ) { udwDiff = udwMacTimeEntry - EdrvCyclicInstance_l.m_dwNextCycleTime; udwDiffNs = OMETH_TICKS_2_NS(udwDiff); udwNextTimerIrqNs -= (EDRVCYC_NEG_SHIFT_US * 1000UL + udwDiffNs); Ret = EdrvCyclicCycleTimeViolation(udwNextTimerIrqNs); goto CycleDone; } //substract TX buffer list processing from cycle time udwNextTimerIrqNs -= OMETH_TICKS_2_NS(EdrvCyclicInstance_l.m_dwTxProcDur); udwDiffNs = OMETH_TICKS_2_NS(udwDiff); if( udwDiffNs > (EDRVCYC_NEG_SHIFT_US * 1000UL) ) { //time difference is larger negative shift udwNextTimerIrqNs += (udwDiffNs - EDRVCYC_NEG_SHIFT_US * 1000UL); } else if( udwDiffNs > (EDRVCYC_MIN_SHIFT_US * 1000UL) ) { //time difference is shorter than negative shift but larger than minimum udwNextTimerIrqNs -= (EDRVCYC_NEG_SHIFT_US * 1000UL - udwDiffNs); } else { //time difference is too short => cycle violation! udwNextTimerIrqNs -= (EDRVCYC_NEG_SHIFT_US * 1000UL - udwDiffNs); Ret = EdrvCyclicCycleTimeViolation(udwNextTimerIrqNs); goto CycleDone; } } //set accumulator for cycle window calculation udwAbsTime = EdrvCyclicInstance_l.m_dwNextCycleTime; //get cycle start time //set limits to verify if time triggered tx is within cycle // note: otherwise openMAC would be confused udwCycleMin = EdrvCyclicInstance_l.m_dwNextCycleTime; //minimum limit udwCycleMax = EdrvCyclicInstance_l.m_dwNextCycleTime + \ OMETH_US_2_TICKS(EdrvCyclicInstance_l.m_dwCycleLenUs); //maximum limit //loop through TX buffer list while ((pTxBuffer = EdrvCyclicInstance_l.m_paTxBufferList[EdrvCyclicInstance_l.m_uiCurTxBufferEntry]) != NULL) { //compare TX buffer time offset with next offset (considers IPG and last packet length) //note: otherwise openMAC is confused if time-trig TX starts within other time-trig TX! if( (fFirstPkt == FALSE) && (udwNextOffNs > pTxBuffer->m_dwTimeOffsetNs) ) { udwAbsTime += OMETH_NS_2_TICKS(udwNextOffNs); //accumulate offset } else { udwAbsTime += OMETH_NS_2_TICKS(pTxBuffer->m_dwTimeOffsetNs); //accumulate offset } fFirstPkt = FALSE; //first packet is surely out... //verify if packet TX start time is within cycle window if( (udwAbsTime - udwCycleMin) > (udwCycleMax - udwCycleMin) ) { //packet is outside of the window Ret = EdrvCyclicCycleTimeViolation(udwNextTimerIrqNs); goto CycleDone; } //pTxBuffer->m_dwTimeOffsetNs = udwAbsTime | 1; //lowest bit enables time triggered send //set the absolute TX start time, and OR the lowest bit to give Edrv a hint pTxBuffer->m_dwTimeOffsetAbsTk = udwAbsTime | 1; //lowest bit enables time triggered send Ret = EdrvSendTxMsg(pTxBuffer); if (Ret != kEplSuccessful) { goto Exit; } //set the absolute TX start time to zero // -> If the TX buffer is reused as manual TX, EdrvSendTxMsg is not confused! pTxBuffer->m_dwTimeOffsetAbsTk = 0; //calculate the length of the sent packet, add IPG and thus know the next earliest TX time { DWORD udwLength = pTxBuffer->m_uiTxMsgLen; //consider padding! if( udwLength < 60UL ) { udwLength = 60UL; } // ( pre + header + payload + padding + crc ) * 80ns/byte + 960ns = next TX time udwNextOffNs = EDRVCYC_BYTETIME_NS * (EDRVCYC_PREAMB_SIZE + ETH_CRC_SIZE + udwLength) + EDRVCYC_IPG_NS; } //switch to next TX buffer EdrvCyclicInstance_l.m_uiCurTxBufferEntry++; } //set up next timer interrupt Ret = EplTimerHighReskModifyTimerNs(&EdrvCyclicInstance_l.m_TimerHdlCycle, udwNextTimerIrqNs, EdrvCyclicCbTimerCycle, 0L, FALSE); if (Ret != kEplSuccessful) { PRINTF("%s: EplTimerHighReskModifyTimerNs ret=0x%X\n", __func__, Ret); goto Exit; } CycleDone: //calculate next cycle EdrvCyclicInstance_l.m_dwNextCycleTime += OMETH_US_2_TICKS(EdrvCyclicInstance_l.m_dwCycleLenUs); Exit: return Ret; }